mirror of
https://github.com/ACINQ/eclair.git
synced 2024-11-19 01:43:22 +01:00
parent
7f747d55fd
commit
d86dd72d78
0
eclair-node/eclair-cli → eclair-core/eclair-cli
Executable file → Normal file
0
eclair-node/eclair-cli → eclair-core/eclair-cli
Executable file → Normal file
198
eclair-core/pom.xml
Normal file
198
eclair-core/pom.xml
Normal file
@ -0,0 +1,198 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>fr.acinq.eclair</groupId>
|
||||
<artifactId>eclair_2.11</artifactId>
|
||||
<version>0.2-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>eclair-core_2.11</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>${project.artifactId}</name>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>pl.project13.maven</groupId>
|
||||
<artifactId>git-commit-id-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>revision</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>com.googlecode.maven-download-plugin</groupId>
|
||||
<artifactId>download-maven-plugin</artifactId>
|
||||
<version>1.3.0</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>download-bitcoind</id>
|
||||
<phase>generate-test-resources</phase>
|
||||
<goals>
|
||||
<goal>wget</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<url>${bitcoind.url}</url>
|
||||
<unpack>true</unpack>
|
||||
<outputDirectory>${project.build.directory}</outputDirectory>
|
||||
<md5>${bitcoind.md5}</md5>
|
||||
<sha1>${bitcoind.sha1}</sha1>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-jar-plugin</artifactId>
|
||||
<configuration>
|
||||
<archive>
|
||||
<manifest>
|
||||
<addClasspath>true</addClasspath>
|
||||
<addDefaultImplementationEntries>true</addDefaultImplementationEntries>
|
||||
</manifest>
|
||||
<manifestEntries>
|
||||
<!-- we hide the git commit in the Specification-Version standard field-->
|
||||
<Specification-Version>${git.commit.id}</Specification-Version>
|
||||
<Url>${project.parent.url}</Url>
|
||||
</manifestEntries>
|
||||
</archive>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<profiles>
|
||||
<profile>
|
||||
<id>default</id>
|
||||
<activation>
|
||||
<activeByDefault>true</activeByDefault>
|
||||
</activation>
|
||||
<properties>
|
||||
<bitcoind.url>https://bitcoin.org/bin/bitcoin-core-0.14.0/bitcoin-0.14.0-x86_64-linux-gnu.tar.gz
|
||||
</bitcoind.url>
|
||||
<bitcoind.md5>c811c157d4d618f7d7f4b9f24834551c</bitcoind.md5>
|
||||
<bitcoind.sha1>3ab7e537bd00bf35e6a78fca108d0d886f8289c1</bitcoind.sha1>
|
||||
</properties>
|
||||
</profile>
|
||||
<profile>
|
||||
<id>Windows</id>
|
||||
<activation>
|
||||
<os>
|
||||
<family>Windows</family>
|
||||
</os>
|
||||
</activation>
|
||||
<properties>
|
||||
<bitcoind.url>https://bitcoin.org/bin/bitcoin-core-0.14.0/bitcoin-0.14.0-win64.zip</bitcoind.url>
|
||||
<bitcoind.md5>e84bc3a81ad3d1776299419eb7a04935</bitcoind.md5>
|
||||
<bitcoind.sha1>d2e64fcabf6f85d56d64a52c76e007b6defc32ef</bitcoind.sha1>
|
||||
</properties>
|
||||
</profile>
|
||||
</profiles>
|
||||
|
||||
<dependencies>
|
||||
<!-- AKKA -->
|
||||
<dependency>
|
||||
<groupId>com.typesafe.akka</groupId>
|
||||
<artifactId>akka-actor_${scala.version.short}</artifactId>
|
||||
<version>${akka.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.typesafe.akka</groupId>
|
||||
<artifactId>akka-slf4j_${scala.version.short}</artifactId>
|
||||
<version>${akka.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.typesafe.akka</groupId>
|
||||
<artifactId>akka-http-core_${scala.version.short}</artifactId>
|
||||
<version>10.0.7</version>
|
||||
</dependency>
|
||||
<!-- JSON -->
|
||||
<dependency>
|
||||
<groupId>org.json4s</groupId>
|
||||
<artifactId>json4s-jackson_${scala.version.short}</artifactId>
|
||||
<version>3.5.2</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>de.heikoseeberger</groupId>
|
||||
<artifactId>akka-http-json4s_${scala.version.short}</artifactId>
|
||||
<version>1.16.1</version>
|
||||
</dependency>
|
||||
<!-- BITCOIN -->
|
||||
<dependency>
|
||||
<groupId>fr.acinq</groupId>
|
||||
<artifactId>bitcoin-lib_${scala.version.short}</artifactId>
|
||||
<version>${bitcoinlib.version}</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>com.google.protobuf</groupId>
|
||||
<artifactId>protobuf-java</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.zeromq</groupId>
|
||||
<artifactId>jeromq</artifactId>
|
||||
<version>0.4.0</version>
|
||||
</dependency>
|
||||
<!-- SERIALIZATION -->
|
||||
<dependency>
|
||||
<groupId>org.scodec</groupId>
|
||||
<artifactId>scodec-core_${scala.version.short}</artifactId>
|
||||
<version>1.10.3</version>
|
||||
</dependency>
|
||||
<!-- LOGGING -->
|
||||
<dependency>
|
||||
<groupId>org.clapper</groupId>
|
||||
<artifactId>grizzled-slf4j_${scala.version.short}</artifactId>
|
||||
<version>1.3.1</version>
|
||||
</dependency>
|
||||
<!-- OTHER -->
|
||||
<dependency>
|
||||
<groupId>org.jgrapht</groupId>
|
||||
<artifactId>jgrapht-core</artifactId>
|
||||
<version>1.0.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jgrapht</groupId>
|
||||
<artifactId>jgrapht-ext</artifactId>
|
||||
<version>1.0.1</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.tinyjee.jgraphx</groupId>
|
||||
<artifactId>jgraphx</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<!-- This is to get rid of '[WARNING] warning: Class javax.annotation.Nonnull not found - continuing with a stub.' compile errors -->
|
||||
<groupId>com.google.code.findbugs</groupId>
|
||||
<artifactId>jsr305</artifactId>
|
||||
<version>3.0.2</version>
|
||||
</dependency>
|
||||
<!-- TESTS -->
|
||||
<dependency>
|
||||
<groupId>com.typesafe.akka</groupId>
|
||||
<artifactId>akka-testkit_${scala.version.short}</artifactId>
|
||||
<version>${akka.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
<version>18.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ch.qos.logback</groupId>
|
||||
<artifactId>logback-classic</artifactId>
|
||||
<version>1.2.3</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
73
eclair-core/src/main/resources/reference.conf
Normal file
73
eclair-core/src/main/resources/reference.conf
Normal file
@ -0,0 +1,73 @@
|
||||
eclair {
|
||||
server {
|
||||
public-ip = "127.0.0.1"
|
||||
binding-ip = "0.0.0.0"
|
||||
port = 9735
|
||||
}
|
||||
api {
|
||||
binding-ip = "127.0.0.1"
|
||||
port = 8080
|
||||
}
|
||||
bitcoind {
|
||||
host = "localhost"
|
||||
rpcport = 18332
|
||||
rpcuser = "foo"
|
||||
rpcpassword = "bar"
|
||||
zmq = "tcp://127.0.0.1:29000"
|
||||
}
|
||||
|
||||
node-alias = "eclair"
|
||||
node-color = "49daaa"
|
||||
global-features = ""
|
||||
local-features = "03" // channels_public and initial_routing_sync
|
||||
|
||||
dust-limit-satoshis = 542
|
||||
default-feerate-perkw = 10000 # corresponds to bitcoind's default value of feerate-perkB=20000 for a standard commit tx
|
||||
|
||||
max-htlc-value-in-flight-msat = 100000000000 // 1 BTC ~= unlimited
|
||||
htlc-minimum-msat = 1000000
|
||||
max-accepted-htlcs = 30
|
||||
|
||||
reserve-to-funding-ratio = 0.01 // recommended by BOLT #2
|
||||
max-reserve-to-funding-ratio = 0.05 // channel reserve can't be more than 5% of the funding amount (recommended: 1%)
|
||||
|
||||
delay-blocks = 144
|
||||
mindepth-blocks = 2
|
||||
expiry-delta-blocks = 144
|
||||
|
||||
fee-base-msat = 546000
|
||||
fee-proportional-millionth = 10
|
||||
|
||||
// maximum local vs remote feerate mismatch; 1.0 means 100%
|
||||
// actual check is abs((local feerate - remote fee rate) / (local fee rate + remote fee rate)/2) > fee rate mismatch
|
||||
max-feerate-mismatch = 1.5
|
||||
|
||||
// funder will send an UpdateFee message if the difference between current commitment fee and actual current network fee is greater
|
||||
// than this ratio.
|
||||
update-fee_min-diff-ratio = 0.1
|
||||
|
||||
router-broadcast-interval = 10 seconds // this should be 60 seconds on mainnet
|
||||
router-validate-interval = 2 seconds // this should be high enough to have a decent level of parallelism
|
||||
|
||||
ping-interval = 30 seconds
|
||||
auto-reconnect = true
|
||||
|
||||
payment-handler = "local"
|
||||
}
|
||||
akka {
|
||||
loggers = ["akka.event.slf4j.Slf4jLogger"]
|
||||
loglevel = "DEBUG"
|
||||
|
||||
actor {
|
||||
debug {
|
||||
# enable DEBUG logging of all LoggingFSMs for events, transitions and timers
|
||||
fsm = on
|
||||
}
|
||||
}
|
||||
|
||||
http {
|
||||
host-connection-pool {
|
||||
max-open-requests = 64
|
||||
}
|
||||
}
|
||||
}
|
@ -55,7 +55,7 @@ object NodeParams {
|
||||
* Order of precedence for the configuration parameters:
|
||||
* 1) Java environment variables (-D...)
|
||||
* 2) Configuration file eclair.conf
|
||||
* 3) default values in application.conf
|
||||
* 3) default values in reference.conf
|
||||
*/
|
||||
def loadConfiguration(datadir: File) =
|
||||
ConfigFactory.parseProperties(System.getProperties)
|
139
eclair-core/src/main/scala/fr/acinq/eclair/Setup.scala
Normal file
139
eclair-core/src/main/scala/fr/acinq/eclair/Setup.scala
Normal file
@ -0,0 +1,139 @@
|
||||
package fr.acinq.eclair
|
||||
|
||||
import java.io.File
|
||||
import java.net.InetSocketAddress
|
||||
|
||||
import akka.actor.{ActorRef, ActorSystem, Props, SupervisorStrategy}
|
||||
import akka.http.scaladsl.Http
|
||||
import akka.stream.ActorMaterializer
|
||||
import akka.util.Timeout
|
||||
import fr.acinq.bitcoin.{Base58Check, OP_CHECKSIG, OP_DUP, OP_EQUALVERIFY, OP_HASH160, OP_PUSHDATA, Script}
|
||||
import fr.acinq.eclair.api.Service
|
||||
import fr.acinq.eclair.blockchain.rpc.BitcoinJsonRPCClient
|
||||
import fr.acinq.eclair.blockchain.zmq.ZMQActor
|
||||
import fr.acinq.eclair.blockchain.{ExtendedBitcoinClient, PeerWatcher}
|
||||
import fr.acinq.eclair.channel.Register
|
||||
import fr.acinq.eclair.io.{Server, Switchboard}
|
||||
import fr.acinq.eclair.payment._
|
||||
import fr.acinq.eclair.router._
|
||||
import fr.acinq.eclair.wire.{ChannelAnnouncement, ChannelUpdate, NodeAnnouncement}
|
||||
import grizzled.slf4j.Logging
|
||||
import org.json4s.JsonAST.JString
|
||||
|
||||
import scala.compat.Platform
|
||||
import scala.concurrent.duration._
|
||||
import scala.concurrent.{Await, ExecutionContext, Promise}
|
||||
import scala.util.Try
|
||||
|
||||
/**
|
||||
* Created by PM on 25/01/2016.
|
||||
*/
|
||||
class Setup(datadir: String, actorSystemName: String = "default") extends Logging {
|
||||
|
||||
logger.info(s"hello!")
|
||||
logger.info(s"version=${getClass.getPackage.getImplementationVersion} commit=${getClass.getPackage.getSpecificationVersion}")
|
||||
val config = NodeParams.loadConfiguration(new File(datadir))
|
||||
|
||||
logger.info(s"initializing secure random generator")
|
||||
// this will force the secure random instance to initialize itself right now, making sure it doesn't hang later (see comment in package.scala)
|
||||
secureRandom.nextInt()
|
||||
|
||||
implicit lazy val system = ActorSystem(actorSystemName)
|
||||
implicit val materializer = ActorMaterializer()
|
||||
implicit val timeout = Timeout(30 seconds)
|
||||
|
||||
val bitcoinClient = new ExtendedBitcoinClient(new BitcoinJsonRPCClient(
|
||||
user = config.getString("bitcoind.rpcuser"),
|
||||
password = config.getString("bitcoind.rpcpassword"),
|
||||
host = config.getString("bitcoind.host"),
|
||||
port = config.getInt("bitcoind.rpcport")))
|
||||
|
||||
implicit val formats = org.json4s.DefaultFormats
|
||||
implicit val ec = ExecutionContext.Implicits.global
|
||||
|
||||
val future = for {
|
||||
json <- bitcoinClient.client.invoke("getblockchaininfo")
|
||||
chain = (json \ "chain").extract[String]
|
||||
blockCount = (json \ "blocks").extract[Long]
|
||||
progress = (json \ "verificationprogress").extract[Double]
|
||||
chainHash <- bitcoinClient.client.invoke("getblockhash", 0).map(_.extract[String])
|
||||
} yield (chain, blockCount, progress, chainHash)
|
||||
val (chain, blockCount, progress, chainHash) = Try(Await.result(future, 10 seconds)).recover { case _ => throw BitcoinRPCConnectionException }.get
|
||||
logger.info(s"using chain=$chain chainHash=$chainHash")
|
||||
chain match {
|
||||
case "test" | "regtest" => ()
|
||||
case _ => throw new RuntimeException("only regtest and testnet are supported for now")
|
||||
}
|
||||
val nodeParams = NodeParams.makeNodeParams(new File(datadir), config, chainHash)
|
||||
logger.info(s"nodeid=${nodeParams.privateKey.publicKey.toBin} alias=${nodeParams.alias}")
|
||||
assert(progress > 0.99, "bitcoind should be synchronized")
|
||||
|
||||
Globals.blockCount.set(blockCount)
|
||||
val defaultFeeratePerKw = config.getLong("default-feerate-perkw")
|
||||
val feeratePerKw = if (chain == "regtest") defaultFeeratePerKw else {
|
||||
val feeratePerKB = Await.result(bitcoinClient.estimateSmartFee(nodeParams.smartfeeNBlocks), 10 seconds)
|
||||
if (feeratePerKB < 0) defaultFeeratePerKw else feerateKB2Kw(feeratePerKB)
|
||||
}
|
||||
|
||||
logger.info(s"initial feeratePerKw=$feeratePerKw")
|
||||
Globals.feeratePerKw.set(feeratePerKw)
|
||||
val bitcoinVersion = Await.result(bitcoinClient.client.invoke("getinfo").map(json => (json \ "version").extract[String]), 10 seconds)
|
||||
// we use it as final payment address, so that funds are moved to the bitcoind wallet upon channel termination
|
||||
val JString(finalAddress) = Await.result(bitcoinClient.client.invoke("getnewaddress"), 10 seconds)
|
||||
logger.info(s"finaladdress=$finalAddress")
|
||||
// TODO: we should use p2wpkh instead of p2pkh as soon as bitcoind supports it
|
||||
//val finalScriptPubKey = OP_0 :: OP_PUSHDATA(Base58Check.decode(finalAddress)._2) :: Nil
|
||||
val finalScriptPubKey = Script.write(OP_DUP :: OP_HASH160 :: OP_PUSHDATA(Base58Check.decode(finalAddress)._2) :: OP_EQUALVERIFY :: OP_CHECKSIG :: Nil)
|
||||
|
||||
val zmqConnected = Promise[Boolean]()
|
||||
val zmq = system.actorOf(SimpleSupervisor.props(Props(new ZMQActor(config.getString("bitcoind.zmq"), Some(zmqConnected))), "zmq", SupervisorStrategy.Restart))
|
||||
val watcher = system.actorOf(SimpleSupervisor.props(PeerWatcher.props(nodeParams, bitcoinClient), "watcher", SupervisorStrategy.Resume))
|
||||
val paymentHandler = system.actorOf(SimpleSupervisor.props(config.getString("payment-handler") match {
|
||||
case "local" => LocalPaymentHandler.props(nodeParams)
|
||||
case "noop" => Props[NoopPaymentHandler]
|
||||
}, "payment-handler", SupervisorStrategy.Resume))
|
||||
val register = system.actorOf(SimpleSupervisor.props(Props(new Register), "register", SupervisorStrategy.Resume))
|
||||
val relayer = system.actorOf(SimpleSupervisor.props(Relayer.props(nodeParams.privateKey, paymentHandler), "relayer", SupervisorStrategy.Resume))
|
||||
val router = system.actorOf(SimpleSupervisor.props(Router.props(nodeParams, watcher), "router", SupervisorStrategy.Resume))
|
||||
val switchboard = system.actorOf(SimpleSupervisor.props(Switchboard.props(nodeParams, watcher, router, relayer, finalScriptPubKey), "switchboard", SupervisorStrategy.Resume))
|
||||
val paymentInitiator = system.actorOf(SimpleSupervisor.props(PaymentInitiator.props(nodeParams.privateKey.publicKey, router, register), "payment-initiator", SupervisorStrategy.Restart))
|
||||
val tcpBound = Promise[Unit]()
|
||||
val server = system.actorOf(SimpleSupervisor.props(Server.props(nodeParams, switchboard, new InetSocketAddress(config.getString("server.binding-ip"), config.getInt("server.port")), Some(tcpBound)), "server", SupervisorStrategy.Restart))
|
||||
|
||||
val _setup = this
|
||||
val api = new Service {
|
||||
override val switchboard: ActorRef = _setup.switchboard
|
||||
override val router: ActorRef = _setup.router
|
||||
override val register: ActorRef = _setup.register
|
||||
override val paymentHandler: ActorRef = _setup.paymentHandler
|
||||
override val paymentInitiator: ActorRef = _setup.paymentInitiator
|
||||
override val system: ActorSystem = _setup.system
|
||||
}
|
||||
val httpBound = Http().bindAndHandle(api.route, config.getString("api.binding-ip"), config.getInt("api.port"))
|
||||
|
||||
Try(Await.result(zmqConnected.future, 5 seconds)).recover { case _ => throw BitcoinZMQConnectionTimeoutException }.get
|
||||
Try(Await.result(tcpBound.future, 5 seconds)).recover { case _ => throw new TCPBindException(config.getInt("server.port")) }.get
|
||||
Try(Await.result(httpBound, 5 seconds)).recover { case _ => throw new TCPBindException(config.getInt("api.port")) }.get
|
||||
|
||||
val tasks = new Thread(new Runnable() {
|
||||
override def run(): Unit = {
|
||||
nodeParams.peersDb.values.foreach(rec => switchboard ! rec)
|
||||
nodeParams.channelsDb.values.foreach(rec => switchboard ! rec)
|
||||
nodeParams.announcementsDb.values.collect { case ann: ChannelAnnouncement => router ! ann }
|
||||
nodeParams.announcementsDb.values.collect { case ann: NodeAnnouncement => router ! ann }
|
||||
nodeParams.announcementsDb.values.collect { case ann: ChannelUpdate => router ! ann }
|
||||
if (nodeParams.channelsDb.values.size > 0) {
|
||||
val nodeAnn = Announcements.makeNodeAnnouncement(nodeParams.privateKey, nodeParams.alias, nodeParams.color, nodeParams.address :: Nil, Platform.currentTime / 1000)
|
||||
router ! nodeAnn
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
def boostrap: Unit = tasks.start()
|
||||
}
|
||||
|
||||
case class TCPBindException(port: Int) extends RuntimeException
|
||||
|
||||
case object BitcoinZMQConnectionTimeoutException extends RuntimeException("could not connect to bitcoind using zeromq")
|
||||
|
||||
case object BitcoinRPCConnectionException extends RuntimeException("could not connect to bitcoind using json-rpc")
|
@ -47,7 +47,7 @@ trait Service extends Logging {
|
||||
implicit val timeout = Timeout(30 seconds)
|
||||
implicit val shouldWritePretty: ShouldWritePretty = ShouldWritePretty.True
|
||||
|
||||
import Json4sSupport.{json4sMarshaller, json4sUnmarshaller}
|
||||
import Json4sSupport.{marshaller, unmarshaller}
|
||||
|
||||
def switchboard: ActorRef
|
||||
|
@ -186,7 +186,7 @@ class PeerWatcher(nodeParams: NodeParams, client: ExtendedBitcoinClient)(implici
|
||||
import akka.pattern.after
|
||||
|
||||
import scala.concurrent.duration._
|
||||
after(3 seconds, context.system.scheduler)(Future.successful()).map(x => publish(tx, isRetry = true))
|
||||
after(3 seconds, context.system.scheduler)(Future.successful(Unit)).map(x => publish(tx, isRetry = true))
|
||||
case t: Throwable => log.error(s"cannot publish tx: reason=${t.getMessage} txid=${tx.txid} tx=${BinaryData(Transaction.write(tx))}")
|
||||
}
|
||||
}
|
@ -25,7 +25,7 @@ class Server(nodeParams: NodeParams, switchboard: ActorRef, address: InetSocketA
|
||||
|
||||
def receive() = {
|
||||
case Bound(localAddress) =>
|
||||
bound.map(_.success())
|
||||
bound.map(_.success(Unit))
|
||||
log.info(s"bound on $localAddress")
|
||||
|
||||
case CommandFailed(_: Bind) =>
|
@ -72,7 +72,7 @@ object LightningMessageCodecs {
|
||||
|
||||
def rgb: Codec[(Byte, Byte, Byte)] = bytes(3).xmap(buf => (buf(0), buf(1), buf(2)), t => ByteVector(t._1, t._2, t._3))
|
||||
|
||||
def zeropaddedstring(size: Int): Codec[String] = fixedSizeBytes(32, utf8).xmap(s => s.takeWhile(_ != '\0'), s => s)
|
||||
def zeropaddedstring(size: Int): Codec[String] = fixedSizeBytes(32, utf8).xmap(s => s.takeWhile(_ != '\u0000'), s => s)
|
||||
|
||||
def der2wire(signature: BinaryData): BinaryData = {
|
||||
require(Crypto.isDERSignature(signature), s"invalid DER signature $signature")
|
38
eclair-core/src/test/resources/logback-test.xml
Normal file
38
eclair-core/src/test/resources/logback-test.xml
Normal file
@ -0,0 +1,38 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<configuration scan="true" debug="false">
|
||||
|
||||
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<target>System.out</target>
|
||||
<encoder>
|
||||
<pattern>%date{HH:mm:ss.SSS} %highlight(%-5level) %X{akkaSource} - %msg%ex{12}%n</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<!--appender name="CONSOLEWARN" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<target>System.out</target>
|
||||
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
|
||||
<level>WARN</level>
|
||||
</filter>
|
||||
<encoder>
|
||||
<pattern>%-5level %X{akkaSource} - %msg%ex{12}%n</pattern>
|
||||
</encoder>
|
||||
</appender-->
|
||||
|
||||
<!--appender name="FILE" class="ch.qos.logback.core.FileAppender">
|
||||
<file>eclair.log</file>
|
||||
<append>false</append>
|
||||
<encoder>
|
||||
<pattern>%-5level %X{akkaSource} - %msg%ex{12}%n</pattern>
|
||||
</encoder>
|
||||
</appender-->
|
||||
|
||||
<logger name="fr.acinq.eclair.Pipe" level="DEBUG" />
|
||||
<logger name="fr.acinq.eclair.crypto.TransportHandler" level="DEBUG" />
|
||||
|
||||
<root level="INFO">
|
||||
<!--appender-ref ref="FILE"/>
|
||||
<appender-ref ref="CONSOLEWARN"/-->
|
||||
<appender-ref ref="CONSOLE"/>
|
||||
</root>
|
||||
|
||||
</configuration>
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user