diff --git a/BUILD.md b/BUILD.md index 523cc523e..95c3f997f 100644 --- a/BUILD.md +++ b/BUILD.md @@ -1,7 +1,7 @@ # Building Eclair ## Requirements -- [Java Development Kit](http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html) 1.8 +- [Java Development Kit](http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html) 1.8u161 or newer - [Maven](https://maven.apache.org/download.cgi) 3.3.x - [Inno Setup](http://www.jrsoftware.org/isdl.php) 5.5.9 (optional, if you want to generate the windows installer) diff --git a/LICENSE b/LICENSE index 2efa8d40f..414b50de0 100644 --- a/LICENSE +++ b/LICENSE @@ -186,7 +186,7 @@ Apache License same "printed page" as the copyright notice for easier identification within third-party archives. - Copyright 2014 ACINQ SAS + Copyright 2018 ACINQ SAS Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/README.md b/README.md index ebf175cc7..7f4928786 100644 --- a/README.md +++ b/README.md @@ -27,11 +27,11 @@ Please see the latest [release note](https://github.com/ACINQ/eclair/releases) f ## Installation -:warning: **Those are valid for the most up-to-date, unreleased, version of eclair. Here are the [instructions for Eclair 0.2-alpha10](https://github.com/ACINQ/eclair/blob/v0.2-alpha10/README.md#installation)**. +:warning: **Those are valid for the most up-to-date, unreleased, version of eclair. Here are the [instructions for Eclair 0.2-alpha11](https://github.com/ACINQ/eclair/blob/v0.2-alpha11/README.md#installation)**. ### Configuring Bitcoin Core -Eclair needs a _synchronized_, _segwit-ready_, **_zeromq-enabled_**, _wallet-enabled_, _non-pruning_, _tx-indexing_ [Bitcoin Core](https://github.com/bitcoin/bitcoin) node. This means that on Windows you will need Bitcoin Core 0.14+. +Eclair needs a _synchronized_, _segwit-ready_, **_zeromq-enabled_**, _wallet-enabled_, _non-pruning_, _tx-indexing_ [Bitcoin Core](https://github.com/bitcoin/bitcoin) node. This means that on Windows you will need Bitcoin Core 0.14+. We highly recommend that you use Bitcoin Core 0.16 and will soon drop support for older versions. Run bitcoind with the following minimal `bitcoin.conf`: ``` @@ -147,6 +147,8 @@ java -Declair.datadir=/tmp/node1 -jar eclair-node-gui--.jar allupdates | nodeId | list all channels updates for this nodeId receive | description | generate a payment request without a required amount (can be useful for donations) receive | amountMsat, description | generate a payment request for a given amount + checkinvoice | paymentRequest | returns node, amount and payment hash in an invoice/paymentRequest + findroute | paymentRequest|nodeId | given a payment request or nodeID checks if there is a valid payment route returns JSON with attempts, nodes and channels of route send | amountMsat, paymentHash, nodeId | send a payment to a lightning node send | paymentRequest | send a payment to a lightning node using a BOLT11 payment request send | paymentRequest, amountMsat | send a payment to a lightning node using a BOLT11 payment request and a custom amount diff --git a/eclair-core/pom.xml b/eclair-core/pom.xml index 147411131..a9bf10a6f 100644 --- a/eclair-core/pom.xml +++ b/eclair-core/pom.xml @@ -1,4 +1,20 @@ + + 4.0.0 diff --git a/eclair-core/src/main/resources/reference.conf b/eclair-core/src/main/resources/reference.conf index cd64212ce..0eb7adefc 100644 --- a/eclair-core/src/main/resources/reference.conf +++ b/eclair-core/src/main/resources/reference.conf @@ -56,7 +56,7 @@ eclair { mindepth-blocks = 2 expiry-delta-blocks = 144 - fee-base-msat = 10000 + fee-base-msat = 1000 fee-proportional-millionths = 100 // fee charged per transferred satoshi in millionths of a satoshi (100 = 0.01%) // maximum local vs remote feerate mismatch; 1.0 means 100% @@ -77,4 +77,5 @@ eclair { payment-handler = "local" payment-request-expiry = 1 hour // default expiry for payment requests generated by this node max-pending-payment-requests = 10000000 + max-payment-fee = 0.03 // max total fee for outgoing payments, in percentage: sending a payment will not be attempted if the cheapest route found is more expensive than that } \ No newline at end of file diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/CoinUtils.scala b/eclair-core/src/main/scala/fr/acinq/eclair/CoinUtils.scala index d26284145..e6fbe9656 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/CoinUtils.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/CoinUtils.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair import java.text.DecimalFormat diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/DBCompatChecker.scala b/eclair-core/src/main/scala/fr/acinq/eclair/DBCompatChecker.scala index 5000f808c..fa05f0770 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/DBCompatChecker.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/DBCompatChecker.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair import grizzled.slf4j.Logging diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/FSMDiagnosticActorLogging.scala b/eclair-core/src/main/scala/fr/acinq/eclair/FSMDiagnosticActorLogging.scala index 251001c44..ff2200b32 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/FSMDiagnosticActorLogging.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/FSMDiagnosticActorLogging.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair import akka.actor.{Actor, FSM} diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/Features.scala b/eclair-core/src/main/scala/fr/acinq/eclair/Features.scala index 8081a119d..abecc33e0 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/Features.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/Features.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/Globals.scala b/eclair-core/src/main/scala/fr/acinq/eclair/Globals.scala index bd09fb289..c2467493d 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/Globals.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/Globals.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair import java.util.concurrent.atomic.{AtomicLong, AtomicReference} diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/HttpHelper.scala b/eclair-core/src/main/scala/fr/acinq/eclair/HttpHelper.scala index 990ed2db6..dcb8b4c46 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/HttpHelper.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/HttpHelper.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair import com.ning.http.client.{AsyncCompletionHandler, AsyncHttpClient, AsyncHttpClientConfig, Response} diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/NodeParams.scala b/eclair-core/src/main/scala/fr/acinq/eclair/NodeParams.scala index ddc45f308..8d6a361d4 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/NodeParams.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/NodeParams.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair import java.io.File @@ -56,7 +72,8 @@ case class NodeParams(keyManager: KeyManager, channelExcludeDuration: FiniteDuration, watcherType: WatcherType, paymentRequestExpiry: FiniteDuration, - maxPendingPaymentRequests: Int) { + maxPendingPaymentRequests: Int, + maxPaymentFee: Double) { val privateKey = keyManager.nodeKey.privateKey val nodeId = keyManager.nodeId } @@ -166,6 +183,7 @@ object NodeParams { channelExcludeDuration = FiniteDuration(config.getDuration("channel-exclude-duration", TimeUnit.SECONDS), TimeUnit.SECONDS), watcherType = watcherType, paymentRequestExpiry = FiniteDuration(config.getDuration("payment-request-expiry", TimeUnit.SECONDS), TimeUnit.SECONDS), - maxPendingPaymentRequests = config.getInt("max-pending-payment-requests")) + maxPendingPaymentRequests = config.getInt("max-pending-payment-requests"), + maxPaymentFee = config.getDouble("max-payment-fee")) } } diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/PortChecker.scala b/eclair-core/src/main/scala/fr/acinq/eclair/PortChecker.scala index 09423f948..98213a853 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/PortChecker.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/PortChecker.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair import java.net.{InetAddress, ServerSocket} diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/Setup.scala b/eclair-core/src/main/scala/fr/acinq/eclair/Setup.scala index 07270376a..760f646bb 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/Setup.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/Setup.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair import java.io.File @@ -7,7 +23,7 @@ import akka.util.Timeout import com.typesafe.config.{Config, ConfigFactory} import fr.acinq.bitcoin.{BinaryData, Block} import fr.acinq.eclair.NodeParams.ELECTRUM -import fr.acinq.eclair.blockchain.electrum.{ElectrumClient, ElectrumEclairWallet, ElectrumWallet, ElectrumWatcher} +import fr.acinq.eclair.blockchain.electrum._ import fr.acinq.eclair.blockchain.fee.{ConstantFeeProvider, _} import fr.acinq.eclair.blockchain.{EclairWallet, _} import fr.acinq.eclair.channel.Register @@ -61,8 +77,8 @@ class Setup(datadir: File, wallet_opt: Option[EclairWallet] = None, overrideDefa case "regtest" => "/electrum/servers_regtest.json" } val stream = classOf[Setup].getResourceAsStream(addressesFile) - val addresses = ElectrumClient.readServerAddresses(stream) - val electrumClient = system.actorOf(SimpleSupervisor.props(Props(new ElectrumClient(addresses)), "electrum-client", SupervisorStrategy.Resume)) + val addresses = ElectrumClientPool.readServerAddresses(stream) + val electrumClient = system.actorOf(SimpleSupervisor.props(Props(new ElectrumClientPool(addresses)), "electrum-client", SupervisorStrategy.Resume)) Electrum(electrumClient) case _ => ??? } @@ -146,7 +162,6 @@ case class Kit(nodeParams: NodeParams, wallet: EclairWallet) - case object BitcoinWalletDisabledException extends RuntimeException("bitcoind must have wallet support enabled") case object EmptyAPIPasswordException extends RuntimeException("must set a password for the json-rpc api") diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/ShortChannelId.scala b/eclair-core/src/main/scala/fr/acinq/eclair/ShortChannelId.scala index 692e3e96c..5b5c5bd6e 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/ShortChannelId.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/ShortChannelId.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair /** diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/SimpleSupervisor.scala b/eclair-core/src/main/scala/fr/acinq/eclair/SimpleSupervisor.scala index 1318fbd0a..637cd608f 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/SimpleSupervisor.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/SimpleSupervisor.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair import akka.actor.{Actor, ActorLogging, OneForOneStrategy, Props, SupervisorStrategy} diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/UInt64.scala b/eclair-core/src/main/scala/fr/acinq/eclair/UInt64.scala index d58c8767b..818eaf23d 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/UInt64.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/UInt64.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair import java.math.BigInteger @@ -13,6 +29,8 @@ case class UInt64(private val underlying: BigInt) extends Ordered[UInt64] { def toByteArray: Array[Byte] = underlying.toByteArray.takeRight(8) + def toBigInt: BigInt = underlying + override def toString: String = underlying.toString } diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/blockchain/BlockchainEvents.scala b/eclair-core/src/main/scala/fr/acinq/eclair/blockchain/BlockchainEvents.scala index eb2e3db53..cd7c9a6ec 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/blockchain/BlockchainEvents.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/blockchain/BlockchainEvents.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.blockchain import fr.acinq.bitcoin.{Block, Transaction} diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/blockchain/EclairWallet.scala b/eclair-core/src/main/scala/fr/acinq/eclair/blockchain/EclairWallet.scala index 20afb9789..a72610e5a 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/blockchain/EclairWallet.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/blockchain/EclairWallet.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.blockchain import fr.acinq.bitcoin.{BinaryData, Satoshi, Transaction} diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/blockchain/WatcherTypes.scala b/eclair-core/src/main/scala/fr/acinq/eclair/blockchain/WatcherTypes.scala index 1f2951789..3b7275b50 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/blockchain/WatcherTypes.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/blockchain/WatcherTypes.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.blockchain import akka.actor.ActorRef diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/blockchain/bitcoind/BitcoinCoreWallet.scala b/eclair-core/src/main/scala/fr/acinq/eclair/blockchain/bitcoind/BitcoinCoreWallet.scala index 2729efc0c..fdd518de0 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/blockchain/bitcoind/BitcoinCoreWallet.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/blockchain/bitcoind/BitcoinCoreWallet.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.blockchain.bitcoind import akka.actor.ActorSystem diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/blockchain/bitcoind/ZMQActor.scala b/eclair-core/src/main/scala/fr/acinq/eclair/blockchain/bitcoind/ZMQActor.scala index 30fae0067..65c909ae1 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/blockchain/bitcoind/ZMQActor.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/blockchain/bitcoind/ZMQActor.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.blockchain.bitcoind.zmq import akka.actor.{Actor, ActorLogging} diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/blockchain/bitcoind/ZmqWatcher.scala b/eclair-core/src/main/scala/fr/acinq/eclair/blockchain/bitcoind/ZmqWatcher.scala index c979590fc..aa08262f2 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/blockchain/bitcoind/ZmqWatcher.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/blockchain/bitcoind/ZmqWatcher.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.blockchain.bitcoind import java.util.concurrent.Executors @@ -48,7 +64,7 @@ class ZmqWatcher(client: ExtendedBitcoinClient)(implicit ec: ExecutionContext = case NewBlock(block) => // using a Try because in tests we generate fake blocks - log.debug(s"received blockid=${Try(block.blockId).getOrElse(BinaryData(""))}") + log.debug(s"received blockid=${Try(block.blockId).getOrElse(BinaryData.empty)}") nextTick.map(_.cancel()) // this may fail or succeed, worse case scenario we will have two ticks in a row (no big deal) log.debug(s"scheduling a new task to check on tx confirmations") // we do this to avoid herd effects in testing when generating a lots of blocks in a row diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/blockchain/bitcoind/rpc/BasicBitcoinJsonRPCClient.scala b/eclair-core/src/main/scala/fr/acinq/eclair/blockchain/bitcoind/rpc/BasicBitcoinJsonRPCClient.scala index 13829405e..2da57cc9a 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/blockchain/bitcoind/rpc/BasicBitcoinJsonRPCClient.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/blockchain/bitcoind/rpc/BasicBitcoinJsonRPCClient.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.blockchain.bitcoind.rpc import akka.actor.ActorSystem diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/blockchain/bitcoind/rpc/BitcoinJsonRPCClient.scala b/eclair-core/src/main/scala/fr/acinq/eclair/blockchain/bitcoind/rpc/BitcoinJsonRPCClient.scala index 33543a2d2..06fcdb7f2 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/blockchain/bitcoind/rpc/BitcoinJsonRPCClient.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/blockchain/bitcoind/rpc/BitcoinJsonRPCClient.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.blockchain.bitcoind.rpc import java.io.IOException diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/blockchain/bitcoind/rpc/ExtendedBitcoinClient.scala b/eclair-core/src/main/scala/fr/acinq/eclair/blockchain/bitcoind/rpc/ExtendedBitcoinClient.scala index 99f1c1c2a..0ccb64700 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/blockchain/bitcoind/rpc/ExtendedBitcoinClient.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/blockchain/bitcoind/rpc/ExtendedBitcoinClient.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.blockchain.bitcoind.rpc import fr.acinq.bitcoin._ @@ -17,13 +33,6 @@ class ExtendedBitcoinClient(val rpcClient: BitcoinJsonRPCClient) { implicit val formats = org.json4s.DefaultFormats - // TODO: this will probably not be needed once segwit is merged into core - val protocolVersion = Protocol.PROTOCOL_VERSION - - def tx2Hex(tx: Transaction): String = toHexString(Transaction.write(tx, protocolVersion)) - - def hex2tx(hex: String): Transaction = Transaction.read(hex, protocolVersion) - def getTxConfirmations(txId: String)(implicit ec: ExecutionContext): Future[Option[Int]] = rpcClient.invoke("getrawtransaction", txId, 1) // we choose verbose output to get the number of confirmations .map(json => Some((json \ "confirmations").extractOrElse[Int](0))) @@ -126,7 +135,7 @@ class ExtendedBitcoinClient(val rpcClient: BitcoinJsonRPCClient) { } def publishTransaction(tx: Transaction)(implicit ec: ExecutionContext): Future[String] = - publishTransaction(tx2Hex(tx)) + publishTransaction(tx.toString()) /** * We need this to compute absolute timeouts expressed in number of blocks (where getBlockCount would be equivalent diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/blockchain/electrum/ElectrumClient.scala b/eclair-core/src/main/scala/fr/acinq/eclair/blockchain/electrum/ElectrumClient.scala index 90bbd02af..2cd8e97ae 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/blockchain/electrum/ElectrumClient.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/blockchain/electrum/ElectrumClient.scala @@ -1,14 +1,27 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.blockchain.electrum -import java.io.InputStream import java.net.InetSocketAddress -import akka.actor.{Actor, ActorLogging, ActorRef, Stash, Terminated} +import akka.actor.{Actor, ActorLogging, ActorRef, Props, Stash, Terminated} import akka.io.{IO, Tcp} import akka.util.ByteString import fr.acinq.bitcoin._ -import fr.acinq.eclair.Globals -import fr.acinq.eclair.blockchain.CurrentBlockCount import fr.acinq.eclair.blockchain.bitcoind.rpc.{Error, JsonRPCRequest, JsonRPCResponse} import org.json4s.JsonAST._ import org.json4s.jackson.JsonMethods @@ -16,11 +29,10 @@ import org.json4s.{DefaultFormats, JInt, JLong, JString} import org.spongycastle.util.encoders.Hex import scala.annotation.tailrec -import scala.concurrent.ExecutionContext.Implicits.global +import scala.concurrent.ExecutionContext import scala.concurrent.duration._ -import scala.util.Random -class ElectrumClient(serverAddresses: Seq[InetSocketAddress]) extends Actor with Stash with ActorLogging { +class ElectrumClient(serverAddress: InetSocketAddress)(implicit val ec: ExecutionContext) extends Actor with Stash with ActorLogging { import ElectrumClient._ import context.system @@ -28,36 +40,36 @@ class ElectrumClient(serverAddresses: Seq[InetSocketAddress]) extends Actor with implicit val formats = DefaultFormats val newline = "\n" - val connectionFailures = collection.mutable.HashMap.empty[InetSocketAddress, Long] val socketOptions = Tcp.SO.KeepAlive(true) :: Nil - + var addressSubscriptions = Map.empty[String, Set[ActorRef]] + var scriptHashSubscriptions = Map.empty[BinaryData, Set[ActorRef]] + val headerSubscriptions = collection.mutable.HashSet.empty[ActorRef] val version = ServerVersion("2.1.7", "1.1") + val statusListeners = collection.mutable.HashSet.empty[ActorRef] + val keepHeaders = 100 + + var reqId = 0L + + self ! Tcp.Connect(serverAddress, options = socketOptions) + // we need to regularly send a ping in order not to get disconnected - context.system.scheduler.schedule(30 seconds, 30 seconds, self, version) + val versionTrigger = context.system.scheduler.schedule(30 seconds, 30 seconds, self, version) override def unhandled(message: Any): Unit = { message match { case _: Tcp.ConnectionClosed => - val nextAddress = nextPeer() - log.warning(s"connection failed, trying $nextAddress") - self ! Tcp.Connect(nextAddress, options = socketOptions) + log.info(s"connection to $serverAddress closed") statusListeners.map(_ ! ElectrumDisconnected) - context.system.eventStream.publish(ElectrumDisconnected) - context become disconnected + context stop self case Terminated(deadActor) => - val removeMe = addressSubscriptions collect { - case (address, actor) if actor == deadActor => address - } - addressSubscriptions --= removeMe - - val removeMe1 = scriptHashSubscriptions collect { - case (scriptHash, actor) if actor == deadActor => scriptHash - } - scriptHashSubscriptions --= removeMe1 + addressSubscriptions = addressSubscriptions.mapValues(subscribers => subscribers - deadActor) + scriptHashSubscriptions = scriptHashSubscriptions.mapValues(subscribers => subscribers - deadActor) statusListeners -= deadActor headerSubscriptions -= deadActor + case RemoveStatusListener(actor) => statusListeners -= actor + case _: ServerVersion => () // we only handle this when connected case _: ServerVersionResponse => () // we just ignore these messages, they are used as pings @@ -66,7 +78,11 @@ class ElectrumClient(serverAddresses: Seq[InetSocketAddress]) extends Actor with } } - val statusListeners = collection.mutable.HashSet.empty[ActorRef] + + override def postStop(): Unit = { + versionTrigger.cancel() + super.postStop() + } def send(connection: ActorRef, request: JsonRPCRequest): Unit = { import org.json4s.JsonDSL._ @@ -83,32 +99,22 @@ class ElectrumClient(serverAddresses: Seq[InetSocketAddress]) extends Actor with }) ~ ("id" -> request.id) ~ ("jsonrpc" -> request.jsonrpc) val serialized = compact(render(json)) val bytes = (serialized + newline).getBytes - connection ! Tcp.Write(ByteString.fromArray(bytes)) + connection ! ByteString.fromArray(bytes) } - private def nextPeer() = { - val nextPos = Random.nextInt(serverAddresses.size) - serverAddresses(nextPos) + /** + * send an electrum request to the server + * @param connection connection to the electrumx server + * @param request electrum request + * @return the request id used to send the request + */ + def send(connection: ActorRef, request: Request): String = { + val electrumRequestId = "" + reqId + send(connection, makeRequest(request, electrumRequestId)) + reqId = reqId + 1 + electrumRequestId } - private def updateBlockCount(blockCount: Long) = { - // when synchronizing we don't want to advertise previous blocks - if (Globals.blockCount.get() < blockCount) { - log.debug(s"current blockchain height=$blockCount") - system.eventStream.publish(CurrentBlockCount(blockCount)) - Globals.blockCount.set(blockCount) - } - } - - val addressSubscriptions = collection.mutable.HashMap.empty[String, Set[ActorRef]] - val scriptHashSubscriptions = collection.mutable.HashMap.empty[BinaryData, Set[ActorRef]] - val headerSubscriptions = collection.mutable.HashSet.empty[ActorRef] - - context.system.eventStream.publish(ElectrumDisconnected) - self ! Tcp.Connect(serverAddresses.head, options = socketOptions) - - var reqId = 0L - def receive = disconnected def disconnected: Receive = { @@ -118,23 +124,16 @@ class ElectrumClient(serverAddresses: Seq[InetSocketAddress]) extends Actor with case Tcp.Connected(remote, _) => log.info(s"connected to $remote") - connectionFailures.clear() - val connection = sender() - connection ! Tcp.Register(self) - val request = version - send(connection, makeRequest(request, "" + reqId)) - reqId = reqId + 1 + val conn = sender() + conn ! Tcp.Register(self) + val connection = context.actorOf(Props(new WriteAckSender(conn)), name = "electrum-sender") + send(connection, version) context become waitingForVersion(connection, remote) case AddStatusListener(actor) => statusListeners += actor case Tcp.CommandFailed(Tcp.Connect(remoteAddress, _, _, _, _)) => - val nextAddress = nextPeer() - log.warning(s"connection to $remoteAddress failed, trying $nextAddress") - connectionFailures.put(remoteAddress, connectionFailures.getOrElse(remoteAddress, 0L) + 1L) - val count = connectionFailures.getOrElse(nextAddress, 0L) - val delay = Math.min(Math.pow(2.0, count), 20.0) seconds; - context.system.scheduler.scheduleOnce(delay, self, Tcp.Connect(nextAddress, options = socketOptions)) + context stop self } def waitingForVersion(connection: ActorRef, remote: InetSocketAddress): Receive = { @@ -142,11 +141,9 @@ class ElectrumClient(serverAddresses: Seq[InetSocketAddress]) extends Actor with val response = parseResponse(new String(data.toArray)).right.get val serverVersion = parseJsonResponse(version, response) log.debug(s"serverVersion=$serverVersion") - val request = HeaderSubscription(self) - send(connection, makeRequest(request, "" + reqId)) + send(connection, HeaderSubscription(self)) headerSubscriptions += self log.debug("waiting for tip") - reqId = reqId + 1 context become waitingForTip(connection, remote: InetSocketAddress) case AddStatusListener(actor) => statusListeners += actor @@ -157,10 +154,8 @@ class ElectrumClient(serverAddresses: Seq[InetSocketAddress]) extends Actor with val response = parseResponse(new String(data.toArray)).right.get val header = parseHeader(response.result) log.debug(s"connected, tip = ${header.block_hash} $header") - updateBlockCount(header.block_height) - statusListeners.map(_ ! ElectrumReady) - context.system.eventStream.publish(ElectrumConnected) - context become connected(connection, remote, header, "", Map.empty) + statusListeners.map(_ ! ElectrumReady(header)) + context become connected(connection, remote, header, "", Map()) case AddStatusListener(actor) => statusListeners += actor } @@ -168,7 +163,7 @@ class ElectrumClient(serverAddresses: Seq[InetSocketAddress]) extends Actor with def connected(connection: ActorRef, remoteAddress: InetSocketAddress, tip: Header, buffer: String, requests: Map[String, (Request, ActorRef)]): Receive = { case AddStatusListener(actor) => statusListeners += actor - actor ! ElectrumReady + actor ! ElectrumReady(tip) case HeaderSubscription(actor) => headerSubscriptions += actor @@ -176,18 +171,16 @@ class ElectrumClient(serverAddresses: Seq[InetSocketAddress]) extends Actor with context watch actor case request: Request => - val curReqId = "" + reqId - send(connection, makeRequest(request, curReqId)) + val curReqId = send(connection, request) request match { case AddressSubscription(address, actor) => - addressSubscriptions.update(address, addressSubscriptions.getOrElse(address, Set()) + actor) + addressSubscriptions = addressSubscriptions.updated(address, addressSubscriptions.getOrElse(address, Set()) + actor) context watch actor case ScriptHashSubscription(scriptHash, actor) => - scriptHashSubscriptions.update(scriptHash, scriptHashSubscriptions.getOrElse(scriptHash, Set()) + actor) + scriptHashSubscriptions = scriptHashSubscriptions.updated(scriptHash, scriptHashSubscriptions.getOrElse(scriptHash, Set()) + actor) context watch actor case _ => () } - reqId = reqId + 1 context become connected(connection, remoteAddress, tip, buffer, requests + (curReqId -> (request, sender()))) case Tcp.Received(data) => @@ -218,19 +211,11 @@ class ElectrumClient(serverAddresses: Seq[InetSocketAddress]) extends Actor with case HeaderSubscriptionResponse(newtip) => log.info(s"new tip $newtip") - updateBlockCount(newtip.block_height) context become connected(connection, remoteAddress, newtip, buffer, requests) } - } object ElectrumClient { - - def apply(addresses: java.util.List[InetSocketAddress]): ElectrumClient = { - import collection.JavaConversions._ - new ElectrumClient(addresses) - } - /** * Utility function to converts a publicKeyScript to electrum's scripthash * @@ -240,6 +225,9 @@ object ElectrumClient { def computeScriptHash(publicKeyScript: BinaryData): BinaryData = Crypto.sha256(publicKeyScript).reverse // @formatter:off + case class AddStatusListener(actor: ActorRef) + case class RemoveStatusListener(actor: ActorRef) + sealed trait Request sealed trait Response @@ -268,6 +256,9 @@ object ElectrumClient { case class GetTransaction(txid: BinaryData) extends Request case class GetTransactionResponse(tx: Transaction) extends Response + case class GetHeader(height: Int) extends Request + case class GetHeaderResponse(header: Header) extends Response + case class GetMerkle(txid: BinaryData, height: Long) extends Request case class GetMerkleResponse(txid: BinaryData, merkle: Seq[BinaryData], block_height: Long, pos: Int) extends Response { lazy val root: BinaryData = { @@ -293,10 +284,9 @@ object ElectrumClient { case class HeaderSubscriptionResponse(header: Header) extends Response case class Header(block_height: Long, version: Long, prev_block_hash: BinaryData, merkle_root: BinaryData, timestamp: Long, bits: Long, nonce: Long) { - lazy val block_hash: BinaryData = { - val blockHeader = BlockHeader(version, prev_block_hash.reverse, merkle_root.reverse, timestamp, bits, nonce) - blockHeader.hash.reverse - } + def blockHeader = BlockHeader(version, prev_block_hash.reverse, merkle_root.reverse, timestamp, bits, nonce) + lazy val block_id: BinaryData = blockHeader.hash + lazy val block_hash: BinaryData = block_id.reverse } object Header { @@ -311,11 +301,9 @@ object ElectrumClient { case class AddressStatus(address: String, status: String) extends Response case class ServerError(request: Request, error: Error) extends Response - case class AddStatusListener(actor: ActorRef) extends Response sealed trait ElectrumEvent - case object ElectrumConnected extends ElectrumEvent - case object ElectrumReady extends ElectrumEvent + case class ElectrumReady(tip: Header) extends ElectrumEvent case object ElectrumDisconnected extends ElectrumEvent // @formatter:on @@ -397,6 +385,7 @@ object ElectrumClient { case BroadcastTransaction(tx) => JsonRPCRequest(id = reqId, method = "blockchain.transaction.broadcast", params = Hex.toHexString(Transaction.write(tx)) :: Nil) case GetTransaction(txid: BinaryData) => JsonRPCRequest(id = reqId, method = "blockchain.transaction.get", params = txid :: Nil) case HeaderSubscription(_) => JsonRPCRequest(id = reqId, method = "blockchain.headers.subscribe", params = Nil) + case GetHeader(height) => JsonRPCRequest(id = reqId, method = "blockchain.block.get_header", params = height :: Nil) case GetMerkle(txid, height) => JsonRPCRequest(id = reqId, method = "blockchain.transaction.get_merkle", params = txid :: height :: Nil) } @@ -464,6 +453,8 @@ object ElectrumClient { val JString(txid) = json.result require(BinaryData(txid) == tx.txid) BroadcastTransactionResponse(tx, None) + case GetHeader(height) => + GetHeaderResponse(parseHeader(json.result)) case GetMerkle(txid, height) => val JArray(hashes) = json.result \ "merkle" val leaves = hashes collect { case JString(value) => BinaryData(value) } @@ -473,17 +464,4 @@ object ElectrumClient { } } } - - def readServerAddresses(stream: InputStream): Seq[InetSocketAddress] = try { - val JObject(values) = JsonMethods.parse(stream) - val addresses = values.map { - case (name, fields) => - val JString(port) = fields \ "t" - new InetSocketAddress(name, port.toInt) - } - val randomized = Random.shuffle(addresses) - randomized - } finally { - stream.close() - } } diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/blockchain/electrum/ElectrumClientPool.scala b/eclair-core/src/main/scala/fr/acinq/eclair/blockchain/electrum/ElectrumClientPool.scala new file mode 100644 index 000000000..8b231abc8 --- /dev/null +++ b/eclair-core/src/main/scala/fr/acinq/eclair/blockchain/electrum/ElectrumClientPool.scala @@ -0,0 +1,188 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package fr.acinq.eclair.blockchain.electrum + +import java.io.InputStream +import java.net.InetSocketAddress + +import akka.actor.{Actor, ActorRef, FSM, Props, Terminated} +import fr.acinq.eclair.Globals +import fr.acinq.eclair.blockchain.CurrentBlockCount +import org.json4s.JsonAST.{JObject, JString} +import org.json4s.jackson.JsonMethods + +import scala.concurrent.ExecutionContext +import scala.concurrent.duration._ +import scala.util.Random + +class ElectrumClientPool(serverAddresses: Set[InetSocketAddress])(implicit val ec: ExecutionContext) extends Actor with FSM[ElectrumClientPool.State, ElectrumClientPool.Data] { + + import ElectrumClientPool._ + + val statusListeners = collection.mutable.HashSet.empty[ActorRef] + val addresses = collection.mutable.Map.empty[ActorRef, InetSocketAddress] + + // on startup, we attempt to connect to a number of electrum clients + // they will send us an `ElectrumReady` message when they're connected, or + // terminate if they cannot connect + (0 until MAX_CONNECTION_COUNT) foreach (_ => self ! Connect) + + startWith(Disconnected, DisconnectedData) + + when(Disconnected) { + case Event(ElectrumClient.ElectrumReady(tip), _) if addresses.contains(sender) => + sender ! ElectrumClient.HeaderSubscription(self) + handleHeader(sender, tip, None) + + case Event(ElectrumClient.AddStatusListener(listener), _) => + statusListeners += listener + stay + + case Event(Terminated(actor), _) => + log.info("lost connection to {}", addresses(actor)) + addresses -= actor + context.system.scheduler.scheduleOnce(5 seconds, self, Connect) + stay + } + + when(Connected) { + case Event(ElectrumClient.ElectrumReady(tip), d: ConnectedData) if addresses.contains(sender) => + sender ! ElectrumClient.HeaderSubscription(self) + handleHeader(sender, tip, Some(d)) + + case Event(ElectrumClient.HeaderSubscriptionResponse(tip), d: ConnectedData) if addresses.contains(sender) => + handleHeader(sender, tip, Some(d)) + + case Event(request: ElectrumClient.Request, ConnectedData(master, _)) => + master forward request + stay + + case Event(ElectrumClient.AddStatusListener(listener), d: ConnectedData) => + statusListeners += listener + listener ! ElectrumClient.ElectrumReady(d.tips(d.master)) + stay + + case Event(Terminated(actor), d: ConnectedData) => + log.info("lost connection to {}", addresses(actor)) + addresses -= actor + context.system.scheduler.scheduleOnce(5 seconds, self, Connect) + val tips1 = d.tips - actor + if (tips1.isEmpty) { + goto(Disconnected) using DisconnectedData // no more connections + } else if (d.master != actor) { + stay using d.copy(tips = tips1) // we don't care, this wasn't our master + } else { + // we choose next best candidate as master + val tips1 = d.tips - actor + val (bestClient, bestTip) = tips1.toSeq.maxBy(_._2.block_height) + handleHeader(bestClient, bestTip, Some(d.copy(tips = tips1))) + } + } + + whenUnhandled { + case Event(Connect, _) => + Random.shuffle(serverAddresses.toSeq diff addresses.values.toSeq).headOption match { + case Some(address) => + val client = context.actorOf(Props(new ElectrumClient(address))) + client ! ElectrumClient.AddStatusListener(self) + // we watch each electrum client, they will stop on disconnection + context watch client + addresses += (client -> address) + case None => () // no more servers available + } + stay + + case Event(ElectrumClient.ElectrumDisconnected, _) => + stay // ignored, we rely on Terminated messages to detect disconnections + } + + onTransition { + case Connected -> Disconnected => + statusListeners.foreach(_ ! ElectrumClient.ElectrumDisconnected) + context.system.eventStream.publish(ElectrumClient.ElectrumDisconnected) + } + + initialize() + + private def handleHeader(connection: ActorRef, tip: ElectrumClient.Header, d: Option[ConnectedData]) = { + // we update our block count even if it doesn't come from our current master + updateBlockCount(tip.block_height) + d match { + case None => + // as soon as we have a connection to an electrum server, we select it as master + log.info(s"selecting master ${addresses(connection)} at $tip") + statusListeners.foreach(_ ! ElectrumClient.ElectrumReady(tip)) + context.system.eventStream.publish(ElectrumClient.ElectrumReady(tip)) + goto(Connected) using ConnectedData(connection, Map(connection -> tip)) + case Some(d) if tip.block_height >= d.blockHeight + 2L => + // we only switch to a new master if there is a significant difference with our current master, because + // we don't want to switch to a new master every time a new block arrives (some servers will be notified before others) + log.info(s"switching to master ${addresses(connection)} at $tip") + // we've switched to a new master, treat this as a disconnection/reconnection + // so users (wallet, watcher, ...) will reset their subscriptions + statusListeners.foreach(_ ! ElectrumClient.ElectrumDisconnected) + context.system.eventStream.publish(ElectrumClient.ElectrumDisconnected) + statusListeners.foreach(_ ! ElectrumClient.ElectrumReady(tip)) + context.system.eventStream.publish(ElectrumClient.ElectrumReady(tip)) + goto(Connected) using d.copy(master = connection, tips = d.tips + (connection -> tip)) + case Some(d) => + log.debug(s"received tip from ${addresses(connection)} $tip") + stay using d.copy(tips = d.tips + (connection -> tip)) + } + } + + private def updateBlockCount(blockCount: Long): Unit = { + // when synchronizing we don't want to advertise previous blocks + if (Globals.blockCount.get() < blockCount) { + log.debug(s"current blockchain height=$blockCount") + context.system.eventStream.publish(CurrentBlockCount(blockCount)) + Globals.blockCount.set(blockCount) + } + } +} + +object ElectrumClientPool { + + val MAX_CONNECTION_COUNT = 3 + + def readServerAddresses(stream: InputStream): Set[InetSocketAddress] = try { + val JObject(values) = JsonMethods.parse(stream) + val addresses = values.map { + case (name, fields) => + val JString(port) = fields \ "t" + new InetSocketAddress(name, port.toInt) + } + addresses.toSet + } finally { + stream.close() + } + + + // @formatter:off + sealed trait State + case object Disconnected extends State + case object Connected extends State + + sealed trait Data + case object DisconnectedData extends Data + case class ConnectedData(master: ActorRef, tips: Map[ActorRef, ElectrumClient.Header]) extends Data { + def blockHeight = tips.get(master).map(_.block_height).getOrElse(0L) + } + + case object Connect + // @formatter:on +} diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/blockchain/electrum/ElectrumEclairWallet.scala b/eclair-core/src/main/scala/fr/acinq/eclair/blockchain/electrum/ElectrumEclairWallet.scala index b9dbe46dd..712478ddf 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/blockchain/electrum/ElectrumEclairWallet.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/blockchain/electrum/ElectrumEclairWallet.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.blockchain.electrum import akka.actor.{ActorRef, ActorSystem} @@ -63,5 +79,17 @@ class ElectrumEclairWallet(val wallet: ActorRef)(implicit system: ActorSystem, e } } + def sendAll(address: String, feeRatePerKw: Long): Future[(Transaction, Satoshi)] = { + val publicKeyScript = Base58Check.decode(address) match { + case (Base58.Prefix.PubkeyAddressTestnet, pubKeyHash) => Script.pay2pkh(pubKeyHash) + case (Base58.Prefix.ScriptAddressTestnet, scriptHash) => OP_HASH160 :: OP_PUSHDATA(scriptHash) :: OP_EQUAL :: Nil + } + (wallet ? SendAll(Script.write(publicKeyScript), feeRatePerKw)) + .mapTo[SendAllResponse] + .map { + case SendAllResponse(tx, fee) => (tx, fee) + } + } + override def rollback(tx: Transaction): Future[Boolean] = (wallet ? CancelTransaction(tx)).map(_ => true) } diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/blockchain/electrum/ElectrumWallet.scala b/eclair-core/src/main/scala/fr/acinq/eclair/blockchain/electrum/ElectrumWallet.scala index f2aab61d5..96842b04a 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/blockchain/electrum/ElectrumWallet.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/blockchain/electrum/ElectrumWallet.scala @@ -1,9 +1,25 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.blockchain.electrum import akka.actor.{ActorRef, FSM, Props} import fr.acinq.bitcoin.Crypto.{PrivateKey, PublicKey} import fr.acinq.bitcoin.DeterministicWallet.{ExtendedPrivateKey, derivePrivateKey, hardened} -import fr.acinq.bitcoin.{Base58, Base58Check, BinaryData, Block, Crypto, DeterministicWallet, OP_PUSHDATA, OutPoint, SIGHASH_ALL, Satoshi, Script, ScriptWitness, SigVersion, Transaction, TxIn, TxOut} +import fr.acinq.bitcoin.{Base58, Base58Check, BinaryData, Block, Crypto, DeterministicWallet, OP_PUSHDATA, OutPoint, SIGHASH_ALL, Satoshi, Script, ScriptElt, ScriptWitness, SigVersion, Transaction, TxIn, TxOut} import fr.acinq.eclair.blockchain.bitcoind.rpc.Error import fr.acinq.eclair.blockchain.electrum.ElectrumClient.{GetTransaction, GetTransactionResponse, TransactionHistoryItem, computeScriptHash} import fr.acinq.eclair.transactions.Transactions @@ -80,7 +96,7 @@ class ElectrumWallet(seed: BinaryData, client: ActorRef, params: ElectrumWallet. }) when(DISCONNECTED) { - case Event(ElectrumClient.ElectrumReady, data) => + case Event(ElectrumClient.ElectrumReady(_), data) => client ! ElectrumClient.HeaderSubscription(self) goto(WAITING_FOR_TIP) using data } @@ -210,6 +226,10 @@ class ElectrumWallet(seed: BinaryData, client: ActorRef, params: ElectrumWallet. case Failure(t) => stay replying CompleteTransactionResponse(tx, Some(t)) } + case Event(SendAll(publicKeyScript, feeRatePerKw), data) => + val (tx, fee) = data.spendAll(publicKeyScript, feeRatePerKw) + stay replying SendAllResponse(tx, fee) + case Event(CommitTransaction(tx), data) => log.info(s"committing txid=${tx.txid}") val data1 = data.commitTransaction(tx) @@ -282,6 +302,9 @@ object ElectrumWallet { case class CompleteTransaction(tx: Transaction, feeRatePerKw: Long) extends Request case class CompleteTransactionResponse(tx: Transaction, error: Option[Throwable]) extends Response + case class SendAll(publicKeyScript: BinaryData, feeRatePerKw: Long) extends Request + case class SendAllResponse(tx: Transaction, fee: Satoshi) extends Response + case class CommitTransaction(tx: Transaction) extends Request case class CommitTransactionResponse(tx: Transaction) extends Response @@ -684,13 +707,7 @@ object ElectrumWallet { } // sign our tx - val tx3 = tx2.copy(txIn = tx2.txIn.zipWithIndex.map { case (txIn, i) => - val key = utxos(i).key - val sig = Transaction.signInput(tx2, i, Script.pay2pkh(key.publicKey), SIGHASH_ALL, Satoshi(utxos(i).item.value), SigVersion.SIGVERSION_WITNESS_V0, key.privateKey) - val sigScript = Script.write(OP_PUSHDATA(Script.write(Script.pay2wpkh(key.publicKey))) :: Nil) - val witness = ScriptWitness(sig :: key.publicKey.toBin :: Nil) - txIn.copy(signatureScript = sigScript, witness = witness) - }) + val tx3 = signTransaction(tx2) //Transaction.correctlySpends(tx3, utxos.map(utxo => utxo.outPoint -> TxOut(Satoshi(utxo.item.value), computePublicKeyScript(utxo.key.publicKey))).toMap, ScriptFlags.STANDARD_SCRIPT_VERIFY_FLAGS) // and add the completed tx to the lokcs @@ -699,6 +716,17 @@ object ElectrumWallet { (data1, tx3) } + def signTransaction(tx: Transaction) : Transaction = { + tx.copy(txIn = tx.txIn.zipWithIndex.map { case (txIn, i) => + val utxo = utxos.find(_.outPoint == txIn.outPoint).getOrElse(throw new RuntimeException(s"cannot sign input that spends from ${txIn.outPoint}")) + val key = utxo.key + val sig = Transaction.signInput(tx, i, Script.pay2pkh(key.publicKey), SIGHASH_ALL, Satoshi(utxos(i).item.value), SigVersion.SIGVERSION_WITNESS_V0, key.privateKey) + val sigScript = Script.write(OP_PUSHDATA(Script.write(Script.pay2wpkh(key.publicKey))) :: Nil) + val witness = ScriptWitness(sig :: key.publicKey.toBin :: Nil) + txIn.copy(signatureScript = sigScript, witness = witness) + }) + } + /** * unlocks input locked by a pending tx. call this method if the tx will not be used after all * @@ -730,6 +758,28 @@ object ElectrumWallet { } this.copy(locks = this.locks - tx, transactions = this.transactions + (tx.txid -> tx), heights = this.heights + (tx.txid -> 0L), history = history1) } + + /** + * spend all our balance, including unconfirmed utxos and locked utxos (i.e utxos + * that are used in funding transactions that have not been published yet + * @param publicKeyScript script to send all our funds to + * @param feeRatePerKw fee rate in satoshi per kiloweight + * @return a (tx, fee) tuple, tx is a signed transaction that spends all our balance and + * fee is the associated bitcoin network fee + */ + def spendAll(publicKeyScript: BinaryData, feeRatePerKw: Long) : (Transaction, Satoshi) = { + // use confirmed and unconfirmed balance + val amount = balance._1 + balance._2 + val tx = Transaction(version = 2, txIn = Nil, txOut = TxOut(amount, publicKeyScript) :: Nil, lockTime = 0) + // use all uxtos, including locked ones + val tx1 = addUtxosWithDummySig(tx, utxos) + val fee = Transactions.weight2fee(feeRatePerKw, tx1.weight()) + val tx2 = tx1.copy(txOut = TxOut(amount - fee, publicKeyScript) :: Nil) + val tx3 = signTransaction(tx2) + (tx3, fee) + } + + def spendAll(publicKeyScript: Seq[ScriptElt], feeRatePerKw: Long) : (Transaction, Satoshi) = spendAll(Script.write(publicKeyScript), feeRatePerKw) } object Data { diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/blockchain/electrum/ElectrumWatcher.scala b/eclair-core/src/main/scala/fr/acinq/eclair/blockchain/electrum/ElectrumWatcher.scala index 8ebca2bea..84fd5fb74 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/blockchain/electrum/ElectrumWatcher.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/blockchain/electrum/ElectrumWatcher.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.blockchain.electrum import java.net.InetSocketAddress @@ -36,7 +52,7 @@ class ElectrumWatcher(client: ActorRef) extends Actor with Stash with ActorLoggi def receive = disconnected(Set.empty, Nil, SortedMap.empty) def disconnected(watches: Set[Watch], publishQueue: Seq[PublishAsap], block2tx: SortedMap[Long, Seq[Transaction]]): Receive = { - case ElectrumClient.ElectrumReady => + case ElectrumClient.ElectrumReady(_) => client ! ElectrumClient.HeaderSubscription(self) case ElectrumClient.HeaderSubscriptionResponse(header) => watches.map(self ! _) @@ -192,10 +208,10 @@ class ElectrumWatcher(client: ActorRef) extends Actor with Stash with ActorLoggi object ElectrumWatcher extends App { val system = ActorSystem() + import scala.concurrent.ExecutionContext.Implicits.global class Root extends Actor with ActorLogging { - val serverAddresses = Seq(new InetSocketAddress("localhost", 51000), new InetSocketAddress("localhost", 51001)) - val client = context.actorOf(Props(new ElectrumClient(serverAddresses)), "client") + val client = context.actorOf(Props(new ElectrumClient(new InetSocketAddress("localhost", 51000))), "client") client ! ElectrumClient.AddStatusListener(self) override def unhandled(message: Any): Unit = { @@ -204,7 +220,7 @@ object ElectrumWatcher extends App { } def receive = { - case ElectrumClient.ElectrumReady => + case ElectrumClient.ElectrumReady(_) => log.info(s"starting watcher") context become running(context.actorOf(Props(new ElectrumWatcher(client)), "watcher")) } diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/blockchain/electrum/WriteAckSender.scala b/eclair-core/src/main/scala/fr/acinq/eclair/blockchain/electrum/WriteAckSender.scala new file mode 100644 index 000000000..fa0d0ae35 --- /dev/null +++ b/eclair-core/src/main/scala/fr/acinq/eclair/blockchain/electrum/WriteAckSender.scala @@ -0,0 +1,69 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package fr.acinq.eclair.blockchain.electrum + +import akka.actor.{Actor, ActorLogging, ActorRef, PoisonPill, Terminated} +import akka.io.Tcp +import akka.util.ByteString + + +/** + * Simple ACK-based throttling mechanism for sending messages to a TCP connection + * See https://doc.akka.io/docs/akka/snapshot/scala/io-tcp.html#throttling-reads-and-writes + */ +class WriteAckSender(connection: ActorRef) extends Actor with ActorLogging { + + // this actor will kill itself if connection dies + context watch connection + + case object Ack extends Tcp.Event + + override def receive = idle + + def idle: Receive = { + case data: ByteString => + connection ! Tcp.Write(data, Ack) + context become buffering(Vector.empty[ByteString]) + } + + def buffering(buffer: Vector[ByteString]): Receive = { + case _: ByteString if buffer.size > MAX_BUFFERED => + log.warning(s"buffer overrun, closing connection") + connection ! PoisonPill + case data: ByteString => + log.debug("buffering write {}", data) + context become buffering(buffer :+ data) + case Ack => + buffer.headOption match { + case Some(data) => + connection ! Tcp.Write(data, Ack) + context become buffering(buffer.drop(1)) + case None => + log.debug(s"got last ack, back to idle") + context become idle + } + } + + override def unhandled(message: Any): Unit = message match { + case _: Tcp.ConnectionClosed => context stop self + case Terminated(_) => context stop self + case _ => log.warning(s"unhandled message $message") + } + + val MAX_BUFFERED = 100000L + +} diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/blockchain/fee/BitcoinCoreFeeProvider.scala b/eclair-core/src/main/scala/fr/acinq/eclair/blockchain/fee/BitcoinCoreFeeProvider.scala index 2cad236ef..2bc5bb729 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/blockchain/fee/BitcoinCoreFeeProvider.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/blockchain/fee/BitcoinCoreFeeProvider.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.blockchain.fee import fr.acinq.bitcoin._ diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/blockchain/fee/BitgoFeeProvider.scala b/eclair-core/src/main/scala/fr/acinq/eclair/blockchain/fee/BitgoFeeProvider.scala index 47eb27a4a..135de1d9e 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/blockchain/fee/BitgoFeeProvider.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/blockchain/fee/BitgoFeeProvider.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.blockchain.fee import akka.actor.ActorSystem diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/blockchain/fee/ConstantFeeProvider.scala b/eclair-core/src/main/scala/fr/acinq/eclair/blockchain/fee/ConstantFeeProvider.scala index ec275182b..307bc3c12 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/blockchain/fee/ConstantFeeProvider.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/blockchain/fee/ConstantFeeProvider.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.blockchain.fee import scala.concurrent.Future diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/blockchain/fee/EarnDotComFeeProvider.scala b/eclair-core/src/main/scala/fr/acinq/eclair/blockchain/fee/EarnDotComFeeProvider.scala index 0b68a2cfe..4c61239bf 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/blockchain/fee/EarnDotComFeeProvider.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/blockchain/fee/EarnDotComFeeProvider.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.blockchain.fee import akka.actor.ActorSystem diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/blockchain/fee/FallbackFeeProvider.scala b/eclair-core/src/main/scala/fr/acinq/eclair/blockchain/fee/FallbackFeeProvider.scala index 096732436..d79ebe679 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/blockchain/fee/FallbackFeeProvider.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/blockchain/fee/FallbackFeeProvider.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.blockchain.fee import scala.concurrent.{ExecutionContext, Future} diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/blockchain/fee/FeeProvider.scala b/eclair-core/src/main/scala/fr/acinq/eclair/blockchain/fee/FeeProvider.scala index deaec42cf..212c881b8 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/blockchain/fee/FeeProvider.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/blockchain/fee/FeeProvider.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.blockchain.fee import fr.acinq.eclair.feerateByte2Kw diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/channel/AliasActor.scala b/eclair-core/src/main/scala/fr/acinq/eclair/channel/AliasActor.scala index d38f5d262..460713635 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/channel/AliasActor.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/channel/AliasActor.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.channel import akka.actor.{Actor, ActorLogging, ActorRef} diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/channel/Channel.scala b/eclair-core/src/main/scala/fr/acinq/eclair/channel/Channel.scala index a66f710f6..1aaa6bc6d 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/channel/Channel.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/channel/Channel.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.channel import java.nio.charset.StandardCharsets diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/channel/ChannelEvents.scala b/eclair-core/src/main/scala/fr/acinq/eclair/channel/ChannelEvents.scala index fe2ff1156..64cb980ea 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/channel/ChannelEvents.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/channel/ChannelEvents.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.channel import akka.actor.ActorRef diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/channel/ChannelExceptions.scala b/eclair-core/src/main/scala/fr/acinq/eclair/channel/ChannelExceptions.scala index 7c0a1aaea..d2c5bfc68 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/channel/ChannelExceptions.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/channel/ChannelExceptions.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.channel import fr.acinq.bitcoin.{BinaryData, Transaction} diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/channel/ChannelTypes.scala b/eclair-core/src/main/scala/fr/acinq/eclair/channel/ChannelTypes.scala index d3e55ee6c..5d855e285 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/channel/ChannelTypes.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/channel/ChannelTypes.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.channel import akka.actor.ActorRef diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/channel/Commitments.scala b/eclair-core/src/main/scala/fr/acinq/eclair/channel/Commitments.scala index 8973c255e..d03a40f38 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/channel/Commitments.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/channel/Commitments.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.channel import akka.event.LoggingAdapter diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/channel/Forwarder.scala b/eclair-core/src/main/scala/fr/acinq/eclair/channel/Forwarder.scala index 712204c4e..2cb91974e 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/channel/Forwarder.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/channel/Forwarder.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.channel import akka.actor.{Actor, ActorLogging, ActorRef} diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/channel/Helpers.scala b/eclair-core/src/main/scala/fr/acinq/eclair/channel/Helpers.scala index 3b9eddf84..acb4497aa 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/channel/Helpers.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/channel/Helpers.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.channel import akka.event.LoggingAdapter @@ -96,8 +112,7 @@ object Helpers { } def makeAnnouncementSignatures(nodeParams: NodeParams, commitments: Commitments, shortChannelId: ShortChannelId) = { - // TODO: empty features - val features = BinaryData("") + val features = BinaryData.empty // empty features for now val (localNodeSig, localBitcoinSig) = nodeParams.keyManager.signChannelAnnouncement(commitments.localParams.channelKeyPath, nodeParams.chainHash, shortChannelId, commitments.remoteParams.nodeId, commitments.remoteParams.fundingPubKey, features) AnnouncementSignatures(commitments.channelId, shortChannelId, localNodeSig, localBitcoinSig) } @@ -281,7 +296,6 @@ object Helpers { // all htlc output to us are delayed, so we need to claim them as soon as the delay is over val htlcDelayedTxes = htlcTxes.flatMap { txinfo: TransactionWithInputInfo => generateTx("claim-delayed-output")(Try { - // TODO: we should use the current fee rate, not the initial fee rate that we get from localParams val claimDelayed = Transactions.makeClaimDelayedOutputTx( txinfo.tx, Satoshi(localParams.dustLimitSatoshis), @@ -438,13 +452,12 @@ object Helpers { // then we punish them by stealing their main output val mainPenaltyTx = generateTx("main-penalty")(Try { - // TODO: we should use the current fee rate, not the initial fee rate that we get from localParams val txinfo = Transactions.makeMainPenaltyTx(tx, Satoshi(localParams.dustLimitSatoshis), remoteRevocationPubkey, localParams.defaultFinalScriptPubKey, localParams.toSelfDelay, remoteDelayedPaymentPubkey, feeratePerKwPenalty) val sig = keyManager.sign(txinfo, keyManager.revocationPoint(localParams.channelKeyPath), remotePerCommitmentSecret) Transactions.addSigs(txinfo, sig) }) - // TODO: we don't claim htlcs outputs yet + // TODO: we don't claim htlcs outputs yet for revoked transactions // OPTIONAL: let's check transactions are actually spendable //val txes = mainDelayedRevokedTx :: Nil @@ -496,7 +509,6 @@ object Helpers { // let's just pretend we received the preimage from the counterparty and build a fulfill message (add, UpdateFulfillHtlc(add.channelId, add.id, paymentPreimage)) } - // TODO: should we handle local htlcs here as well? currently timed out htlcs that we sent will never have an answer } } @@ -620,7 +632,7 @@ object Helpers { val isCommitTx = revokedCommitPublished.commitTx.txid == tx.txid // does the tx spend an output of the local commitment tx? val spendsTheCommitTx = revokedCommitPublished.commitTx.txid == outPoint.txid - // TODO: we don't currently spend/steal htlc transactions + // TODO: we don't claim htlcs outputs yet for revoked transactions isCommitTx || spendsTheCommitTx } // then we add the relevant outpoints to the map keeping track of which txid spends which outpoint @@ -677,7 +689,7 @@ object Helpers { // are there remaining spendable outputs from the commitment tx? val commitOutputsSpendableByUs = (revokedCommitPublished.claimMainOutputTx.toSeq ++ revokedCommitPublished.mainPenaltyTx) .flatMap(_.txIn.map(_.outPoint)).toSet -- revokedCommitPublished.irrevocablySpent.keys - // TODO: we don't currently spend htlc transactions + // TODO: we don't claim htlcs outputs yet for revoked transactions isCommitTxConfirmed && commitOutputsSpendableByUs.isEmpty } diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/channel/Register.scala b/eclair-core/src/main/scala/fr/acinq/eclair/channel/Register.scala index a6a31e1ec..87a082f9e 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/channel/Register.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/channel/Register.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.channel import akka.actor.Status.Failure diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/crypto/BitStream.scala b/eclair-core/src/main/scala/fr/acinq/eclair/crypto/BitStream.scala index 42c1a346b..dd6c9be2a 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/crypto/BitStream.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/crypto/BitStream.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.crypto import org.spongycastle.util.encoders.Hex diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/crypto/ChaCha20Poly1305.scala b/eclair-core/src/main/scala/fr/acinq/eclair/crypto/ChaCha20Poly1305.scala index 6b2898906..210128ec9 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/crypto/ChaCha20Poly1305.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/crypto/ChaCha20Poly1305.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.crypto import java.nio.ByteOrder diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/crypto/Generators.scala b/eclair-core/src/main/scala/fr/acinq/eclair/crypto/Generators.scala index c350166be..d86527aa1 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/crypto/Generators.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/crypto/Generators.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.crypto import fr.acinq.bitcoin.Crypto.{Point, PrivateKey, PublicKey, Scalar} diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/crypto/KeyManager.scala b/eclair-core/src/main/scala/fr/acinq/eclair/crypto/KeyManager.scala index 2c5ab57d0..ec0b15019 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/crypto/KeyManager.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/crypto/KeyManager.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.crypto import fr.acinq.bitcoin.{BinaryData, Crypto, DeterministicWallet} diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/crypto/LocalKeyManager.scala b/eclair-core/src/main/scala/fr/acinq/eclair/crypto/LocalKeyManager.scala index 1d98d9c82..510637511 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/crypto/LocalKeyManager.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/crypto/LocalKeyManager.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.crypto import com.google.common.cache.{CacheBuilder, CacheLoader, LoadingCache} diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/crypto/Noise.scala b/eclair-core/src/main/scala/fr/acinq/eclair/crypto/Noise.scala index 0513651e6..52a3cfb46 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/crypto/Noise.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/crypto/Noise.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.crypto import java.math.BigInteger diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/crypto/ShaChain.scala b/eclair-core/src/main/scala/fr/acinq/eclair/crypto/ShaChain.scala index 472596f8f..c7d899e97 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/crypto/ShaChain.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/crypto/ShaChain.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.crypto import fr.acinq.bitcoin._ diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/crypto/Sphinx.scala b/eclair-core/src/main/scala/fr/acinq/eclair/crypto/Sphinx.scala index bf85fb5a3..afc6f76f8 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/crypto/Sphinx.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/crypto/Sphinx.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.crypto import java.io.{ByteArrayInputStream, ByteArrayOutputStream, InputStream, OutputStream} diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/crypto/TransportHandler.scala b/eclair-core/src/main/scala/fr/acinq/eclair/crypto/TransportHandler.scala index 485ca5a84..12171a931 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/crypto/TransportHandler.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/crypto/TransportHandler.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.crypto import java.nio.ByteOrder diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/db/ChannelsDb.scala b/eclair-core/src/main/scala/fr/acinq/eclair/db/ChannelsDb.scala index 7e6115c2d..54093f714 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/db/ChannelsDb.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/db/ChannelsDb.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.db import fr.acinq.bitcoin.BinaryData diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/db/NetworkDb.scala b/eclair-core/src/main/scala/fr/acinq/eclair/db/NetworkDb.scala index a150432b8..8d61abd1b 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/db/NetworkDb.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/db/NetworkDb.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.db import fr.acinq.bitcoin.{BinaryData, Satoshi} diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/db/PaymentsDb.scala b/eclair-core/src/main/scala/fr/acinq/eclair/db/PaymentsDb.scala index 0756c1b49..6a52c1a62 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/db/PaymentsDb.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/db/PaymentsDb.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.db import fr.acinq.bitcoin.BinaryData diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/db/PeersDb.scala b/eclair-core/src/main/scala/fr/acinq/eclair/db/PeersDb.scala index d45e5094c..f1b24922d 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/db/PeersDb.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/db/PeersDb.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.db import java.net.InetSocketAddress diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/db/PendingRelayDb.scala b/eclair-core/src/main/scala/fr/acinq/eclair/db/PendingRelayDb.scala index f8759eedc..d92313f97 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/db/PendingRelayDb.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/db/PendingRelayDb.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.db import fr.acinq.bitcoin.BinaryData diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/db/sqlite/SqliteChannelsDb.scala b/eclair-core/src/main/scala/fr/acinq/eclair/db/sqlite/SqliteChannelsDb.scala index 1d2b72915..0172b30be 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/db/sqlite/SqliteChannelsDb.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/db/sqlite/SqliteChannelsDb.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.db.sqlite import java.sql.Connection @@ -11,7 +27,11 @@ class SqliteChannelsDb(sqlite: Connection) extends ChannelsDb { import SqliteUtils._ + val DB_NAME = "channels" + val CURRENT_VERSION = 1 + using(sqlite.createStatement()) { statement => + require(getVersion(statement, DB_NAME, CURRENT_VERSION) == CURRENT_VERSION) // there is only one version currently deployed statement.executeUpdate("CREATE TABLE IF NOT EXISTS local_channels (channel_id BLOB NOT NULL PRIMARY KEY, data BLOB NOT NULL)") } diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/db/sqlite/SqliteNetworkDb.scala b/eclair-core/src/main/scala/fr/acinq/eclair/db/sqlite/SqliteNetworkDb.scala index eb86f4fdd..58f9515de 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/db/sqlite/SqliteNetworkDb.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/db/sqlite/SqliteNetworkDb.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.db.sqlite import java.sql.Connection @@ -16,7 +32,11 @@ class SqliteNetworkDb(sqlite: Connection) extends NetworkDb { import SqliteUtils._ + val DB_NAME = "network" + val CURRENT_VERSION = 1 + using(sqlite.createStatement()) { statement => + require(getVersion(statement, DB_NAME, CURRENT_VERSION) == CURRENT_VERSION) // there is only one version currently deployed statement.execute("PRAGMA foreign_keys = ON") statement.executeUpdate("CREATE TABLE IF NOT EXISTS nodes (node_id BLOB NOT NULL PRIMARY KEY, data BLOB NOT NULL)") statement.executeUpdate("CREATE TABLE IF NOT EXISTS channels (short_channel_id INTEGER NOT NULL PRIMARY KEY, node_id_1 BLOB NOT NULL, node_id_2 BLOB NOT NULL)") diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/db/sqlite/SqlitePaymentsDb.scala b/eclair-core/src/main/scala/fr/acinq/eclair/db/sqlite/SqlitePaymentsDb.scala index 817c618e0..9c3366089 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/db/sqlite/SqlitePaymentsDb.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/db/sqlite/SqlitePaymentsDb.scala @@ -1,9 +1,25 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.db.sqlite import java.sql.Connection import fr.acinq.bitcoin.BinaryData -import fr.acinq.eclair.db.sqlite.SqliteUtils.using +import fr.acinq.eclair.db.sqlite.SqliteUtils.{getVersion, using} import fr.acinq.eclair.db.{Payment, PaymentsDb} import grizzled.slf4j.Logging @@ -21,7 +37,11 @@ import scala.collection.immutable.Queue */ class SqlitePaymentsDb(sqlite: Connection) extends PaymentsDb with Logging { + val DB_NAME = "payments" + val CURRENT_VERSION = 1 + using(sqlite.createStatement()) { statement => + require(getVersion(statement, DB_NAME, CURRENT_VERSION) == CURRENT_VERSION) // there is only one version currently deployed statement.executeUpdate("CREATE TABLE IF NOT EXISTS payments (payment_hash BLOB NOT NULL PRIMARY KEY, amount_msat INTEGER NOT NULL, timestamp INTEGER NOT NULL)") } diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/db/sqlite/SqlitePeersDb.scala b/eclair-core/src/main/scala/fr/acinq/eclair/db/sqlite/SqlitePeersDb.scala index a256e7fbb..499f967eb 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/db/sqlite/SqlitePeersDb.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/db/sqlite/SqlitePeersDb.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.db.sqlite import java.net.InetSocketAddress @@ -6,13 +22,17 @@ import java.sql.Connection import fr.acinq.bitcoin.Crypto import fr.acinq.bitcoin.Crypto.PublicKey import fr.acinq.eclair.db.PeersDb -import fr.acinq.eclair.db.sqlite.SqliteUtils.using +import fr.acinq.eclair.db.sqlite.SqliteUtils.{getVersion, using} import fr.acinq.eclair.wire.LightningMessageCodecs.socketaddress import scodec.bits.BitVector class SqlitePeersDb(sqlite: Connection) extends PeersDb { + val DB_NAME = "peers" + val CURRENT_VERSION = 1 + using(sqlite.createStatement()) { statement => + require(getVersion(statement, DB_NAME, CURRENT_VERSION) == CURRENT_VERSION) // there is only one version currently deployed statement.executeUpdate("CREATE TABLE IF NOT EXISTS peers (node_id BLOB NOT NULL PRIMARY KEY, data BLOB NOT NULL)") } diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/db/sqlite/SqlitePendingRelayDb.scala b/eclair-core/src/main/scala/fr/acinq/eclair/db/sqlite/SqlitePendingRelayDb.scala index b448de41d..c623b86e3 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/db/sqlite/SqlitePendingRelayDb.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/db/sqlite/SqlitePendingRelayDb.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.db.sqlite import java.sql.Connection @@ -5,12 +21,16 @@ import java.sql.Connection import fr.acinq.bitcoin.BinaryData import fr.acinq.eclair.channel.Command import fr.acinq.eclair.db.PendingRelayDb -import fr.acinq.eclair.db.sqlite.SqliteUtils.{codecSequence, using} +import fr.acinq.eclair.db.sqlite.SqliteUtils.{codecSequence, getVersion, using} import fr.acinq.eclair.wire.CommandCodecs.cmdCodec class SqlitePendingRelayDb(sqlite: Connection) extends PendingRelayDb { + val DB_NAME = "pending_relay" + val CURRENT_VERSION = 1 + using(sqlite.createStatement()) { statement => + require(getVersion(statement, DB_NAME, CURRENT_VERSION) == CURRENT_VERSION) // there is only one version currently deployed // note: should we use a foreign key to local_channels table here? statement.executeUpdate("CREATE TABLE IF NOT EXISTS pending_relay (channel_id BLOB NOT NULL, htlc_id INTEGER NOT NULL, data BLOB NOT NULL, PRIMARY KEY(channel_id, htlc_id))") } diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/db/sqlite/SqliteUtils.scala b/eclair-core/src/main/scala/fr/acinq/eclair/db/sqlite/SqliteUtils.scala index 91a314df2..366c571cf 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/db/sqlite/SqliteUtils.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/db/sqlite/SqliteUtils.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.db.sqlite import java.sql.{ResultSet, Statement} @@ -23,6 +39,24 @@ object SqliteUtils { } } + /** + * Several logical databases (channels, network, peers) may be stored in the same physical sqlite database. + * We keep track of their respective version using a dedicated table. + * + * @param statement + * @param db_name + * @param currentVersion + * @return + */ + def getVersion(statement: Statement, db_name: String, currentVersion: Int): Int = { + statement.executeUpdate("CREATE TABLE IF NOT EXISTS versions (db_name TEXT NOT NULL PRIMARY KEY, version INTEGER NOT NULL)") + // if there was no version for the current db, then insert the current version + statement.executeUpdate(s"INSERT OR IGNORE INTO versions VALUES ('$db_name', $currentVersion)") + // if there was a previous version installed, this will return a different value from current version + val res = statement.executeQuery(s"SELECT version FROM versions WHERE db_name='$db_name'") + res.getInt("version") + } + /** * This helper assumes that there is a "data" column available, decodable with the provided codec * diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/io/Authenticator.scala b/eclair-core/src/main/scala/fr/acinq/eclair/io/Authenticator.scala index 99de8ef83..397b65610 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/io/Authenticator.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/io/Authenticator.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.io import java.net.InetSocketAddress diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/io/Client.scala b/eclair-core/src/main/scala/fr/acinq/eclair/io/Client.scala index 0dd6d2dbb..88534e925 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/io/Client.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/io/Client.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.io import java.net.InetSocketAddress diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/io/NodeURI.scala b/eclair-core/src/main/scala/fr/acinq/eclair/io/NodeURI.scala index b35f12e38..b39d920a2 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/io/NodeURI.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/io/NodeURI.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.io import com.google.common.net.HostAndPort diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/io/Peer.scala b/eclair-core/src/main/scala/fr/acinq/eclair/io/Peer.scala index 2f9422fdd..d1a1ea59a 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/io/Peer.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/io/Peer.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.io import java.io.ByteArrayInputStream diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/io/Server.scala b/eclair-core/src/main/scala/fr/acinq/eclair/io/Server.scala index 08733a3c2..fd4040ec8 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/io/Server.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/io/Server.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.io import java.net.InetSocketAddress diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/io/Switchboard.scala b/eclair-core/src/main/scala/fr/acinq/eclair/io/Switchboard.scala index 576178b08..2fb0d2435 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/io/Switchboard.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/io/Switchboard.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.io import java.net.InetSocketAddress diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/package.scala b/eclair-core/src/main/scala/fr/acinq/eclair/package.scala index 930a23359..e3d06e28b 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/package.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/package.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq import java.security.SecureRandom diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/payment/CommandBuffer.scala b/eclair-core/src/main/scala/fr/acinq/eclair/payment/CommandBuffer.scala index 983b4dd13..0092efae1 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/payment/CommandBuffer.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/payment/CommandBuffer.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.payment import akka.actor.{Actor, ActorLogging, ActorRef} diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/payment/LocalPaymentHandler.scala b/eclair-core/src/main/scala/fr/acinq/eclair/payment/LocalPaymentHandler.scala index 391b53666..496b668bb 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/payment/LocalPaymentHandler.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/payment/LocalPaymentHandler.scala @@ -1,9 +1,26 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.payment import akka.actor.{Actor, ActorLogging, Props, Status} import fr.acinq.bitcoin.{BinaryData, Crypto, MilliSatoshi} import fr.acinq.eclair.channel.{CMD_FAIL_HTLC, CMD_FULFILL_HTLC, Channel} import fr.acinq.eclair.db.Payment +import fr.acinq.eclair.payment.PaymentLifecycle.{CheckPayment, ReceivePayment} import fr.acinq.eclair.wire._ import scala.concurrent.duration._ diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/payment/NoopPaymentHandler.scala b/eclair-core/src/main/scala/fr/acinq/eclair/payment/NoopPaymentHandler.scala index 9d50daab5..f2a59c63f 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/payment/NoopPaymentHandler.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/payment/NoopPaymentHandler.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.payment import akka.actor.{Actor, ActorLogging, ActorRef} diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/payment/PaymentEvents.scala b/eclair-core/src/main/scala/fr/acinq/eclair/payment/PaymentEvents.scala index 384f54764..6542d9eac 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/payment/PaymentEvents.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/payment/PaymentEvents.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.payment import fr.acinq.bitcoin.{BinaryData, MilliSatoshi} diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/payment/PaymentInitiator.scala b/eclair-core/src/main/scala/fr/acinq/eclair/payment/PaymentInitiator.scala index 535a09cba..96fd5f8c8 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/payment/PaymentInitiator.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/payment/PaymentInitiator.scala @@ -1,7 +1,24 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.payment import akka.actor.{Actor, ActorLogging, ActorRef, Props} import fr.acinq.bitcoin.Crypto.PublicKey +import fr.acinq.eclair.payment.PaymentLifecycle.SendPayment /** * Created by PM on 29/08/2016. diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/payment/PaymentLifecycle.scala b/eclair-core/src/main/scala/fr/acinq/eclair/payment/PaymentLifecycle.scala index 430e87244..cc4002678 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/payment/PaymentLifecycle.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/payment/PaymentLifecycle.scala @@ -1,13 +1,33 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.payment +import java.text.NumberFormat +import java.util.Locale + import akka.actor.{ActorRef, FSM, Props, Status} import fr.acinq.bitcoin.Crypto.PublicKey import fr.acinq.bitcoin.{BinaryData, MilliSatoshi} import fr.acinq.eclair._ import fr.acinq.eclair.blockchain.WatchEventSpentBasic -import fr.acinq.eclair.channel._ -import fr.acinq.eclair.crypto.{Sphinx, TransportHandler} +import fr.acinq.eclair.channel.{AddHtlcFailed, CMD_ADD_HTLC, Channel, Register, _} import fr.acinq.eclair.crypto.Sphinx.{ErrorPacket, Packet} +import fr.acinq.eclair.crypto.{Sphinx, TransportHandler} +import fr.acinq.eclair.payment.PaymentLifecycle._ import fr.acinq.eclair.payment.PaymentRequest.ExtraHop import fr.acinq.eclair.router._ import fr.acinq.eclair.wire._ @@ -15,40 +35,10 @@ import scodec.Attempt import scala.util.{Failure, Success} -// @formatter:off -case class ReceivePayment(amountMsat_opt: Option[MilliSatoshi], description: String) -/** - * @param finalCltvExpiry by default we choose finalCltvExpiry = Channel.MIN_CLTV_EXPIRY + 1 to not have our htlc fail when a new block has just been found - */ -case class SendPayment(amountMsat: Long, paymentHash: BinaryData, targetNodeId: PublicKey, assistedRoutes: Seq[Seq[ExtraHop]] = Nil, finalCltvExpiry: Long = Channel.MIN_CLTV_EXPIRY + 1, maxAttempts: Int = 5) -case class CheckPayment(paymentHash: BinaryData) - -sealed trait PaymentResult -case class PaymentSucceeded(amountMsat: Long, paymentHash: BinaryData, paymentPreimage: BinaryData, route: Seq[Hop]) extends PaymentResult // note: the amount includes fees -sealed trait PaymentFailure -case class LocalFailure(t: Throwable) extends PaymentFailure -case class RemoteFailure(route: Seq[Hop], e: ErrorPacket) extends PaymentFailure -case class UnreadableRemoteFailure(route: Seq[Hop]) extends PaymentFailure -case class PaymentFailed(paymentHash: BinaryData, failures: Seq[PaymentFailure]) extends PaymentResult - -sealed trait Data -case object WaitingForRequest extends Data -case class WaitingForRoute(sender: ActorRef, c: SendPayment, failures: Seq[PaymentFailure]) extends Data -case class WaitingForComplete(sender: ActorRef, c: SendPayment, cmd: CMD_ADD_HTLC, failures: Seq[PaymentFailure], sharedSecrets: Seq[(BinaryData, PublicKey)], ignoreNodes: Set[PublicKey], ignoreChannels: Set[ChannelDesc], hops: Seq[Hop]) extends Data - -sealed trait State -case object WAITING_FOR_REQUEST extends State -case object WAITING_FOR_ROUTE extends State -case object WAITING_FOR_PAYMENT_COMPLETE extends State - -// @formatter:on - /** * Created by PM on 26/08/2016. */ -class PaymentLifecycle(sourceNodeId: PublicKey, router: ActorRef, register: ActorRef) extends FSM[State, Data] { - - import PaymentLifecycle._ +class PaymentLifecycle(sourceNodeId: PublicKey, router: ActorRef, register: ActorRef) extends FSM[PaymentLifecycle.State, PaymentLifecycle.Data] { startWith(WAITING_FOR_REQUEST, WaitingForRequest) @@ -64,8 +54,15 @@ class PaymentLifecycle(sourceNodeId: PublicKey, router: ActorRef, register: Acto val firstHop = hops.head val finalExpiry = Globals.blockCount.get().toInt + c.finalCltvExpiry.toInt val (cmd, sharedSecrets) = buildCommand(c.amountMsat, finalExpiry, c.paymentHash, hops) - register ! Register.ForwardShortId(firstHop.lastUpdate.shortChannelId, cmd) - goto(WAITING_FOR_PAYMENT_COMPLETE) using WaitingForComplete(s, c, cmd, failures, sharedSecrets, ignoreNodes, ignoreChannels, hops) + val feePct = (cmd.amountMsat - c.amountMsat) / c.amountMsat.toDouble // c.amountMsat is required to be > 0, have to convert to double, otherwise will be rounded + if (feePct > c.maxFeePct) { + log.info(s"cheapest route found is too expensive: feePct=$feePct maxFeePct=${c.maxFeePct}") + reply(s, PaymentFailed(c.paymentHash, failures = failures :+ LocalFailure(RouteTooExpensive(feePct, c.maxFeePct)))) + stop(FSM.Normal) + } else { + register ! Register.ForwardShortId(firstHop.lastUpdate.shortChannelId, cmd) + goto(WAITING_FOR_PAYMENT_COMPLETE) using WaitingForComplete(s, c, cmd, failures, sharedSecrets, ignoreNodes, ignoreChannels, hops) + } case Event(Status.Failure(t), WaitingForRoute(s, c, failures)) => reply(s, PaymentFailed(c.paymentHash, failures = failures :+ LocalFailure(t))) @@ -190,6 +187,42 @@ object PaymentLifecycle { def props(sourceNodeId: PublicKey, router: ActorRef, register: ActorRef) = Props(classOf[PaymentLifecycle], sourceNodeId, router, register) + // @formatter:off + case class ReceivePayment(amountMsat_opt: Option[MilliSatoshi], description: String) + /** + * @param finalCltvExpiry by default we choose finalCltvExpiry = Channel.MIN_CLTV_EXPIRY + 1 to not have our htlc fail when a new block has just been found + * @param maxFeePct set by default to 3% as a safety measure (even if a route is found, if fee is higher than that payment won't be attempted) + */ + case class SendPayment(amountMsat: Long, paymentHash: BinaryData, targetNodeId: PublicKey, assistedRoutes: Seq[Seq[ExtraHop]] = Nil, finalCltvExpiry: Long = Channel.MIN_CLTV_EXPIRY + 1, maxAttempts: Int = 5, maxFeePct: Double = 0.03) { + require(amountMsat > 0, s"amountMsat must be > 0") + } + case class CheckPayment(paymentHash: BinaryData) + + sealed trait PaymentResult + case class PaymentSucceeded(amountMsat: Long, paymentHash: BinaryData, paymentPreimage: BinaryData, route: Seq[Hop]) extends PaymentResult // note: the amount includes fees + sealed trait PaymentFailure + case class LocalFailure(t: Throwable) extends PaymentFailure + case class RemoteFailure(route: Seq[Hop], e: ErrorPacket) extends PaymentFailure + case class UnreadableRemoteFailure(route: Seq[Hop]) extends PaymentFailure + case class PaymentFailed(paymentHash: BinaryData, failures: Seq[PaymentFailure]) extends PaymentResult + + sealed trait Data + case object WaitingForRequest extends Data + case class WaitingForRoute(sender: ActorRef, c: SendPayment, failures: Seq[PaymentFailure]) extends Data + case class WaitingForComplete(sender: ActorRef, c: SendPayment, cmd: CMD_ADD_HTLC, failures: Seq[PaymentFailure], sharedSecrets: Seq[(BinaryData, PublicKey)], ignoreNodes: Set[PublicKey], ignoreChannels: Set[ChannelDesc], hops: Seq[Hop]) extends Data + + sealed trait State + case object WAITING_FOR_REQUEST extends State + case object WAITING_FOR_ROUTE extends State + case object WAITING_FOR_PAYMENT_COMPLETE extends State + + val percentageFormatter = NumberFormat.getPercentInstance(Locale.US) // force US locale to always get "fee=0.272% max=0.1%" (otherwise depending on locale it can be "fee=0,272 % max=0,1 %") + percentageFormatter.setMaximumFractionDigits(3) + case class RouteTooExpensive(feePct: Double, maxFeePct: Double) extends RuntimeException(s"cheapest route found is too expensive: fee=${percentageFormatter.format(feePct)} max=${percentageFormatter.format(maxFeePct)}") + + // @formatter:on + + def buildOnion(nodes: Seq[PublicKey], payloads: Seq[PerHopPayload], associatedData: BinaryData): Sphinx.PacketAndSecrets = { require(nodes.size == payloads.size) val sessionKey = randomKey diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/payment/PaymentRequest.scala b/eclair-core/src/main/scala/fr/acinq/eclair/payment/PaymentRequest.scala index de24efe27..c636fc603 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/payment/PaymentRequest.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/payment/PaymentRequest.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.payment import java.math.BigInteger @@ -105,15 +121,16 @@ object PaymentRequest { // https://github.com/lightningnetwork/lightning-rfc/blob/master/02-peer-protocol.md#adding-an-htlc-update_add_htlc val MAX_AMOUNT = MilliSatoshi(4294967296L) + val prefixes = Map( + Block.RegtestGenesisBlock.hash -> "lnbcrt", + Block.TestnetGenesisBlock.hash -> "lntb", + Block.LivenetGenesisBlock.hash -> "lnbc") + def apply(chainHash: BinaryData, amount: Option[MilliSatoshi], paymentHash: BinaryData, privateKey: PrivateKey, description: String, fallbackAddress: Option[String] = None, expirySeconds: Option[Long] = None, extraHops: Seq[Seq[ExtraHop]] = Nil, timestamp: Long = System.currentTimeMillis() / 1000L): PaymentRequest = { - val prefix = chainHash match { - case Block.RegtestGenesisBlock.hash => "lntb" - case Block.TestnetGenesisBlock.hash => "lntb" - case Block.LivenetGenesisBlock.hash => "lnbc" - } + val prefix = prefixes(chainHash) PaymentRequest( prefix = prefix, @@ -216,11 +233,11 @@ object PaymentRequest { /** * Extra hop contained in RoutingInfoTag * - * @param nodeId start of the channel - * @param shortChannelId channel id - * @param feeBaseMsat node fixed fee - * @param feeProportionalMillionths node proportional fee - * @param cltvExpiryDelta node cltv expiry delta + * @param nodeId start of the channel + * @param shortChannelId channel id + * @param feeBaseMsat node fixed fee + * @param feeProportionalMillionths node proportional fee + * @param cltvExpiryDelta node cltv expiry delta */ case class ExtraHop(nodeId: PublicKey, shortChannelId: ShortChannelId, feeBaseMsat: Long, feeProportionalMillionths: Long, cltvExpiryDelta: Int) { def pack: Seq[Byte] = nodeId.toBin ++ Protocol.writeUInt64(shortChannelId.toLong, ByteOrder.BIG_ENDIAN) ++ @@ -494,8 +511,8 @@ object PaymentRequest { val message: BinaryData = hrp.getBytes ++ stream1.bytes val (pub1, pub2) = Crypto.recoverPublicKey((r, s), Crypto.sha256(message)) val pub = if (recid % 2 != 0) pub2 else pub1 - val prefix = hrp.take(4) - val amount_opt = Amount.decode(hrp.drop(4)) + val prefix = prefixes.values.find(prefix => hrp.startsWith(prefix)).getOrElse(throw new RuntimeException("unknown prefix")) + val amount_opt = Amount.decode(hrp.drop(prefix.length)) val pr = PaymentRequest(prefix, amount_opt, timestamp, pub, tags.toList, signature) val validSig = Crypto.verifySignature(Crypto.sha256(message), (r, s), pub) require(validSig, "invalid signature") diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/payment/Relayer.scala b/eclair-core/src/main/scala/fr/acinq/eclair/payment/Relayer.scala index 7ab280348..6f0d55208 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/payment/Relayer.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/payment/Relayer.scala @@ -1,9 +1,26 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.payment import akka.actor.{Actor, ActorLogging, ActorRef, Props, Status} import fr.acinq.bitcoin.{BinaryData, Crypto, MilliSatoshi} import fr.acinq.eclair.channel._ import fr.acinq.eclair.crypto.Sphinx +import fr.acinq.eclair.payment.PaymentLifecycle.{PaymentFailed, PaymentSucceeded} import fr.acinq.eclair.router.Announcements import fr.acinq.eclair.wire._ import fr.acinq.eclair.{Globals, NodeParams, ShortChannelId} diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/router/Announcements.scala b/eclair-core/src/main/scala/fr/acinq/eclair/router/Announcements.scala index a121e7f28..4a49896c8 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/router/Announcements.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/router/Announcements.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.router import java.net.InetSocketAddress @@ -54,7 +70,7 @@ object Announcements { nodeId2 = nodeId2, bitcoinKey1 = bitcoinKey1, bitcoinKey2 = bitcoinKey2, - features = BinaryData(""), + features = BinaryData.empty, chainHash = chainHash ) } diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/router/ChannelRangeQueries.scala b/eclair-core/src/main/scala/fr/acinq/eclair/router/ChannelRangeQueries.scala index b5f3cc87e..f39a52a61 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/router/ChannelRangeQueries.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/router/ChannelRangeQueries.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.router import java.io.{ByteArrayInputStream, ByteArrayOutputStream} diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/router/NetworkEvents.scala b/eclair-core/src/main/scala/fr/acinq/eclair/router/NetworkEvents.scala index 90cc50716..a26b374df 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/router/NetworkEvents.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/router/NetworkEvents.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.router import fr.acinq.bitcoin.Crypto.PublicKey diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/router/Router.scala b/eclair-core/src/main/scala/fr/acinq/eclair/router/Router.scala index 635fe13fa..a36144739 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/router/Router.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/router/Router.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.router import akka.actor.{ActorRef, FSM, Props, Status} @@ -278,6 +294,7 @@ class Router(nodeParams: NodeParams, watcher: ActorRef) extends FSM[State, Data] // it takes precedence over all other channel_updates we know val assistedUpdates = assistedRoutes.flatMap(toFakeUpdates(_, end)).toMap // we also filter out updates corresponding to channels/nodes that are blacklisted for this particular request + // TODO: in case of duplicates, d.updates will be overriden by assistedUpdates even if they are more recent! val ignoredUpdates = getIgnoredChannelDesc(d.updates ++ d.privateUpdates ++ assistedUpdates, ignoreNodes) ++ ignoreChannels ++ d.excludedChannels log.info(s"finding a route $start->$end with assistedChannels={} ignoreNodes={} ignoreChannels={} excludedChannels={}", assistedUpdates.keys.mkString(","), ignoreNodes.map(_.toBin).mkString(","), ignoreChannels.mkString(","), d.excludedChannels.mkString(",")) findRoute(d.graph, start, end, withEdges = assistedUpdates, withoutEdges = ignoredUpdates) diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/router/RouterExceptions.scala b/eclair-core/src/main/scala/fr/acinq/eclair/router/RouterExceptions.scala index 737ee21b0..b579a70bf 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/router/RouterExceptions.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/router/RouterExceptions.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.router /** diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/transactions/CommitmentSpec.scala b/eclair-core/src/main/scala/fr/acinq/eclair/transactions/CommitmentSpec.scala index 8fb4cf20f..1e23d8205 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/transactions/CommitmentSpec.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/transactions/CommitmentSpec.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.transactions import fr.acinq.eclair.wire._ diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/transactions/Scripts.scala b/eclair-core/src/main/scala/fr/acinq/eclair/transactions/Scripts.scala index becf64be7..e7f2aaf7e 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/transactions/Scripts.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/transactions/Scripts.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.transactions import fr.acinq.bitcoin.Crypto.{PublicKey, ripemd160} diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/transactions/Transactions.scala b/eclair-core/src/main/scala/fr/acinq/eclair/transactions/Transactions.scala index d2ef3770a..d5d05d9f0 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/transactions/Transactions.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/transactions/Transactions.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.transactions import java.nio.ByteOrder diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/wire/ChannelCodecs.scala b/eclair-core/src/main/scala/fr/acinq/eclair/wire/ChannelCodecs.scala index af0b96d93..3a1a487e2 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/wire/ChannelCodecs.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/wire/ChannelCodecs.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.wire import fr.acinq.bitcoin.DeterministicWallet.{ExtendedPrivateKey, KeyPath} diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/wire/CommandCodecs.scala b/eclair-core/src/main/scala/fr/acinq/eclair/wire/CommandCodecs.scala index 14dedd132..4a8b03ff1 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/wire/CommandCodecs.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/wire/CommandCodecs.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.wire import fr.acinq.eclair.channel.{CMD_FAIL_HTLC, CMD_FAIL_MALFORMED_HTLC, CMD_FULFILL_HTLC, Command} diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/wire/FailureMessage.scala b/eclair-core/src/main/scala/fr/acinq/eclair/wire/FailureMessage.scala index dea08f167..213c4258f 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/wire/FailureMessage.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/wire/FailureMessage.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.wire import fr.acinq.bitcoin.BinaryData diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/wire/FixedSizeStrictCodec.scala b/eclair-core/src/main/scala/fr/acinq/eclair/wire/FixedSizeStrictCodec.scala index 0c2d95b70..95f60e386 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/wire/FixedSizeStrictCodec.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/wire/FixedSizeStrictCodec.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.wire import scodec.bits.{BitVector, ByteVector} diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/wire/LightningMessageCodecs.scala b/eclair-core/src/main/scala/fr/acinq/eclair/wire/LightningMessageCodecs.scala index e93678aab..1f931fff9 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/wire/LightningMessageCodecs.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/wire/LightningMessageCodecs.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.wire import java.math.BigInteger diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/wire/LightningMessageTypes.scala b/eclair-core/src/main/scala/fr/acinq/eclair/wire/LightningMessageTypes.scala index 723cd8acc..d9d3d3b47 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/wire/LightningMessageTypes.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/wire/LightningMessageTypes.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.wire import java.net.InetSocketAddress diff --git a/eclair-core/src/test/java/fr/acinq/eclair/crypto/Curve25519.java b/eclair-core/src/test/java/fr/acinq/eclair/crypto/Curve25519.java index b19232c0d..12306c0be 100644 --- a/eclair-core/src/test/java/fr/acinq/eclair/crypto/Curve25519.java +++ b/eclair-core/src/test/java/fr/acinq/eclair/crypto/Curve25519.java @@ -1,27 +1,20 @@ -package fr.acinq.eclair.crypto; - /* - * Copyright (C) 2016 Southern Storm Software, Pty Ltd. + * Copyright 2018 ACINQ SAS * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. + * http://www.apache.org/licenses/LICENSE-2.0 * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ +package fr.acinq.eclair.crypto; import java.util.Arrays; diff --git a/eclair-core/src/test/resources/logback-test.xml b/eclair-core/src/test/resources/logback-test.xml index 98a65c054..16b083f9d 100644 --- a/eclair-core/src/test/resources/logback-test.xml +++ b/eclair-core/src/test/resources/logback-test.xml @@ -1,4 +1,20 @@ + + diff --git a/eclair-core/src/test/scala/fr/acinq/eclair/CoinUtilsSpec.scala b/eclair-core/src/test/scala/fr/acinq/eclair/CoinUtilsSpec.scala index bd1c9203a..f0f83e42b 100644 --- a/eclair-core/src/test/scala/fr/acinq/eclair/CoinUtilsSpec.scala +++ b/eclair-core/src/test/scala/fr/acinq/eclair/CoinUtilsSpec.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair import fr.acinq.bitcoin.{Btc, MilliBtc, MilliSatoshi, Satoshi} diff --git a/eclair-core/src/test/scala/fr/acinq/eclair/FeaturesSpec.scala b/eclair-core/src/test/scala/fr/acinq/eclair/FeaturesSpec.scala index c4f7463c6..7a874d9fb 100644 --- a/eclair-core/src/test/scala/fr/acinq/eclair/FeaturesSpec.scala +++ b/eclair-core/src/test/scala/fr/acinq/eclair/FeaturesSpec.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair import java.nio.ByteOrder diff --git a/eclair-core/src/test/scala/fr/acinq/eclair/PackageSpec.scala b/eclair-core/src/test/scala/fr/acinq/eclair/PackageSpec.scala index 1a84386c6..d301f9b30 100644 --- a/eclair-core/src/test/scala/fr/acinq/eclair/PackageSpec.scala +++ b/eclair-core/src/test/scala/fr/acinq/eclair/PackageSpec.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair import fr.acinq.bitcoin.BinaryData diff --git a/eclair-core/src/test/scala/fr/acinq/eclair/Pipe.scala b/eclair-core/src/test/scala/fr/acinq/eclair/Pipe.scala index 7345bf98f..f19f07c5d 100644 --- a/eclair-core/src/test/scala/fr/acinq/eclair/Pipe.scala +++ b/eclair-core/src/test/scala/fr/acinq/eclair/Pipe.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair import akka.actor.{Actor, ActorLogging, ActorRef, Stash} diff --git a/eclair-core/src/test/scala/fr/acinq/eclair/ShortChannelIdSpec.scala b/eclair-core/src/test/scala/fr/acinq/eclair/ShortChannelIdSpec.scala index d877eee94..ce4a45a71 100644 --- a/eclair-core/src/test/scala/fr/acinq/eclair/ShortChannelIdSpec.scala +++ b/eclair-core/src/test/scala/fr/acinq/eclair/ShortChannelIdSpec.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair import org.junit.runner.RunWith diff --git a/eclair-core/src/test/scala/fr/acinq/eclair/TestBitcoinClient.scala b/eclair-core/src/test/scala/fr/acinq/eclair/TestBitcoinClient.scala index 1f504bc0d..6d33a6e69 100644 --- a/eclair-core/src/test/scala/fr/acinq/eclair/TestBitcoinClient.scala +++ b/eclair-core/src/test/scala/fr/acinq/eclair/TestBitcoinClient.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair import akka.actor.ActorSystem diff --git a/eclair-core/src/test/scala/fr/acinq/eclair/TestConstants.scala b/eclair-core/src/test/scala/fr/acinq/eclair/TestConstants.scala index 145c628a5..4a48c9614 100644 --- a/eclair-core/src/test/scala/fr/acinq/eclair/TestConstants.scala +++ b/eclair-core/src/test/scala/fr/acinq/eclair/TestConstants.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair import java.net.InetSocketAddress @@ -64,7 +80,8 @@ object TestConstants { channelExcludeDuration = 5 seconds, watcherType = BITCOIND, paymentRequestExpiry = 1 hour, - maxPendingPaymentRequests = 10000000) + maxPendingPaymentRequests = 10000000, + maxPaymentFee = 0.03) def channelParams = Peer.makeChannelParams( nodeParams = nodeParams, @@ -117,7 +134,8 @@ object TestConstants { channelExcludeDuration = 5 seconds, watcherType = BITCOIND, paymentRequestExpiry = 1 hour, - maxPendingPaymentRequests = 10000000) + maxPendingPaymentRequests = 10000000, + maxPaymentFee = 0.03) def channelParams = Peer.makeChannelParams( nodeParams = nodeParams, diff --git a/eclair-core/src/test/scala/fr/acinq/eclair/TestkitBaseClass.scala b/eclair-core/src/test/scala/fr/acinq/eclair/TestkitBaseClass.scala index 622987a22..979c3efb6 100644 --- a/eclair-core/src/test/scala/fr/acinq/eclair/TestkitBaseClass.scala +++ b/eclair-core/src/test/scala/fr/acinq/eclair/TestkitBaseClass.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair import akka.actor.{ActorNotFound, ActorSystem, PoisonPill} diff --git a/eclair-core/src/test/scala/fr/acinq/eclair/UInt64Spec.scala b/eclair-core/src/test/scala/fr/acinq/eclair/UInt64Spec.scala index c9983a96e..596858b49 100644 --- a/eclair-core/src/test/scala/fr/acinq/eclair/UInt64Spec.scala +++ b/eclair-core/src/test/scala/fr/acinq/eclair/UInt64Spec.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair import fr.acinq.bitcoin.BinaryData diff --git a/eclair-core/src/test/scala/fr/acinq/eclair/blockchain/TestWallet.scala b/eclair-core/src/test/scala/fr/acinq/eclair/blockchain/TestWallet.scala index c2cdbcf31..3d85935b5 100644 --- a/eclair-core/src/test/scala/fr/acinq/eclair/blockchain/TestWallet.scala +++ b/eclair-core/src/test/scala/fr/acinq/eclair/blockchain/TestWallet.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.blockchain import fr.acinq.bitcoin.{BinaryData, Crypto, OP_PUSHDATA, OutPoint, Satoshi, Script, Transaction, TxIn, TxOut} diff --git a/eclair-core/src/test/scala/fr/acinq/eclair/blockchain/bitcoind/BitcoinCoreWalletSpec.scala b/eclair-core/src/test/scala/fr/acinq/eclair/blockchain/bitcoind/BitcoinCoreWalletSpec.scala index 722e5b9fd..464b5a0e1 100644 --- a/eclair-core/src/test/scala/fr/acinq/eclair/blockchain/bitcoind/BitcoinCoreWalletSpec.scala +++ b/eclair-core/src/test/scala/fr/acinq/eclair/blockchain/bitcoind/BitcoinCoreWalletSpec.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.blockchain.bitcoind import java.io.File diff --git a/eclair-core/src/test/scala/fr/acinq/eclair/blockchain/electrum/ElectrumClientPoolSpec.scala b/eclair-core/src/test/scala/fr/acinq/eclair/blockchain/electrum/ElectrumClientPoolSpec.scala new file mode 100644 index 000000000..12d246eed --- /dev/null +++ b/eclair-core/src/test/scala/fr/acinq/eclair/blockchain/electrum/ElectrumClientPoolSpec.scala @@ -0,0 +1,95 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package fr.acinq.eclair.blockchain.electrum + +import akka.actor.{ActorRef, ActorSystem, Props} +import akka.testkit.{TestKit, TestProbe} +import fr.acinq.bitcoin.{BinaryData, Crypto, Transaction} +import fr.acinq.eclair.blockchain.electrum.ElectrumClient._ +import grizzled.slf4j.Logging +import org.junit.runner.RunWith +import org.scalatest.junit.JUnitRunner +import org.scalatest.{BeforeAndAfterAll, FunSuiteLike} + +import scala.concurrent.duration._ +import scala.util.Random + +@RunWith(classOf[JUnitRunner]) +class ElectrumClientPoolSpec extends TestKit(ActorSystem("test")) with FunSuiteLike with Logging with BeforeAndAfterAll { + var router: ActorRef = _ + val probe = TestProbe() + val referenceTx = Transaction.read("0200000003947e307df3ab452d23f02b5a65f4ada1804ee733e168e6197b0bd6cc79932b6c010000006a473044022069346ec6526454a481690a3664609f9e8032c34553015cfa2e9b25ebb420a33002206998f21a2aa771ad92a0c1083f4181a3acdb0d42ca51d01be1309da2ffb9cecf012102b4568cc6ee751f6d39f4a908b1fcffdb878f5f784a26a48c0acb0acff9d88e3bfeffffff966d9d969cd5f95bfd53003a35fcc1a50f4fb51f211596e6472583fdc5d38470000000006b4830450221009c9757515009c5709b5b678d678185202b817ef9a69ffb954144615ab11762210220732216384da4bf79340e9c46d0effba6ba92982cca998adfc3f354cec7715f800121035f7c3e077108035026f4ebd5d6ca696ef088d4f34d45d94eab4c41202ec74f9bfefffffff8d5062f5b04455c6cfa7e3f250e5a4fb44308ba2b86baf77f9ad0d782f57071010000006a47304402207f9f7dd91fe537a26d5554105977e3949a5c8c4ef53a6a3bff6da2d36eff928f02202b9427bef487a1825fd0c3c6851d17d5f19e6d73dfee22bf06db591929a2044d012102b4568cc6ee751f6d39f4a908b1fcffdb878f5f784a26a48c0acb0acff9d88e3bfeffffff02809698000000000017a914c82753548fdf4be1c3c7b14872c90b5198e67eaa876e642500000000001976a914e2365ec29471b3e271388b22eadf0e7f54d307a788ac6f771200") + val scriptHash: BinaryData = Crypto.sha256(referenceTx.txOut(0).publicKeyScript).reverse + import scala.concurrent.ExecutionContext.Implicits.global + + override protected def beforeAll(): Unit = { + val stream = classOf[ElectrumClientSpec].getResourceAsStream("/electrum/servers_testnet.json") + val addresses = Random.shuffle(ElectrumClientPool.readServerAddresses(stream)) + stream.close() + router = system.actorOf(Props(new ElectrumClientPool(addresses)), "electrum-client") + } + + override protected def afterAll(): Unit = { + TestKit.shutdownActorSystem(system) + } + + test("connect to an electrumx testnet server") { + probe.send(router, AddStatusListener(probe.ref)) + probe.expectMsgType[ElectrumReady](15 seconds) + } + + test("get transaction") { + probe.send(router, GetTransaction("c5efb5cbd35a44ba956b18100be0a91c9c33af4c7f31be20e33741d95f04e202")) + val GetTransactionResponse(tx) = probe.expectMsgType[GetTransactionResponse] + assert(tx.txid == BinaryData("c5efb5cbd35a44ba956b18100be0a91c9c33af4c7f31be20e33741d95f04e202")) + } + + test("get merkle tree") { + probe.send(router, GetMerkle("c5efb5cbd35a44ba956b18100be0a91c9c33af4c7f31be20e33741d95f04e202", 1210223L)) + val response = probe.expectMsgType[GetMerkleResponse] + assert(response.txid == BinaryData("c5efb5cbd35a44ba956b18100be0a91c9c33af4c7f31be20e33741d95f04e202")) + assert(response.block_height == 1210223L) + assert(response.pos == 28) + assert(response.root == BinaryData("fb0234a21e96913682bc4108bcf72b67fb5d2dd680875b7e4671c03ccf523a20")) + } + + test("header subscription") { + val probe1 = TestProbe() + probe1.send(router, HeaderSubscription(probe1.ref)) + val HeaderSubscriptionResponse(header) = probe1.expectMsgType[HeaderSubscriptionResponse] + logger.info(s"received header for block ${header.block_hash}") + } + + test("scripthash subscription") { + val probe1 = TestProbe() + probe1.send(router, ScriptHashSubscription(scriptHash, probe1.ref)) + val ScriptHashSubscriptionResponse(scriptHash1, status) = probe1.expectMsgType[ScriptHashSubscriptionResponse] + assert(status != "") + } + + test("get scripthash history") { + probe.send(router, GetScriptHashHistory(scriptHash)) + val GetScriptHashHistoryResponse(scriptHash1, history) = probe.expectMsgType[GetScriptHashHistoryResponse] + assert(history.contains((TransactionHistoryItem(1210224, "3903726806aa044fe59f40e42eed71bded068b43aaa9e2d716e38b7825412de0")))) + } + + test("list script unspents") { + probe.send(router, ScriptHashListUnspent(scriptHash)) + val ScriptHashListUnspentResponse(scriptHash1, unspents) = probe.expectMsgType[ScriptHashListUnspentResponse] + assert(unspents.contains(UnspentItem("3903726806aa044fe59f40e42eed71bded068b43aaa9e2d716e38b7825412de0", 0, 10000000L, 1210224L))) + } +} diff --git a/eclair-core/src/test/scala/fr/acinq/eclair/blockchain/electrum/ElectrumClientSpec.scala b/eclair-core/src/test/scala/fr/acinq/eclair/blockchain/electrum/ElectrumClientSpec.scala index bef24beea..006b13d02 100644 --- a/eclair-core/src/test/scala/fr/acinq/eclair/blockchain/electrum/ElectrumClientSpec.scala +++ b/eclair-core/src/test/scala/fr/acinq/eclair/blockchain/electrum/ElectrumClientSpec.scala @@ -1,5 +1,23 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + 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.{BinaryData, Crypto, Transaction} @@ -8,6 +26,7 @@ import org.junit.runner.RunWith import org.scalatest.junit.JUnitRunner import org.scalatest.{BeforeAndAfterAll, FunSuiteLike} +import scala.concurrent.ExecutionContext.Implicits.global import scala.concurrent.duration._ @RunWith(classOf[JUnitRunner]) @@ -21,10 +40,7 @@ class ElectrumClientSpec extends TestKit(ActorSystem("test")) with FunSuiteLike val scriptHash: BinaryData = Crypto.sha256(referenceTx.txOut(0).publicKeyScript).reverse override protected def beforeAll(): Unit = { - val stream = classOf[ElectrumClientSpec].getResourceAsStream("/electrum/servers_testnet.json") - val addresses = ElectrumClient.readServerAddresses(stream) - stream.close() - client = system.actorOf(Props(new ElectrumClient(addresses)), "electrum-client") + client = system.actorOf(Props(new ElectrumClient(new InetSocketAddress("testnet.qtornado.com", 51001))), "electrum-client") } override protected def afterAll(): Unit = { @@ -33,7 +49,7 @@ class ElectrumClientSpec extends TestKit(ActorSystem("test")) with FunSuiteLike test("connect to an electrumx testnet server") { probe.send(client, AddStatusListener(probe.ref)) - probe.expectMsg(15 seconds, ElectrumReady) + probe.expectMsgType[ElectrumReady](15 seconds) } test("get transaction") { @@ -42,6 +58,12 @@ class ElectrumClientSpec extends TestKit(ActorSystem("test")) with FunSuiteLike assert(tx.txid == BinaryData("c5efb5cbd35a44ba956b18100be0a91c9c33af4c7f31be20e33741d95f04e202")) } + test("get header") { + probe.send(client, GetHeader(10000)) + val GetHeaderResponse(header) = probe.expectMsgType[GetHeaderResponse] + assert(header.block_hash == BinaryData("000000000058b74204bb9d59128e7975b683ac73910660b6531e59523fb4a102")) + } + test("get merkle tree") { probe.send(client, GetMerkle("c5efb5cbd35a44ba956b18100be0a91c9c33af4c7f31be20e33741d95f04e202", 1210223L)) val response = probe.expectMsgType[GetMerkleResponse] diff --git a/eclair-core/src/test/scala/fr/acinq/eclair/blockchain/electrum/ElectrumWalletBaseSpec.scala b/eclair-core/src/test/scala/fr/acinq/eclair/blockchain/electrum/ElectrumWalletBaseSpec.scala index 945b9f01c..5687244b5 100644 --- a/eclair-core/src/test/scala/fr/acinq/eclair/blockchain/electrum/ElectrumWalletBaseSpec.scala +++ b/eclair-core/src/test/scala/fr/acinq/eclair/blockchain/electrum/ElectrumWalletBaseSpec.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.blockchain.electrum import java.io.File @@ -66,7 +82,8 @@ class IntegrationSpec extends TestKit(ActorSystem("test")) with FunSuiteLike wit sender.expectMsgType[JValue](10 seconds) startElectrum - electrumClient = system.actorOf(Props(new ElectrumClient(Seq(new InetSocketAddress("localhost", 51001))))) + // FIXME use docker + electrumClient = system.actorOf(Props(new ElectrumClient(new InetSocketAddress("localhost", 51001)))) sender.send(electrumClient, ElectrumClient.AddStatusListener(sender.ref)) sender.expectMsg(3 seconds, ElectrumClient.ElectrumReady) } diff --git a/eclair-core/src/test/scala/fr/acinq/eclair/blockchain/electrum/ElectrumWalletBasicSpec.scala b/eclair-core/src/test/scala/fr/acinq/eclair/blockchain/electrum/ElectrumWalletBasicSpec.scala index 1da45e998..05f6210b0 100644 --- a/eclair-core/src/test/scala/fr/acinq/eclair/blockchain/electrum/ElectrumWalletBasicSpec.scala +++ b/eclair-core/src/test/scala/fr/acinq/eclair/blockchain/electrum/ElectrumWalletBasicSpec.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.blockchain.electrum import fr.acinq.bitcoin.Crypto.PrivateKey @@ -146,6 +162,20 @@ class ElectrumWalletBasicSpec extends FunSuite { } } + test("spend all our balance") { + val state1 = addFunds(state, state.accountKeys(0), 1 btc) + val state2 = addFunds(state1, state1.accountKeys(1), 2 btc) + val state3 = addFunds(state2, state2.changeKeys(0), 0.5 btc) + assert(state3.utxos.length == 3) + assert(state3.balance == (Satoshi(350000000),Satoshi(0))) + + val (tx, fee) = state3.spendAll(Script.pay2wpkh(BinaryData("01" * 20)), feeRatePerKw) + val Some((received, sent, Some(fee1))) = state3.computeTransactionDelta(tx) + assert(received == Satoshi(0)) + assert(fee == fee1) + assert(tx.txOut.map(_.amount).sum + fee == state3.balance._1 + state3.balance._2) + } + test("fuzzy test") { val random = new Random() (0 to 10) foreach { _ => diff --git a/eclair-core/src/test/scala/fr/acinq/eclair/blockchain/electrum/ElectrumWalletSimulatedClientSpec.scala b/eclair-core/src/test/scala/fr/acinq/eclair/blockchain/electrum/ElectrumWalletSimulatedClientSpec.scala index f70524094..cd2515e0d 100644 --- a/eclair-core/src/test/scala/fr/acinq/eclair/blockchain/electrum/ElectrumWalletSimulatedClientSpec.scala +++ b/eclair-core/src/test/scala/fr/acinq/eclair/blockchain/electrum/ElectrumWalletSimulatedClientSpec.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.blockchain.electrum import akka.actor.{Actor, ActorSystem, Props} @@ -42,7 +58,7 @@ class ElectrumWalletSimulatedClientSpec extends TestKit(ActorSystem("test")) wit test("wait until wallet is ready") { - sender.send(wallet, ElectrumClient.ElectrumReady) + sender.send(wallet, ElectrumClient.ElectrumReady(header1)) sender.send(wallet, ElectrumClient.HeaderSubscriptionResponse(header1)) awaitCond(wallet.stateName == ElectrumWallet.RUNNING) assert(listener.expectMsgType[WalletReady].timestamp == header1.timestamp) @@ -61,7 +77,7 @@ class ElectrumWalletSimulatedClientSpec extends TestKit(ActorSystem("test")) wit awaitCond(wallet.stateName == ElectrumWallet.DISCONNECTED) // reconnect wallet - sender.send(wallet, ElectrumClient.ElectrumReady) + sender.send(wallet, ElectrumClient.ElectrumReady(header3)) sender.send(wallet, ElectrumClient.HeaderSubscriptionResponse(header3)) awaitCond(wallet.stateName == ElectrumWallet.RUNNING) diff --git a/eclair-core/src/test/scala/fr/acinq/eclair/blockchain/electrum/ElectrumWalletSpec.scala b/eclair-core/src/test/scala/fr/acinq/eclair/blockchain/electrum/ElectrumWalletSpec.scala index ad78a907d..3b2a1973c 100644 --- a/eclair-core/src/test/scala/fr/acinq/eclair/blockchain/electrum/ElectrumWalletSpec.scala +++ b/eclair-core/src/test/scala/fr/acinq/eclair/blockchain/electrum/ElectrumWalletSpec.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.blockchain.electrum import akka.actor.{ActorRef, Props} diff --git a/eclair-core/src/test/scala/fr/acinq/eclair/blockchain/electrum/ElectrumWatcherSpec.scala b/eclair-core/src/test/scala/fr/acinq/eclair/blockchain/electrum/ElectrumWatcherSpec.scala index c0b1a17ec..de167d3e1 100644 --- a/eclair-core/src/test/scala/fr/acinq/eclair/blockchain/electrum/ElectrumWatcherSpec.scala +++ b/eclair-core/src/test/scala/fr/acinq/eclair/blockchain/electrum/ElectrumWatcherSpec.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.blockchain.electrum import akka.actor.Props diff --git a/eclair-core/src/test/scala/fr/acinq/eclair/blockchain/fee/BitgoFeeProviderSpec.scala b/eclair-core/src/test/scala/fr/acinq/eclair/blockchain/fee/BitgoFeeProviderSpec.scala index ee0e6e750..aecbda0fb 100644 --- a/eclair-core/src/test/scala/fr/acinq/eclair/blockchain/fee/BitgoFeeProviderSpec.scala +++ b/eclair-core/src/test/scala/fr/acinq/eclair/blockchain/fee/BitgoFeeProviderSpec.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.blockchain.fee import akka.actor.ActorSystem diff --git a/eclair-core/src/test/scala/fr/acinq/eclair/blockchain/fee/EarnDotComFeeProviderSpec.scala b/eclair-core/src/test/scala/fr/acinq/eclair/blockchain/fee/EarnDotComFeeProviderSpec.scala index 80f13b9f5..93f7731fe 100644 --- a/eclair-core/src/test/scala/fr/acinq/eclair/blockchain/fee/EarnDotComFeeProviderSpec.scala +++ b/eclair-core/src/test/scala/fr/acinq/eclair/blockchain/fee/EarnDotComFeeProviderSpec.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.blockchain.fee import akka.actor.ActorSystem diff --git a/eclair-core/src/test/scala/fr/acinq/eclair/blockchain/fee/FallbackFeeProviderSpec.scala b/eclair-core/src/test/scala/fr/acinq/eclair/blockchain/fee/FallbackFeeProviderSpec.scala index 933b890f0..185ad4851 100644 --- a/eclair-core/src/test/scala/fr/acinq/eclair/blockchain/fee/FallbackFeeProviderSpec.scala +++ b/eclair-core/src/test/scala/fr/acinq/eclair/blockchain/fee/FallbackFeeProviderSpec.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.blockchain.fee import org.junit.runner.RunWith diff --git a/eclair-core/src/test/scala/fr/acinq/eclair/channel/FuzzyPipe.scala b/eclair-core/src/test/scala/fr/acinq/eclair/channel/FuzzyPipe.scala index 8a174fa3a..2963e1291 100644 --- a/eclair-core/src/test/scala/fr/acinq/eclair/channel/FuzzyPipe.scala +++ b/eclair-core/src/test/scala/fr/acinq/eclair/channel/FuzzyPipe.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.channel import akka.actor.{Actor, ActorLogging, ActorRef, Stash} diff --git a/eclair-core/src/test/scala/fr/acinq/eclair/channel/FuzzySpec.scala b/eclair-core/src/test/scala/fr/acinq/eclair/channel/FuzzySpec.scala index d5493131b..09451818f 100644 --- a/eclair-core/src/test/scala/fr/acinq/eclair/channel/FuzzySpec.scala +++ b/eclair-core/src/test/scala/fr/acinq/eclair/channel/FuzzySpec.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.channel import java.util.concurrent.CountDownLatch @@ -10,6 +26,7 @@ import fr.acinq.eclair.TestConstants.{Alice, Bob} import fr.acinq.eclair._ import fr.acinq.eclair.blockchain._ import fr.acinq.eclair.channel.states.StateTestsHelperMethods +import fr.acinq.eclair.payment.PaymentLifecycle.ReceivePayment import fr.acinq.eclair.payment._ import fr.acinq.eclair.router.Hop import fr.acinq.eclair.wire._ diff --git a/eclair-core/src/test/scala/fr/acinq/eclair/channel/states/StateTestsHelperMethods.scala b/eclair-core/src/test/scala/fr/acinq/eclair/channel/states/StateTestsHelperMethods.scala index fae892c64..3c30514dc 100644 --- a/eclair-core/src/test/scala/fr/acinq/eclair/channel/states/StateTestsHelperMethods.scala +++ b/eclair-core/src/test/scala/fr/acinq/eclair/channel/states/StateTestsHelperMethods.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.channel.states import akka.testkit.{TestFSMRef, TestKitBase, TestProbe} diff --git a/eclair-core/src/test/scala/fr/acinq/eclair/channel/states/a/WaitForAcceptChannelStateSpec.scala b/eclair-core/src/test/scala/fr/acinq/eclair/channel/states/a/WaitForAcceptChannelStateSpec.scala index cf6d4fdd4..d8385c7b8 100644 --- a/eclair-core/src/test/scala/fr/acinq/eclair/channel/states/a/WaitForAcceptChannelStateSpec.scala +++ b/eclair-core/src/test/scala/fr/acinq/eclair/channel/states/a/WaitForAcceptChannelStateSpec.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.channel.states.a import akka.testkit.{TestFSMRef, TestProbe} diff --git a/eclair-core/src/test/scala/fr/acinq/eclair/channel/states/a/WaitForOpenChannelStateSpec.scala b/eclair-core/src/test/scala/fr/acinq/eclair/channel/states/a/WaitForOpenChannelStateSpec.scala index 2c128e432..deff2860f 100644 --- a/eclair-core/src/test/scala/fr/acinq/eclair/channel/states/a/WaitForOpenChannelStateSpec.scala +++ b/eclair-core/src/test/scala/fr/acinq/eclair/channel/states/a/WaitForOpenChannelStateSpec.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.channel.states.a import akka.testkit.{TestFSMRef, TestProbe} diff --git a/eclair-core/src/test/scala/fr/acinq/eclair/channel/states/b/WaitForFundingCreatedInternalStateSpec.scala b/eclair-core/src/test/scala/fr/acinq/eclair/channel/states/b/WaitForFundingCreatedInternalStateSpec.scala index 8e7e39f54..5a89800a2 100644 --- a/eclair-core/src/test/scala/fr/acinq/eclair/channel/states/b/WaitForFundingCreatedInternalStateSpec.scala +++ b/eclair-core/src/test/scala/fr/acinq/eclair/channel/states/b/WaitForFundingCreatedInternalStateSpec.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.channel.states.b import akka.testkit.{TestFSMRef, TestProbe} diff --git a/eclair-core/src/test/scala/fr/acinq/eclair/channel/states/b/WaitForFundingCreatedStateSpec.scala b/eclair-core/src/test/scala/fr/acinq/eclair/channel/states/b/WaitForFundingCreatedStateSpec.scala index b4004be14..684be75b8 100644 --- a/eclair-core/src/test/scala/fr/acinq/eclair/channel/states/b/WaitForFundingCreatedStateSpec.scala +++ b/eclair-core/src/test/scala/fr/acinq/eclair/channel/states/b/WaitForFundingCreatedStateSpec.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.channel.states.b import akka.testkit.{TestFSMRef, TestProbe} diff --git a/eclair-core/src/test/scala/fr/acinq/eclair/channel/states/b/WaitForFundingSignedStateSpec.scala b/eclair-core/src/test/scala/fr/acinq/eclair/channel/states/b/WaitForFundingSignedStateSpec.scala index 178308274..f772deba9 100644 --- a/eclair-core/src/test/scala/fr/acinq/eclair/channel/states/b/WaitForFundingSignedStateSpec.scala +++ b/eclair-core/src/test/scala/fr/acinq/eclair/channel/states/b/WaitForFundingSignedStateSpec.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.channel.states.b import akka.testkit.{TestFSMRef, TestProbe} diff --git a/eclair-core/src/test/scala/fr/acinq/eclair/channel/states/c/WaitForFundingConfirmedStateSpec.scala b/eclair-core/src/test/scala/fr/acinq/eclair/channel/states/c/WaitForFundingConfirmedStateSpec.scala index dd639d5e0..48c31cfb0 100644 --- a/eclair-core/src/test/scala/fr/acinq/eclair/channel/states/c/WaitForFundingConfirmedStateSpec.scala +++ b/eclair-core/src/test/scala/fr/acinq/eclair/channel/states/c/WaitForFundingConfirmedStateSpec.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.channel.states.c import akka.actor.Status.Failure diff --git a/eclair-core/src/test/scala/fr/acinq/eclair/channel/states/c/WaitForFundingLockedStateSpec.scala b/eclair-core/src/test/scala/fr/acinq/eclair/channel/states/c/WaitForFundingLockedStateSpec.scala index 9edbe5894..605e0da34 100644 --- a/eclair-core/src/test/scala/fr/acinq/eclair/channel/states/c/WaitForFundingLockedStateSpec.scala +++ b/eclair-core/src/test/scala/fr/acinq/eclair/channel/states/c/WaitForFundingLockedStateSpec.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.channel.states.c import akka.actor.Status diff --git a/eclair-core/src/test/scala/fr/acinq/eclair/channel/states/e/NormalStateSpec.scala b/eclair-core/src/test/scala/fr/acinq/eclair/channel/states/e/NormalStateSpec.scala index 4c0afd272..98899008e 100644 --- a/eclair-core/src/test/scala/fr/acinq/eclair/channel/states/e/NormalStateSpec.scala +++ b/eclair-core/src/test/scala/fr/acinq/eclair/channel/states/e/NormalStateSpec.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.channel.states.e import akka.actor.ActorRef @@ -652,8 +668,7 @@ class NormalStateSpec extends TestkitBaseClass with StateTestsHelperMethods { } } - // TODO: maybe should be illegal? - ignore("recv CommitSig (two htlcs received with same r)") { case (alice, bob, alice2bob, bob2alice, _, _, _) => + test("recv CommitSig (two htlcs received with same r)") { case (alice, bob, alice2bob, bob2alice, _, _, _) => within(30 seconds) { val sender = TestProbe() val r = BinaryData("42" * 32) diff --git a/eclair-core/src/test/scala/fr/acinq/eclair/channel/states/e/OfflineStateSpec.scala b/eclair-core/src/test/scala/fr/acinq/eclair/channel/states/e/OfflineStateSpec.scala index ae731c677..4a0fb1715 100644 --- a/eclair-core/src/test/scala/fr/acinq/eclair/channel/states/e/OfflineStateSpec.scala +++ b/eclair-core/src/test/scala/fr/acinq/eclair/channel/states/e/OfflineStateSpec.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.channel.states.e import akka.testkit.{TestFSMRef, TestProbe} diff --git a/eclair-core/src/test/scala/fr/acinq/eclair/channel/states/f/ShutdownStateSpec.scala b/eclair-core/src/test/scala/fr/acinq/eclair/channel/states/f/ShutdownStateSpec.scala index 42ac2bf4d..783630e7b 100644 --- a/eclair-core/src/test/scala/fr/acinq/eclair/channel/states/f/ShutdownStateSpec.scala +++ b/eclair-core/src/test/scala/fr/acinq/eclair/channel/states/f/ShutdownStateSpec.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.channel.states.f import akka.actor.Status.Failure diff --git a/eclair-core/src/test/scala/fr/acinq/eclair/channel/states/g/NegotiatingStateSpec.scala b/eclair-core/src/test/scala/fr/acinq/eclair/channel/states/g/NegotiatingStateSpec.scala index 8b5ac5073..0a49f9bb9 100644 --- a/eclair-core/src/test/scala/fr/acinq/eclair/channel/states/g/NegotiatingStateSpec.scala +++ b/eclair-core/src/test/scala/fr/acinq/eclair/channel/states/g/NegotiatingStateSpec.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.channel.states.g import akka.actor.Status.Failure diff --git a/eclair-core/src/test/scala/fr/acinq/eclair/channel/states/h/ClosingStateSpec.scala b/eclair-core/src/test/scala/fr/acinq/eclair/channel/states/h/ClosingStateSpec.scala index 157934fd9..188c6960f 100644 --- a/eclair-core/src/test/scala/fr/acinq/eclair/channel/states/h/ClosingStateSpec.scala +++ b/eclair-core/src/test/scala/fr/acinq/eclair/channel/states/h/ClosingStateSpec.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.channel.states.h import akka.actor.Status.Failure diff --git a/eclair-core/src/test/scala/fr/acinq/eclair/crypto/BitStreamSpec.scala b/eclair-core/src/test/scala/fr/acinq/eclair/crypto/BitStreamSpec.scala index e2fbfa3d9..645397122 100644 --- a/eclair-core/src/test/scala/fr/acinq/eclair/crypto/BitStreamSpec.scala +++ b/eclair-core/src/test/scala/fr/acinq/eclair/crypto/BitStreamSpec.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.crypto import org.junit.runner.RunWith diff --git a/eclair-core/src/test/scala/fr/acinq/eclair/crypto/ChaCha20Poly1305Spec.scala b/eclair-core/src/test/scala/fr/acinq/eclair/crypto/ChaCha20Poly1305Spec.scala index 6c7f19b62..cd4a8a2bc 100644 --- a/eclair-core/src/test/scala/fr/acinq/eclair/crypto/ChaCha20Poly1305Spec.scala +++ b/eclair-core/src/test/scala/fr/acinq/eclair/crypto/ChaCha20Poly1305Spec.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.crypto import fr.acinq.bitcoin.BinaryData diff --git a/eclair-core/src/test/scala/fr/acinq/eclair/crypto/GeneratorsSpec.scala b/eclair-core/src/test/scala/fr/acinq/eclair/crypto/GeneratorsSpec.scala index 8f08a04d4..43fc0ed63 100644 --- a/eclair-core/src/test/scala/fr/acinq/eclair/crypto/GeneratorsSpec.scala +++ b/eclair-core/src/test/scala/fr/acinq/eclair/crypto/GeneratorsSpec.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.crypto import fr.acinq.bitcoin.BinaryData diff --git a/eclair-core/src/test/scala/fr/acinq/eclair/crypto/LocalKeyManagerSpec.scala b/eclair-core/src/test/scala/fr/acinq/eclair/crypto/LocalKeyManagerSpec.scala index 55602f248..f61fcf868 100644 --- a/eclair-core/src/test/scala/fr/acinq/eclair/crypto/LocalKeyManagerSpec.scala +++ b/eclair-core/src/test/scala/fr/acinq/eclair/crypto/LocalKeyManagerSpec.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.crypto import fr.acinq.bitcoin.BinaryData diff --git a/eclair-core/src/test/scala/fr/acinq/eclair/crypto/NoiseDemo.scala b/eclair-core/src/test/scala/fr/acinq/eclair/crypto/NoiseDemo.scala index e4641a7bd..8abbb9ad7 100644 --- a/eclair-core/src/test/scala/fr/acinq/eclair/crypto/NoiseDemo.scala +++ b/eclair-core/src/test/scala/fr/acinq/eclair/crypto/NoiseDemo.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.crypto import akka.actor.{Actor, ActorRef, ActorSystem, Props, Stash} diff --git a/eclair-core/src/test/scala/fr/acinq/eclair/crypto/NoiseSpec.scala b/eclair-core/src/test/scala/fr/acinq/eclair/crypto/NoiseSpec.scala index e98690646..15e68a5e8 100644 --- a/eclair-core/src/test/scala/fr/acinq/eclair/crypto/NoiseSpec.scala +++ b/eclair-core/src/test/scala/fr/acinq/eclair/crypto/NoiseSpec.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.crypto import fr.acinq.bitcoin.BinaryData diff --git a/eclair-core/src/test/scala/fr/acinq/eclair/crypto/ShaChainSpec.scala b/eclair-core/src/test/scala/fr/acinq/eclair/crypto/ShaChainSpec.scala index 49117aad0..e292a23b8 100644 --- a/eclair-core/src/test/scala/fr/acinq/eclair/crypto/ShaChainSpec.scala +++ b/eclair-core/src/test/scala/fr/acinq/eclair/crypto/ShaChainSpec.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.crypto import fr.acinq.bitcoin.{BinaryData, Hash} diff --git a/eclair-core/src/test/scala/fr/acinq/eclair/crypto/SphinxSpec.scala b/eclair-core/src/test/scala/fr/acinq/eclair/crypto/SphinxSpec.scala index 16b456939..ec8fa4cf1 100644 --- a/eclair-core/src/test/scala/fr/acinq/eclair/crypto/SphinxSpec.scala +++ b/eclair-core/src/test/scala/fr/acinq/eclair/crypto/SphinxSpec.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.crypto import fr.acinq.bitcoin.BinaryData diff --git a/eclair-core/src/test/scala/fr/acinq/eclair/crypto/TransportHandlerSpec.scala b/eclair-core/src/test/scala/fr/acinq/eclair/crypto/TransportHandlerSpec.scala index b9f58bc7b..569eb9da5 100644 --- a/eclair-core/src/test/scala/fr/acinq/eclair/crypto/TransportHandlerSpec.scala +++ b/eclair-core/src/test/scala/fr/acinq/eclair/crypto/TransportHandlerSpec.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.crypto import java.nio.charset.Charset diff --git a/eclair-core/src/test/scala/fr/acinq/eclair/db/ChannelStateSpec.scala b/eclair-core/src/test/scala/fr/acinq/eclair/db/ChannelStateSpec.scala index f0e7b0664..478494fd6 100644 --- a/eclair-core/src/test/scala/fr/acinq/eclair/db/ChannelStateSpec.scala +++ b/eclair-core/src/test/scala/fr/acinq/eclair/db/ChannelStateSpec.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.db import fr.acinq.bitcoin.Crypto.{PrivateKey, Scalar} diff --git a/eclair-core/src/test/scala/fr/acinq/eclair/db/SqliteChannelsDbSpec.scala b/eclair-core/src/test/scala/fr/acinq/eclair/db/SqliteChannelsDbSpec.scala index ad1a56187..77098fe93 100644 --- a/eclair-core/src/test/scala/fr/acinq/eclair/db/SqliteChannelsDbSpec.scala +++ b/eclair-core/src/test/scala/fr/acinq/eclair/db/SqliteChannelsDbSpec.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.db import java.sql.DriverManager diff --git a/eclair-core/src/test/scala/fr/acinq/eclair/db/SqliteNetworkDbSpec.scala b/eclair-core/src/test/scala/fr/acinq/eclair/db/SqliteNetworkDbSpec.scala index 37ee3f6cb..01268dc7c 100644 --- a/eclair-core/src/test/scala/fr/acinq/eclair/db/SqliteNetworkDbSpec.scala +++ b/eclair-core/src/test/scala/fr/acinq/eclair/db/SqliteNetworkDbSpec.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.db import java.net.{InetAddress, InetSocketAddress} diff --git a/eclair-core/src/test/scala/fr/acinq/eclair/db/SqlitePaymentsDbSpec.scala b/eclair-core/src/test/scala/fr/acinq/eclair/db/SqlitePaymentsDbSpec.scala index 132d06729..52211208e 100644 --- a/eclair-core/src/test/scala/fr/acinq/eclair/db/SqlitePaymentsDbSpec.scala +++ b/eclair-core/src/test/scala/fr/acinq/eclair/db/SqlitePaymentsDbSpec.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.db import java.sql.DriverManager diff --git a/eclair-core/src/test/scala/fr/acinq/eclair/db/SqlitePeersDbSpec.scala b/eclair-core/src/test/scala/fr/acinq/eclair/db/SqlitePeersDbSpec.scala index 3cbada014..cc81fa625 100644 --- a/eclair-core/src/test/scala/fr/acinq/eclair/db/SqlitePeersDbSpec.scala +++ b/eclair-core/src/test/scala/fr/acinq/eclair/db/SqlitePeersDbSpec.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.db import java.net.{InetAddress, InetSocketAddress} diff --git a/eclair-core/src/test/scala/fr/acinq/eclair/db/SqlitePendingRelayDbSpec.scala b/eclair-core/src/test/scala/fr/acinq/eclair/db/SqlitePendingRelayDbSpec.scala index a41b4c51d..cb4d975dc 100644 --- a/eclair-core/src/test/scala/fr/acinq/eclair/db/SqlitePendingRelayDbSpec.scala +++ b/eclair-core/src/test/scala/fr/acinq/eclair/db/SqlitePendingRelayDbSpec.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.db import java.sql.DriverManager diff --git a/eclair-core/src/test/scala/fr/acinq/eclair/integration/IntegrationSpec.scala b/eclair-core/src/test/scala/fr/acinq/eclair/integration/IntegrationSpec.scala index d73cce982..06a9fbd7e 100644 --- a/eclair-core/src/test/scala/fr/acinq/eclair/integration/IntegrationSpec.scala +++ b/eclair-core/src/test/scala/fr/acinq/eclair/integration/IntegrationSpec.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.integration import java.io.{File, PrintWriter} @@ -18,7 +34,8 @@ import fr.acinq.eclair.channel._ import fr.acinq.eclair.crypto.Sphinx.ErrorPacket import fr.acinq.eclair.io.Peer.Disconnect import fr.acinq.eclair.io.{NodeURI, Peer} -import fr.acinq.eclair.payment.{State => _, _} +import fr.acinq.eclair.payment.PaymentLifecycle.{State => _, _} +import fr.acinq.eclair.payment.PaymentRequest import fr.acinq.eclair.router.{Announcements, AnnouncementsBatchValidationSpec} import fr.acinq.eclair.wire._ import fr.acinq.eclair.{Globals, Kit, Setup} diff --git a/eclair-core/src/test/scala/fr/acinq/eclair/interop/rustytests/RustyTestsSpec.scala b/eclair-core/src/test/scala/fr/acinq/eclair/interop/rustytests/RustyTestsSpec.scala index d1c830482..2cbb54900 100644 --- a/eclair-core/src/test/scala/fr/acinq/eclair/interop/rustytests/RustyTestsSpec.scala +++ b/eclair-core/src/test/scala/fr/acinq/eclair/interop/rustytests/RustyTestsSpec.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.interop.rustytests import java.io.File @@ -73,7 +89,7 @@ class RustyTestsSpec extends TestKit(ActorSystem("test")) with Matchers with fix test("01-offer1") { case (ref, res) => assert(ref === res) } test("02-offer2") { case (ref, res) => assert(ref === res) } - //test("03-fulfill1") { case (ref, res) => assert(ref === res) } TODO: check + //test("03-fulfill1") { case (ref, res) => assert(ref === res) } // test("04-two-commits-onedir") { case (ref, res) => assert(ref === res) } DOES NOT PASS : we now automatically sign back when we receive a revocation and have acked changes // test("05-two-commits-in-flight") { case (ref, res) => assert(ref === res)} DOES NOT PASS : cannot send two commit in a row (without having first revocation) test("10-offers-crossover") { case (ref, res) => assert(ref === res) } diff --git a/eclair-core/src/test/scala/fr/acinq/eclair/interop/rustytests/SynchronizationPipe.scala b/eclair-core/src/test/scala/fr/acinq/eclair/interop/rustytests/SynchronizationPipe.scala index e316aca43..3c6b7223a 100644 --- a/eclair-core/src/test/scala/fr/acinq/eclair/interop/rustytests/SynchronizationPipe.scala +++ b/eclair-core/src/test/scala/fr/acinq/eclair/interop/rustytests/SynchronizationPipe.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.interop.rustytests import java.io.{BufferedWriter, File, FileWriter} diff --git a/eclair-core/src/test/scala/fr/acinq/eclair/io/NodeURISpec.scala b/eclair-core/src/test/scala/fr/acinq/eclair/io/NodeURISpec.scala index 992086476..7c2520e79 100644 --- a/eclair-core/src/test/scala/fr/acinq/eclair/io/NodeURISpec.scala +++ b/eclair-core/src/test/scala/fr/acinq/eclair/io/NodeURISpec.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.io import org.junit.runner.RunWith diff --git a/eclair-core/src/test/scala/fr/acinq/eclair/io/PeerSpec.scala b/eclair-core/src/test/scala/fr/acinq/eclair/io/PeerSpec.scala index 3649f4610..9393f61f4 100644 --- a/eclair-core/src/test/scala/fr/acinq/eclair/io/PeerSpec.scala +++ b/eclair-core/src/test/scala/fr/acinq/eclair/io/PeerSpec.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.io import akka.actor.ActorRef diff --git a/eclair-core/src/test/scala/fr/acinq/eclair/payment/HtlcGenerationSpec.scala b/eclair-core/src/test/scala/fr/acinq/eclair/payment/HtlcGenerationSpec.scala index 4444ea727..0b6fdfb6a 100644 --- a/eclair-core/src/test/scala/fr/acinq/eclair/payment/HtlcGenerationSpec.scala +++ b/eclair-core/src/test/scala/fr/acinq/eclair/payment/HtlcGenerationSpec.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.payment import fr.acinq.bitcoin.DeterministicWallet.ExtendedPrivateKey diff --git a/eclair-core/src/test/scala/fr/acinq/eclair/payment/PaymentHandlerSpec.scala b/eclair-core/src/test/scala/fr/acinq/eclair/payment/PaymentHandlerSpec.scala index a777e362c..d68b17c00 100644 --- a/eclair-core/src/test/scala/fr/acinq/eclair/payment/PaymentHandlerSpec.scala +++ b/eclair-core/src/test/scala/fr/acinq/eclair/payment/PaymentHandlerSpec.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.payment import akka.actor.{ActorSystem, Status} @@ -7,6 +23,7 @@ import fr.acinq.bitcoin.{MilliSatoshi, Satoshi} import fr.acinq.eclair.Globals import fr.acinq.eclair.TestConstants.Alice import fr.acinq.eclair.channel.{CMD_FAIL_HTLC, CMD_FULFILL_HTLC} +import fr.acinq.eclair.payment.PaymentLifecycle.{CheckPayment, ReceivePayment} import fr.acinq.eclair.wire.{FinalExpiryTooSoon, UpdateAddHtlc} import org.junit.runner.RunWith import org.scalatest.FunSuiteLike diff --git a/eclair-core/src/test/scala/fr/acinq/eclair/payment/PaymentLifecycleSpec.scala b/eclair-core/src/test/scala/fr/acinq/eclair/payment/PaymentLifecycleSpec.scala index d8dcc697c..b2eedc145 100644 --- a/eclair-core/src/test/scala/fr/acinq/eclair/payment/PaymentLifecycleSpec.scala +++ b/eclair-core/src/test/scala/fr/acinq/eclair/payment/PaymentLifecycleSpec.scala @@ -1,15 +1,32 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.payment import akka.actor.FSM.{CurrentState, SubscribeTransitionCallBack, Transition} import akka.actor.Status import akka.testkit.{TestFSMRef, TestProbe} -import fr.acinq.bitcoin.MilliSatoshi +import fr.acinq.bitcoin.{BinaryData, MilliSatoshi} import fr.acinq.eclair.Globals import fr.acinq.eclair.blockchain.WatchEventSpentBasic import fr.acinq.eclair.channel.Register.ForwardShortId import fr.acinq.eclair.channel.{AddHtlcFailed, BITCOIN_FUNDING_EXTERNAL_CHANNEL_SPENT, ChannelUnavailable} import fr.acinq.eclair.crypto.Sphinx import fr.acinq.eclair.crypto.Sphinx.ErrorPacket +import fr.acinq.eclair.payment.PaymentLifecycle._ import fr.acinq.eclair.router._ import fr.acinq.eclair.wire._ import org.junit.runner.RunWith @@ -23,6 +40,9 @@ class PaymentLifecycleSpec extends BaseRouterSpec { val initialBlockCount = 420000 Globals.blockCount.set(initialBlockCount) + + val defaultAmountMsat = 142000000L + val defaultPaymentHash = BinaryData("42" * 32) test("payment failed (route not found)") { case (router, _) => val paymentFSM = system.actorOf(PaymentLifecycle.props(a, router, TestProbe().ref)) @@ -32,13 +52,28 @@ class PaymentLifecycleSpec extends BaseRouterSpec { paymentFSM ! SubscribeTransitionCallBack(monitor.ref) val CurrentState(_, WAITING_FOR_REQUEST) = monitor.expectMsgClass(classOf[CurrentState[_]]) - val request = SendPayment(142000L, "42" * 32, f) + val request = SendPayment(defaultAmountMsat, defaultPaymentHash, f) sender.send(paymentFSM, request) val Transition(_, WAITING_FOR_REQUEST, WAITING_FOR_ROUTE) = monitor.expectMsgClass(classOf[Transition[_]]) sender.expectMsg(PaymentFailed(request.paymentHash, LocalFailure(RouteNotFound) :: Nil)) } + test("payment failed (route too expensive)") { case (router, _) => + val paymentFSM = system.actorOf(PaymentLifecycle.props(a, router, TestProbe().ref)) + val monitor = TestProbe() + val sender = TestProbe() + + paymentFSM ! SubscribeTransitionCallBack(monitor.ref) + val CurrentState(_, WAITING_FOR_REQUEST) = monitor.expectMsgClass(classOf[CurrentState[_]]) + + val request = SendPayment(defaultAmountMsat, defaultPaymentHash, d, maxFeePct = 0.001) + sender.send(paymentFSM, request) + val Transition(_, WAITING_FOR_REQUEST, WAITING_FOR_ROUTE) = monitor.expectMsgClass(classOf[Transition[_]]) + + val Seq(LocalFailure(RouteTooExpensive(_, _))) = sender.expectMsgType[PaymentFailed].failures + } + test("payment failed (unparsable failure)") { case (router, _) => val relayer = TestProbe() val routerForwarder = TestProbe() @@ -49,7 +84,7 @@ class PaymentLifecycleSpec extends BaseRouterSpec { paymentFSM ! SubscribeTransitionCallBack(monitor.ref) val CurrentState(_, WAITING_FOR_REQUEST) = monitor.expectMsgClass(classOf[CurrentState[_]]) - val request = SendPayment(142000L, "42" * 32, d, maxAttempts = 2) + val request = SendPayment(defaultAmountMsat, defaultPaymentHash, d, maxAttempts = 2) sender.send(paymentFSM, request) awaitCond(paymentFSM.stateName == WAITING_FOR_ROUTE) val WaitingForRoute(_, _, Nil) = paymentFSM.stateData @@ -59,7 +94,7 @@ class PaymentLifecycleSpec extends BaseRouterSpec { val WaitingForComplete(_, _, cmd1, Nil, _, _, _, hops) = paymentFSM.stateData relayer.expectMsg(ForwardShortId(channelId_ab, cmd1)) - sender.send(paymentFSM, UpdateFailHtlc("00" * 32, 0, "42" * 32)) // unparsable message + sender.send(paymentFSM, UpdateFailHtlc("00" * 32, 0, defaultPaymentHash)) // unparsable message // then the payment lifecycle will ask for a new route excluding all intermediate nodes routerForwarder.expectMsg(RouteRequest(a, d, ignoreNodes = Set(c), ignoreChannels = Set.empty)) @@ -70,7 +105,7 @@ class PaymentLifecycleSpec extends BaseRouterSpec { val WaitingForComplete(_, _, cmd2, _, _, _, _, _) = paymentFSM.stateData // and reply a 2nd time with an unparsable failure relayer.expectMsg(ForwardShortId(channelId_ab, cmd2)) - sender.send(paymentFSM, UpdateFailHtlc("00" * 32, 0, "42" * 32)) // unparsable message + sender.send(paymentFSM, UpdateFailHtlc("00" * 32, 0, defaultPaymentHash)) // unparsable message // we allow 2 tries, so we send a 2nd request to the router sender.expectMsg(PaymentFailed(request.paymentHash, UnreadableRemoteFailure(hops) :: UnreadableRemoteFailure(hops) :: Nil)) @@ -86,7 +121,7 @@ class PaymentLifecycleSpec extends BaseRouterSpec { paymentFSM ! SubscribeTransitionCallBack(monitor.ref) val CurrentState(_, WAITING_FOR_REQUEST) = monitor.expectMsgClass(classOf[CurrentState[_]]) - val request = SendPayment(142000L, "42" * 32, d, maxAttempts = 2) + val request = SendPayment(defaultAmountMsat, defaultPaymentHash, d, maxAttempts = 2) sender.send(paymentFSM, request) awaitCond(paymentFSM.stateName == WAITING_FOR_ROUTE) val WaitingForRoute(_, _, Nil) = paymentFSM.stateData @@ -113,7 +148,7 @@ class PaymentLifecycleSpec extends BaseRouterSpec { paymentFSM ! SubscribeTransitionCallBack(monitor.ref) val CurrentState(_, WAITING_FOR_REQUEST) = monitor.expectMsgClass(classOf[CurrentState[_]]) - val request = SendPayment(142000L, "42" * 32, d, maxAttempts = 2) + val request = SendPayment(defaultAmountMsat, defaultPaymentHash, d, maxAttempts = 2) sender.send(paymentFSM, request) awaitCond(paymentFSM.stateName == WAITING_FOR_ROUTE) val WaitingForRoute(_, _, Nil) = paymentFSM.stateData @@ -123,7 +158,7 @@ class PaymentLifecycleSpec extends BaseRouterSpec { val WaitingForComplete(_, _, cmd1, Nil, _, _, _, hops) = paymentFSM.stateData relayer.expectMsg(ForwardShortId(channelId_ab, cmd1)) - sender.send(paymentFSM, UpdateFailMalformedHtlc("00" * 32, 0, "42" * 32, FailureMessageCodecs.BADONION)) + sender.send(paymentFSM, UpdateFailMalformedHtlc("00" * 32, 0, defaultPaymentHash, FailureMessageCodecs.BADONION)) // then the payment lifecycle will ask for a new route excluding the channel routerForwarder.expectMsg(RouteRequest(a, d, assistedRoutes = Nil, ignoreNodes = Set.empty, ignoreChannels = Set(ChannelDesc(channelId_ab, a, b)))) @@ -140,7 +175,7 @@ class PaymentLifecycleSpec extends BaseRouterSpec { paymentFSM ! SubscribeTransitionCallBack(monitor.ref) val CurrentState(_, WAITING_FOR_REQUEST) = monitor.expectMsgClass(classOf[CurrentState[_]]) - val request = SendPayment(142000L, "42" * 32, d, maxAttempts = 2) + val request = SendPayment(defaultAmountMsat, defaultPaymentHash, d, maxAttempts = 2) sender.send(paymentFSM, request) awaitCond(paymentFSM.stateName == WAITING_FOR_ROUTE) val WaitingForRoute(_, _, Nil) = paymentFSM.stateData @@ -176,7 +211,7 @@ class PaymentLifecycleSpec extends BaseRouterSpec { paymentFSM ! SubscribeTransitionCallBack(monitor.ref) val CurrentState(_, WAITING_FOR_REQUEST) = monitor.expectMsgClass(classOf[CurrentState[_]]) - val request = SendPayment(142000L, "42" * 32, d, maxAttempts = 2) + val request = SendPayment(defaultAmountMsat, defaultPaymentHash, d, maxAttempts = 2) sender.send(paymentFSM, request) awaitCond(paymentFSM.stateName == WAITING_FOR_ROUTE) val WaitingForRoute(_, _, Nil) = paymentFSM.stateData @@ -210,12 +245,12 @@ class PaymentLifecycleSpec extends BaseRouterSpec { paymentFSM ! SubscribeTransitionCallBack(monitor.ref) val CurrentState(_, WAITING_FOR_REQUEST) = monitor.expectMsgClass(classOf[CurrentState[_]]) - val request = SendPayment(142000L, "42" * 32, d) + val request = SendPayment(defaultAmountMsat, defaultPaymentHash, d) sender.send(paymentFSM, request) val Transition(_, WAITING_FOR_REQUEST, WAITING_FOR_ROUTE) = monitor.expectMsgClass(classOf[Transition[_]]) val Transition(_, WAITING_FOR_ROUTE, WAITING_FOR_PAYMENT_COMPLETE) = monitor.expectMsgClass(classOf[Transition[_]]) - sender.send(paymentFSM, UpdateFulfillHtlc("00" * 32, 0, "42" * 32)) + sender.send(paymentFSM, UpdateFulfillHtlc("00" * 32, 0, defaultPaymentHash)) val paymentOK = sender.expectMsgType[PaymentSucceeded] assert(paymentOK.amountMsat > request.amountMsat) diff --git a/eclair-core/src/test/scala/fr/acinq/eclair/payment/PaymentRequestSpec.scala b/eclair-core/src/test/scala/fr/acinq/eclair/payment/PaymentRequestSpec.scala index 8f38ed150..58a08b185 100644 --- a/eclair-core/src/test/scala/fr/acinq/eclair/payment/PaymentRequestSpec.scala +++ b/eclair-core/src/test/scala/fr/acinq/eclair/payment/PaymentRequestSpec.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.payment import java.nio.ByteOrder diff --git a/eclair-core/src/test/scala/fr/acinq/eclair/payment/RelayerSpec.scala b/eclair-core/src/test/scala/fr/acinq/eclair/payment/RelayerSpec.scala index 997ff0a50..8e3ea9f66 100644 --- a/eclair-core/src/test/scala/fr/acinq/eclair/payment/RelayerSpec.scala +++ b/eclair-core/src/test/scala/fr/acinq/eclair/payment/RelayerSpec.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.payment import akka.actor.{ActorRef, Status} diff --git a/eclair-core/src/test/scala/fr/acinq/eclair/router/AnnouncementsBatchValidationSpec.scala b/eclair-core/src/test/scala/fr/acinq/eclair/router/AnnouncementsBatchValidationSpec.scala index b1a222a9f..d4ec6d5a2 100644 --- a/eclair-core/src/test/scala/fr/acinq/eclair/router/AnnouncementsBatchValidationSpec.scala +++ b/eclair-core/src/test/scala/fr/acinq/eclair/router/AnnouncementsBatchValidationSpec.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.router import akka.actor.ActorSystem @@ -80,8 +96,8 @@ object AnnouncementsBatchValidationSpec { def makeChannelAnnouncement(c: SimulatedChannel)(implicit extendedBitcoinClient: ExtendedBitcoinClient, ec: ExecutionContext): ChannelAnnouncement = { val (blockHeight, txIndex) = Await.result(extendedBitcoinClient.getTransactionShortId(c.fundingTx.txid.toString()), 10 seconds) val shortChannelId = ShortChannelId(blockHeight, txIndex, c.fundingOutputIndex) - val (channelAnnNodeSig1, channelAnnBitcoinSig1) = Announcements.signChannelAnnouncement(Block.RegtestGenesisBlock.hash, shortChannelId, c.node1Key, c.node2Key.publicKey, c.node1FundingKey, c.node2FundingKey.publicKey, BinaryData("")) - val (channelAnnNodeSig2, channelAnnBitcoinSig2) = Announcements.signChannelAnnouncement(Block.RegtestGenesisBlock.hash, shortChannelId, c.node2Key, c.node1Key.publicKey, c.node2FundingKey, c.node1FundingKey.publicKey, BinaryData("")) + val (channelAnnNodeSig1, channelAnnBitcoinSig1) = Announcements.signChannelAnnouncement(Block.RegtestGenesisBlock.hash, shortChannelId, c.node1Key, c.node2Key.publicKey, c.node1FundingKey, c.node2FundingKey.publicKey, BinaryData.empty) + val (channelAnnNodeSig2, channelAnnBitcoinSig2) = Announcements.signChannelAnnouncement(Block.RegtestGenesisBlock.hash, shortChannelId, c.node2Key, c.node1Key.publicKey, c.node2FundingKey, c.node1FundingKey.publicKey, BinaryData.empty) val channelAnnouncement = Announcements.makeChannelAnnouncement(Block.RegtestGenesisBlock.hash, shortChannelId, c.node1Key.publicKey, c.node2Key.publicKey, c.node1FundingKey.publicKey, c.node2FundingKey.publicKey, channelAnnNodeSig1, channelAnnNodeSig2, channelAnnBitcoinSig1, channelAnnBitcoinSig2) channelAnnouncement } diff --git a/eclair-core/src/test/scala/fr/acinq/eclair/router/AnnouncementsSpec.scala b/eclair-core/src/test/scala/fr/acinq/eclair/router/AnnouncementsSpec.scala index 2bb4f8447..aedc401cd 100644 --- a/eclair-core/src/test/scala/fr/acinq/eclair/router/AnnouncementsSpec.scala +++ b/eclair-core/src/test/scala/fr/acinq/eclair/router/AnnouncementsSpec.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.router import fr.acinq.bitcoin.Crypto.{PrivateKey, PublicKey} diff --git a/eclair-core/src/test/scala/fr/acinq/eclair/router/BaseRouterSpec.scala b/eclair-core/src/test/scala/fr/acinq/eclair/router/BaseRouterSpec.scala index 6d0059b72..f034fdde8 100644 --- a/eclair-core/src/test/scala/fr/acinq/eclair/router/BaseRouterSpec.scala +++ b/eclair-core/src/test/scala/fr/acinq/eclair/router/BaseRouterSpec.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.router import akka.actor.ActorRef diff --git a/eclair-core/src/test/scala/fr/acinq/eclair/router/ChannelRangeQueriesSpec.scala b/eclair-core/src/test/scala/fr/acinq/eclair/router/ChannelRangeQueriesSpec.scala index b6190139b..89582d7eb 100644 --- a/eclair-core/src/test/scala/fr/acinq/eclair/router/ChannelRangeQueriesSpec.scala +++ b/eclair-core/src/test/scala/fr/acinq/eclair/router/ChannelRangeQueriesSpec.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.router import java.nio.ByteOrder diff --git a/eclair-core/src/test/scala/fr/acinq/eclair/router/RouteCalculationSpec.scala b/eclair-core/src/test/scala/fr/acinq/eclair/router/RouteCalculationSpec.scala index 77a8e5d53..cd9cb37ad 100644 --- a/eclair-core/src/test/scala/fr/acinq/eclair/router/RouteCalculationSpec.scala +++ b/eclair-core/src/test/scala/fr/acinq/eclair/router/RouteCalculationSpec.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.router import fr.acinq.bitcoin.Crypto.{PrivateKey, PublicKey} diff --git a/eclair-core/src/test/scala/fr/acinq/eclair/router/RouterSpec.scala b/eclair-core/src/test/scala/fr/acinq/eclair/router/RouterSpec.scala index 798953a7f..c4a57deeb 100644 --- a/eclair-core/src/test/scala/fr/acinq/eclair/router/RouterSpec.scala +++ b/eclair-core/src/test/scala/fr/acinq/eclair/router/RouterSpec.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.router import akka.actor.Status.Failure diff --git a/eclair-core/src/test/scala/fr/acinq/eclair/router/RoutingSyncSpec.scala b/eclair-core/src/test/scala/fr/acinq/eclair/router/RoutingSyncSpec.scala index d35e03575..9aa5a42e7 100644 --- a/eclair-core/src/test/scala/fr/acinq/eclair/router/RoutingSyncSpec.scala +++ b/eclair-core/src/test/scala/fr/acinq/eclair/router/RoutingSyncSpec.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.router import akka.actor.{Actor, ActorRef, Props} diff --git a/eclair-core/src/test/scala/fr/acinq/eclair/transactions/ClaimReceivedHtlcSpec.scala b/eclair-core/src/test/scala/fr/acinq/eclair/transactions/ClaimReceivedHtlcSpec.scala index 594a0a864..0f4365488 100644 --- a/eclair-core/src/test/scala/fr/acinq/eclair/transactions/ClaimReceivedHtlcSpec.scala +++ b/eclair-core/src/test/scala/fr/acinq/eclair/transactions/ClaimReceivedHtlcSpec.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.transactions import fr.acinq.bitcoin.Crypto.PrivateKey diff --git a/eclair-core/src/test/scala/fr/acinq/eclair/transactions/ClaimSentHtlcSpec.scala b/eclair-core/src/test/scala/fr/acinq/eclair/transactions/ClaimSentHtlcSpec.scala index 665871a65..3203d3b86 100644 --- a/eclair-core/src/test/scala/fr/acinq/eclair/transactions/ClaimSentHtlcSpec.scala +++ b/eclair-core/src/test/scala/fr/acinq/eclair/transactions/ClaimSentHtlcSpec.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.transactions import fr.acinq.bitcoin.Crypto.PrivateKey diff --git a/eclair-core/src/test/scala/fr/acinq/eclair/transactions/CommitmentSpecSpec.scala b/eclair-core/src/test/scala/fr/acinq/eclair/transactions/CommitmentSpecSpec.scala index e8f639064..d3bfc6ad4 100644 --- a/eclair-core/src/test/scala/fr/acinq/eclair/transactions/CommitmentSpecSpec.scala +++ b/eclair-core/src/test/scala/fr/acinq/eclair/transactions/CommitmentSpecSpec.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.transactions import fr.acinq.bitcoin.{BinaryData, Crypto} diff --git a/eclair-core/src/test/scala/fr/acinq/eclair/transactions/TestVectorsSpec.scala b/eclair-core/src/test/scala/fr/acinq/eclair/transactions/TestVectorsSpec.scala index a33f1b516..e1458713c 100644 --- a/eclair-core/src/test/scala/fr/acinq/eclair/transactions/TestVectorsSpec.scala +++ b/eclair-core/src/test/scala/fr/acinq/eclair/transactions/TestVectorsSpec.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.transactions import fr.acinq.bitcoin.Crypto.{Point, PrivateKey, PublicKey, Scalar} @@ -135,11 +151,11 @@ class TestVectorsSpec extends FunSuite { ) val htlcs = Seq( - DirectedHtlc(IN, UpdateAddHtlc("00" * 32, 0, MilliSatoshi(1000000).amount, Crypto.sha256(paymentPreimages(0)), 500, BinaryData(""))), - DirectedHtlc(IN, UpdateAddHtlc("00" * 32, 0, MilliSatoshi(2000000).amount, Crypto.sha256(paymentPreimages(1)), 501, BinaryData(""))), - DirectedHtlc(OUT, UpdateAddHtlc("00" * 32, 0, MilliSatoshi(2000000).amount, Crypto.sha256(paymentPreimages(2)), 502, BinaryData(""))), - DirectedHtlc(OUT, UpdateAddHtlc("00" * 32, 0, MilliSatoshi(3000000).amount, Crypto.sha256(paymentPreimages(3)), 503, BinaryData(""))), - DirectedHtlc(IN, UpdateAddHtlc("00" * 32, 0, MilliSatoshi(4000000).amount, Crypto.sha256(paymentPreimages(4)), 504, BinaryData(""))) + DirectedHtlc(IN, UpdateAddHtlc("00" * 32, 0, MilliSatoshi(1000000).amount, Crypto.sha256(paymentPreimages(0)), 500, BinaryData.empty)), + DirectedHtlc(IN, UpdateAddHtlc("00" * 32, 0, MilliSatoshi(2000000).amount, Crypto.sha256(paymentPreimages(1)), 501, BinaryData.empty)), + DirectedHtlc(OUT, UpdateAddHtlc("00" * 32, 0, MilliSatoshi(2000000).amount, Crypto.sha256(paymentPreimages(2)), 502, BinaryData.empty)), + DirectedHtlc(OUT, UpdateAddHtlc("00" * 32, 0, MilliSatoshi(3000000).amount, Crypto.sha256(paymentPreimages(3)), 503, BinaryData.empty)), + DirectedHtlc(IN, UpdateAddHtlc("00" * 32, 0, MilliSatoshi(4000000).amount, Crypto.sha256(paymentPreimages(4)), 504, BinaryData.empty)) ) val htlcScripts = htlcs.map(htlc => htlc.direction match { case OUT => Scripts.htlcOffered(Local.payment_privkey.publicKey, Remote.payment_privkey.publicKey, Local.revocation_pubkey, Crypto.ripemd160(htlc.add.paymentHash)) diff --git a/eclair-core/src/test/scala/fr/acinq/eclair/transactions/TransactionsSpec.scala b/eclair-core/src/test/scala/fr/acinq/eclair/transactions/TransactionsSpec.scala index fc1ab53c5..0904b27bd 100644 --- a/eclair-core/src/test/scala/fr/acinq/eclair/transactions/TransactionsSpec.scala +++ b/eclair-core/src/test/scala/fr/acinq/eclair/transactions/TransactionsSpec.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.transactions import java.nio.ByteOrder @@ -47,10 +63,10 @@ class TransactionsSpec extends FunSuite { test("compute fees") { // see BOLT #3 specs val htlcs = Set( - DirectedHtlc(OUT, UpdateAddHtlc("00" * 32, 0, MilliSatoshi(5000000).amount, Hash.Zeroes, 552, BinaryData(""))), - DirectedHtlc(OUT, UpdateAddHtlc("00" * 32, 0, MilliSatoshi(1000000).amount, Hash.Zeroes, 553, BinaryData(""))), - DirectedHtlc(IN, UpdateAddHtlc("00" * 32, 0, MilliSatoshi(7000000).amount, Hash.Zeroes, 550, BinaryData(""))), - DirectedHtlc(IN, UpdateAddHtlc("00" * 32, 0, MilliSatoshi(800000).amount, Hash.Zeroes, 551, BinaryData(""))) + DirectedHtlc(OUT, UpdateAddHtlc("00" * 32, 0, MilliSatoshi(5000000).amount, Hash.Zeroes, 552, BinaryData.empty)), + DirectedHtlc(OUT, UpdateAddHtlc("00" * 32, 0, MilliSatoshi(1000000).amount, Hash.Zeroes, 553, BinaryData.empty)), + DirectedHtlc(IN, UpdateAddHtlc("00" * 32, 0, MilliSatoshi(7000000).amount, Hash.Zeroes, 550, BinaryData.empty)), + DirectedHtlc(IN, UpdateAddHtlc("00" * 32, 0, MilliSatoshi(800000).amount, Hash.Zeroes, 551, BinaryData.empty)) ) val spec = CommitmentSpec(htlcs, feeratePerKw = 5000, toLocalMsat = 0, toRemoteMsat = 0) val fee = Transactions.commitTxFee(Satoshi(546), spec) @@ -106,7 +122,7 @@ class TransactionsSpec extends FunSuite { // ClaimHtlcSuccessTx // first we create a fake commitTx tx, containing only the output that will be spent by the ClaimHtlcSuccessTx val paymentPreimage = BinaryData("42" * 32) - val htlc = UpdateAddHtlc("00" * 32, 0, Satoshi(20000).amount * 1000, sha256(paymentPreimage), expiry = 400144, BinaryData("")) + val htlc = UpdateAddHtlc("00" * 32, 0, Satoshi(20000).amount * 1000, sha256(paymentPreimage), expiry = 400144, BinaryData.empty) val pubKeyScript = write(pay2wsh(htlcOffered(localHtlcPriv.publicKey, remoteHtlcPriv.publicKey, localRevocationPriv.publicKey, ripemd160(htlc.paymentHash)))) val commitTx = Transaction(version = 0, txIn = Nil, txOut = TxOut(Satoshi(htlc.amountMsat / 1000), pubKeyScript) :: Nil, lockTime = 0) val claimHtlcSuccessTx = makeClaimHtlcSuccessTx(commitTx, localDustLimit, remoteHtlcPriv.publicKey, localHtlcPriv.publicKey, localRevocationPriv.publicKey, finalPubKeyScript, htlc, feeratePerKw) @@ -119,7 +135,7 @@ class TransactionsSpec extends FunSuite { // ClaimHtlcTimeoutTx // first we create a fake commitTx tx, containing only the output that will be spent by the ClaimHtlcSuccessTx val paymentPreimage = BinaryData("42" * 32) - val htlc = UpdateAddHtlc("00" * 32, 0, Satoshi(20000).amount * 1000, sha256(paymentPreimage), expiry = 400144, BinaryData("")) + val htlc = UpdateAddHtlc("00" * 32, 0, Satoshi(20000).amount * 1000, sha256(paymentPreimage), expiry = 400144, BinaryData.empty) val pubKeyScript = write(pay2wsh(htlcReceived(localHtlcPriv.publicKey, remoteHtlcPriv.publicKey, localRevocationPriv.publicKey, ripemd160(htlc.paymentHash), htlc.expiry))) val commitTx = Transaction(version = 0, txIn = Nil, txOut = TxOut(Satoshi(htlc.amountMsat / 1000), pubKeyScript) :: Nil, lockTime = 0) val claimClaimHtlcTimeoutTx = makeClaimHtlcTimeoutTx(commitTx, localDustLimit, remoteHtlcPriv.publicKey, localHtlcPriv.publicKey, localRevocationPriv.publicKey, finalPubKeyScript, htlc, feeratePerKw) @@ -147,14 +163,14 @@ class TransactionsSpec extends FunSuite { // htlc1 and htlc2 are regular IN/OUT htlcs val paymentPreimage1 = BinaryData("11" * 32) - val htlc1 = UpdateAddHtlc("00" * 32, 0, millibtc2satoshi(MilliBtc(100)).amount * 1000, sha256(paymentPreimage1), 300, BinaryData("")) + val htlc1 = UpdateAddHtlc("00" * 32, 0, millibtc2satoshi(MilliBtc(100)).amount * 1000, sha256(paymentPreimage1), 300, BinaryData.empty) val paymentPreimage2 = BinaryData("22" * 32) - val htlc2 = UpdateAddHtlc("00" * 32, 1, millibtc2satoshi(MilliBtc(200)).amount * 1000, sha256(paymentPreimage2), 300, BinaryData("")) + val htlc2 = UpdateAddHtlc("00" * 32, 1, millibtc2satoshi(MilliBtc(200)).amount * 1000, sha256(paymentPreimage2), 300, BinaryData.empty) // htlc3 and htlc4 are dust htlcs IN/OUT htlcs, with an amount large enough to be included in the commit tx, but too small to be claimed at 2nd stage val paymentPreimage3 = BinaryData("33" * 32) - val htlc3 = UpdateAddHtlc("00" * 32, 2, (localDustLimit + weight2fee(feeratePerKw, htlcTimeoutWeight)).amount * 1000, sha256(paymentPreimage3), 300, BinaryData("")) + val htlc3 = UpdateAddHtlc("00" * 32, 2, (localDustLimit + weight2fee(feeratePerKw, htlcTimeoutWeight)).amount * 1000, sha256(paymentPreimage3), 300, BinaryData.empty) val paymentPreimage4 = BinaryData("44" * 32) - val htlc4 = UpdateAddHtlc("00" * 32, 3, (localDustLimit + weight2fee(feeratePerKw, htlcSuccessWeight)).amount * 1000, sha256(paymentPreimage4), 300, BinaryData("")) + val htlc4 = UpdateAddHtlc("00" * 32, 3, (localDustLimit + weight2fee(feeratePerKw, htlcSuccessWeight)).amount * 1000, sha256(paymentPreimage4), 300, BinaryData.empty) val spec = CommitmentSpec( htlcs = Set( DirectedHtlc(OUT, htlc1), diff --git a/eclair-core/src/test/scala/fr/acinq/eclair/wire/ChannelCodecsSpec.scala b/eclair-core/src/test/scala/fr/acinq/eclair/wire/ChannelCodecsSpec.scala index 679880ccb..48cb26052 100644 --- a/eclair-core/src/test/scala/fr/acinq/eclair/wire/ChannelCodecsSpec.scala +++ b/eclair-core/src/test/scala/fr/acinq/eclair/wire/ChannelCodecsSpec.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.wire import fr.acinq.bitcoin.DeterministicWallet.KeyPath diff --git a/eclair-core/src/test/scala/fr/acinq/eclair/wire/CommandCodecsSpec.scala b/eclair-core/src/test/scala/fr/acinq/eclair/wire/CommandCodecsSpec.scala index 1e142494e..dcf4356ea 100644 --- a/eclair-core/src/test/scala/fr/acinq/eclair/wire/CommandCodecsSpec.scala +++ b/eclair-core/src/test/scala/fr/acinq/eclair/wire/CommandCodecsSpec.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.wire import fr.acinq.eclair.channel.{CMD_FAIL_HTLC, CMD_FAIL_MALFORMED_HTLC, CMD_FULFILL_HTLC, Command} diff --git a/eclair-core/src/test/scala/fr/acinq/eclair/wire/FailureMessageCodecsSpec.scala b/eclair-core/src/test/scala/fr/acinq/eclair/wire/FailureMessageCodecsSpec.scala index 738f90067..7777890ab 100644 --- a/eclair-core/src/test/scala/fr/acinq/eclair/wire/FailureMessageCodecsSpec.scala +++ b/eclair-core/src/test/scala/fr/acinq/eclair/wire/FailureMessageCodecsSpec.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.wire import fr.acinq.bitcoin.{BinaryData, Block} diff --git a/eclair-core/src/test/scala/fr/acinq/eclair/wire/LightningMessageCodecsSpec.scala b/eclair-core/src/test/scala/fr/acinq/eclair/wire/LightningMessageCodecsSpec.scala index f7b7b6e24..bfb8f9261 100644 --- a/eclair-core/src/test/scala/fr/acinq/eclair/wire/LightningMessageCodecsSpec.scala +++ b/eclair-core/src/test/scala/fr/acinq/eclair/wire/LightningMessageCodecsSpec.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair.wire import java.net.{InetAddress, InetSocketAddress} diff --git a/eclair-node/pom.xml b/eclair-node/pom.xml index 148aceed9..5f4b7e336 100644 --- a/eclair-node/pom.xml +++ b/eclair-node/pom.xml @@ -1,4 +1,20 @@ + + 4.0.0 diff --git a/eclair-node/src/main/resources/logback.xml b/eclair-node/src/main/resources/logback.xml index 4d5f81c63..f93ac4aee 100644 --- a/eclair-node/src/main/resources/logback.xml +++ b/eclair-node/src/main/resources/logback.xml @@ -1,4 +1,20 @@ + + diff --git a/eclair-node/src/main/resources/logback_colors.xml b/eclair-node/src/main/resources/logback_colors.xml index dc3ada972..d281f7c11 100644 --- a/eclair-node/src/main/resources/logback_colors.xml +++ b/eclair-node/src/main/resources/logback_colors.xml @@ -1,4 +1,20 @@ + + diff --git a/eclair-node/src/main/scala/fr/acinq/eclair/Boot.scala b/eclair-node/src/main/scala/fr/acinq/eclair/Boot.scala index 6871431ea..d210a57d2 100644 --- a/eclair-node/src/main/scala/fr/acinq/eclair/Boot.scala +++ b/eclair-node/src/main/scala/fr/acinq/eclair/Boot.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair import java.io.File diff --git a/eclair-node/src/main/scala/fr/acinq/eclair/Textui.scala b/eclair-node/src/main/scala/fr/acinq/eclair/Textui.scala index cf2870847..cad707936 100644 --- a/eclair-node/src/main/scala/fr/acinq/eclair/Textui.scala +++ b/eclair-node/src/main/scala/fr/acinq/eclair/Textui.scala @@ -1,21 +1,38 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair import java.util.concurrent.atomic.AtomicBoolean import akka.actor.{ActorRef, Props, SupervisorStrategy} +import akka.pattern.ask +import akka.util.Timeout import com.googlecode.lanterna.gui2.dialogs.TextInputDialogBuilder import com.googlecode.lanterna.input.KeyStroke import com.googlecode.lanterna.{TerminalPosition, TerminalSize} import fr.acinq.bitcoin.Crypto.PublicKey -import fr.acinq.bitcoin.{BinaryData, MilliBtc, MilliSatoshi, Satoshi} +import fr.acinq.bitcoin.{BinaryData, MilliSatoshi, Satoshi} import fr.acinq.eclair.channel.State import fr.acinq.eclair.io.{NodeURI, Peer} -import fr.acinq.eclair.payment.{PaymentRequest, SendPayment} +import fr.acinq.eclair.payment.PaymentLifecycle.SendPayment +import fr.acinq.eclair.payment.PaymentRequest import grizzled.slf4j.Logging import scala.collection.JavaConversions._ -import akka.pattern.ask -import akka.util.Timeout import scala.concurrent.duration._ /** diff --git a/eclair-node/src/main/scala/fr/acinq/eclair/TextuiUpdater.scala b/eclair-node/src/main/scala/fr/acinq/eclair/TextuiUpdater.scala index 57f6b4cb6..9cdce3489 100644 --- a/eclair-node/src/main/scala/fr/acinq/eclair/TextuiUpdater.scala +++ b/eclair-node/src/main/scala/fr/acinq/eclair/TextuiUpdater.scala @@ -1,3 +1,19 @@ +/* + * Copyright 2018 ACINQ SAS + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package fr.acinq.eclair import akka.actor.Actor diff --git a/pom.xml b/pom.xml index 00dc008d2..8abb94673 100644 --- a/pom.xml +++ b/pom.xml @@ -1,3 +1,19 @@ + + 4.0.0