1
0
mirror of https://github.com/ACINQ/eclair.git synced 2024-11-19 09:54:02 +01:00
This commit is contained in:
pm47 2016-05-25 16:29:54 +02:00
parent b886388b88
commit d2d1514284
13 changed files with 118 additions and 13 deletions

View File

@ -5,7 +5,7 @@
<parent>
<groupId>fr.acinq.eclair</groupId>
<artifactId>eclair_2.11</artifactId>
<version>0.1-rfc2a-SNAPSHOT</version>
<version>0.1-gossip-SNAPSHOT</version>
</parent>
<artifactId>eclair-demo_2.11</artifactId>

View File

@ -10,9 +10,10 @@ import akka.stream.ActorMaterializer
import com.typesafe.config.ConfigFactory
import fr.acinq.eclair.api.Service
import fr.acinq.eclair.blockchain.{ExtendedBitcoinClient, PollingWatcher}
import fr.acinq.eclair.channel.Register
import fr.acinq.eclair.channel.{Register, Router}
import fr.acinq.eclair.io.{Client, Server}
import grizzled.slf4j.Logging
import scala.concurrent.{Await, ExecutionContext}
import scala.concurrent.duration._
import Globals._
@ -37,10 +38,12 @@ object Boot extends App with Logging {
val blockchain = system.actorOf(Props(new PollingWatcher(new ExtendedBitcoinClient(bitcoin_client))), name = "blockchain")
val register = system.actorOf(Props[Register], name = "register")
val router = system.actorOf(Props[Router], name = "router")
val server = system.actorOf(Server.props(config.getString("eclair.server.address"), config.getInt("eclair.server.port")), "server")
val api = new Service {
override val register: ActorRef = Boot.register
override val router: ActorRef = Boot.router
override def connect(addr: InetSocketAddress, amount: Long): Unit = system.actorOf(Props(classOf[Client], addr, amount))
}

View File

@ -3,9 +3,9 @@ package fr.acinq.eclair.api
import fr.acinq.eclair._
import fr.acinq.bitcoin.BinaryData
import fr.acinq.eclair.channel.State
import lightning.sha256_hash
import lightning.{channel_desc, sha256_hash}
import org.json4s.CustomSerializer
import org.json4s.JsonAST.JString
import org.json4s.JsonAST.{JObject, JString}
/**
* Created by PM on 28/01/2016.
@ -38,4 +38,14 @@ class Sha256Serializer extends CustomSerializer[sha256_hash](format => (
{
case x: sha256_hash => JString(sha2562bin(x).toString())
}
))
class ChannelDescSerializer extends CustomSerializer[channel_desc](format => (
{
case JString(x) if (false) => // NOT IMPLEMENTED
???
},
{
case x: channel_desc => JObject(("channelId", JString(BinaryData(x.id.toByteArray).toString())), ("A", JString(BinaryData(x.nodeIdA.toByteArray).toString)), ("B", JString(BinaryData(x.nodeIdB.toByteArray).toString())))
}
))

View File

@ -2,9 +2,8 @@ package fr.acinq.eclair.api
import java.net.InetSocketAddress
import akka.actor.ActorRef
import akka.http.scaladsl.model.{HttpEntity, StatusCodes, ContentTypes, HttpResponse}
import akka.http.scaladsl.model.{ContentTypes, HttpEntity, HttpResponse, StatusCodes}
import akka.util.Timeout
import akka.http.scaladsl.server.Directives._
import fr.acinq.bitcoin.BinaryData
@ -12,7 +11,7 @@ import fr.acinq.eclair._
import fr.acinq.eclair.channel._
import fr.acinq.eclair.Boot
import grizzled.slf4j.Logging
import lightning.locktime
import lightning.{channel_desc, locktime}
import lightning.locktime.Locktime.Seconds
import org.json4s.JsonAST.JString
import org.json4s._
@ -38,11 +37,12 @@ trait Service extends Logging {
implicit def ec: ExecutionContext = ExecutionContext.Implicits.global
implicit val formats = org.json4s.DefaultFormats + new BinaryDataSerializer + new StateSerializer + new Sha256Serializer
implicit val formats = org.json4s.DefaultFormats + new BinaryDataSerializer + new StateSerializer + new Sha256Serializer + new ChannelDescSerializer
implicit val timeout = Timeout(30 seconds)
def connect(addr: InetSocketAddress, amount: Long): Unit // amount in satoshis
def register: ActorRef
def router: ActorRef
def sendCommand(channel_id: String, cmd: Command): Future[String] = {
Boot.system.actorSelection(Register.actorPathToChannelId(channel_id)).resolveOne().map(actor => {
@ -64,6 +64,8 @@ trait Service extends Logging {
case JsonRPCBody(_, _, "list", _) =>
(register ? ListChannels).mapTo[Iterable[ActorRef]]
.flatMap(l => Future.sequence(l.map(c => c ? CMD_GETINFO)))
case JsonRPCBody(_, _, "network", _) =>
(router ? 'network).mapTo[Iterable[channel_desc]]
case JsonRPCBody(_, _, "addhtlc", JInt(amount) :: JString(rhash) :: JInt(expiry) :: tail) =>
val nodeIds = tail.map {
case JString(nodeId) => nodeId

View File

@ -213,6 +213,7 @@ class Channel(val them: ActorRef, val blockchain: ActorRef, val params: OurChann
when(OPEN_WAIT_FOR_COMPLETE_THEIRANCHOR) {
case Event(open_complete(blockid_opt), d: CurrentCommitment) =>
Register.create_alias(theirNodeId, d.anchorId)
them ! register_channel(channel_desc(d.anchorId, BinaryData(Globals.Node.id), BinaryData(theirNodeId)))
goto(NORMAL)
/*case Event(pkt: close_channel, d: CurrentCommitment) =>
@ -241,6 +242,7 @@ class Channel(val them: ActorRef, val blockchain: ActorRef, val params: OurChann
case Event(open_complete(blockid_opt), d: CurrentCommitment) =>
Register.create_alias(theirNodeId, d.anchorId)
them ! register_channel(channel_desc(d.anchorId, BinaryData(Globals.Node.id), BinaryData(theirNodeId)))
goto(NORMAL)
/*case Event(pkt: close_channel, d: CurrentCommitment) =>

View File

@ -58,7 +58,8 @@ object Helpers {
}
def checksig(ourParams: OurChannelParams, theirParams: TheirChannelParams, anchorOutput: TxOut, tx: Transaction): Boolean =
Try(Transaction.correctlySpends(tx, Map(tx.txIn(0).outPoint -> anchorOutput), ScriptFlags.STANDARD_SCRIPT_VERIFY_FLAGS)).isSuccess
true
// TODO : Try(Transaction.correctlySpends(tx, Map(tx.txIn(0).outPoint -> anchorOutput), ScriptFlags.STANDARD_SCRIPT_VERIFY_FLAGS)).isSuccess
def isMutualClose(tx: Transaction, ourParams: OurChannelParams, theirParams: TheirChannelParams, commitment: OurCommit): Boolean = {
// we rebuild the closing tx as seen by both parties

View File

@ -64,4 +64,7 @@ object Register {
def actorPathToChannels(): ActorPath =
Boot.system / "register" / "handler-*" / "channel"
def actorPathToHandlers(): ActorPath =
Boot.system / "register" / "handler-*"
}

View File

@ -0,0 +1,34 @@
package fr.acinq.eclair.channel
import akka.actor.{Actor, ActorLogging}
import fr.acinq.bitcoin.BinaryData
import lightning._
import scala.concurrent.ExecutionContext
import scala.concurrent.duration._
/**
* Created by PM on 24/05/2016.
*/
class Router extends Actor with ActorLogging {
import ExecutionContext.Implicits.global
context.system.scheduler.schedule(5 seconds, 10 seconds, self, 'tick)
def receive: Receive = main(Map())
def main(channels: Map[BinaryData, channel_desc]): Receive = {
case r@register_channel(c) =>
log.debug(s"received $r")
context become main(channels + (BinaryData(c.id.toByteArray) -> c))
case u@unregister_channel(c) =>
log.debug(s"received $u")
context become main(channels - BinaryData(c.id.toByteArray))
case 'tick =>
val sel = context.actorSelection(Register.actorPathToHandlers())
channels.values.foreach(sel ! register_channel(_))
case 'network =>
sender ! channels.values
}
}

View File

@ -155,7 +155,7 @@ class AuthHandler(them: ActorRef, blockchain: ActorRef, our_params: OurChannelPa
log.error(s"cannot verify peer signature $their_sig for public key $their_nodeid")
context.stop(self)
}
val channel = context.actorOf(Channel.props(self, blockchain, our_params), name = "channel")
val channel = context.actorOf(Channel.props(self, blockchain, our_params, their_nodeid.toString()), name = "channel")
goto(IO_NORMAL) using Normal(channel, s.copy(decryptor = decryptor1.copy(header = None, body = None)))
}
}
@ -175,6 +175,8 @@ class AuthHandler(them: ActorRef, blockchain: ActorRef, our_params: OurChannelPa
case Event(packet: pkt, n@Normal(channel, s@SessionData(theirpub, decryptor, encryptor))) =>
log.debug(s"receiving $packet")
packet.pkt match {
case RegisterChannel(o) => Boot.router ! o
case UnregisterChannel(o) => Boot.router ! o
case Open(o) => channel ! o
case OpenAnchor(o) => channel ! o
case OpenCommitSig(o) => channel ! o
@ -193,6 +195,8 @@ class AuthHandler(them: ActorRef, blockchain: ActorRef, our_params: OurChannelPa
case Event(msg: GeneratedMessage, n@Normal(channel, s@SessionData(theirpub, decryptor, encryptor))) =>
val packet = msg match {
case o: open_channel => pkt(Open(o))
case o: register_channel => pkt(RegisterChannel(o))
case o: unregister_channel => pkt(UnregisterChannel(o))
case o: open_anchor => pkt(OpenAnchor(o))
case o: open_commit_sig => pkt(OpenCommitSig(o))
case o: open_complete => pkt(OpenComplete(o))

View File

@ -5,7 +5,7 @@
<parent>
<groupId>fr.acinq.eclair</groupId>
<artifactId>eclair_2.11</artifactId>
<version>0.1-rfc2a-SNAPSHOT</version>
<version>0.1-gossip-SNAPSHOT</version>
</parent>
<artifactId>lightning-types_2.11</artifactId>

View File

@ -7,8 +7,11 @@ syntax = "proto2";
// Helper Types
//
import "scalapb/scalapb.proto";
// Protobufs don't have fixed-length fields, so these are a hack.
message sha256_hash {
option (scalapb.message).extends = "lightning.Sha256ToString";
required fixed64 a = 1;
required fixed64 b = 2;
required fixed64 c = 3;
@ -16,6 +19,7 @@ message sha256_hash {
}
message signature {
option (scalapb.message).extends = "lightning.SignatureToString";
required fixed64 r1 = 1;
required fixed64 r2 = 2;
required fixed64 r3 = 3;
@ -33,8 +37,11 @@ message locktime {
}
}
// Pubkey for commitment transaction input.
message bitcoin_pubkey {
option (scalapb.message).extends = "lightning.PubkeyToString";
// Must be 33 bytes.
required bytes key = 1;
}
@ -61,6 +68,22 @@ message authenticate {
optional uint64 ack = 3 [ default = 0 ];
};
// Description of a channel
message channel_desc {
option (scalapb.message).extends = "lightning.ChannelDescToString";
required bytes id = 1;
required bytes node_id_a = 2;
required bytes node_id_b = 3;
}
message register_channel {
required channel_desc channel = 1;
}
message unregister_channel {
required channel_desc channel = 1;
}
// Set channel params.
message open_channel {
// Relative locktime for outputs going to us.
@ -190,6 +213,11 @@ message pkt {
oneof pkt {
// Start of connection
authenticate auth = 50;
// Gossip
register_channel register_channel = 10;
unregister_channel unregister_channel = 11;
// Opening
open_channel open = 20;
open_anchor open_anchor = 21;

View File

@ -4,10 +4,12 @@
package lightning
import java.io.{OutputStream, ByteArrayOutputStream}
import java.io.{ByteArrayOutputStream, OutputStream}
import java.math.BigInteger
import javax.xml.bind.DatatypeConverter
import com.google.protobuf.ByteString
object ToStrings {
def writeUInt8(input: Long, out: OutputStream): Unit = out.write((input & 0xff).asInstanceOf[Int])
@ -75,3 +77,19 @@ trait SignatureToString {
s"signature(r=${DatatypeConverter.printHexBinary(r.toByteArray)},s=${DatatypeConverter.printHexBinary(s.toByteArray)})"
}
}
trait PubkeyToString {
def key: ByteString
override def toString = s"bitcoin_pubkey(${DatatypeConverter.printHexBinary(key.toByteArray)})"
}
trait ChannelDescToString {
def id: ByteString
def nodeIdA: ByteString
def nodeIdB: ByteString
override def toString = s"channel_desc(id=${DatatypeConverter.printHexBinary(id.toByteArray)},a=${DatatypeConverter.printHexBinary(nodeIdA.toByteArray)},b=${DatatypeConverter.printHexBinary(nodeIdB.toByteArray)})"
}

View File

@ -4,7 +4,7 @@
<groupId>fr.acinq.eclair</groupId>
<artifactId>eclair_2.11</artifactId>
<version>0.1-rfc2a-SNAPSHOT</version>
<version>0.1-gossip-SNAPSHOT</version>
<packaging>pom</packaging>
<modules>