mirror of
https://github.com/ACINQ/eclair.git
synced 2024-11-19 18:10:42 +01:00
anchor is now created, funded and pushed through bitcoind
This commit is contained in:
parent
07053b7d22
commit
bdbd733e16
@ -35,7 +35,7 @@ object Boot extends App with Logging {
|
|||||||
val api = system.actorOf(Props(new ServiceActor {
|
val api = system.actorOf(Props(new ServiceActor {
|
||||||
override val register: ActorRef = Boot.register
|
override val register: ActorRef = Boot.register
|
||||||
|
|
||||||
override def connect(addr: InetSocketAddress): Unit = system.actorOf(Props(classOf[Client], addr))
|
override def connect(addr: InetSocketAddress, amount: Long): Unit = system.actorOf(Props(classOf[Client], addr, amount))
|
||||||
}), "api")
|
}), "api")
|
||||||
|
|
||||||
// start a new HTTP server on port 8080 with our service actor as the handler
|
// start a new HTTP server on port 8080 with our service actor as the handler
|
||||||
|
@ -22,7 +22,7 @@ object Demo extends App {
|
|||||||
val system = ActorSystem()
|
val system = ActorSystem()
|
||||||
implicit val timeout = Timeout(30 seconds)
|
implicit val timeout = Timeout(30 seconds)
|
||||||
|
|
||||||
val anchorInput = AnchorInput(100100000L, OutPoint(Hex.decode("7727730d21428276a4d6b0e16f3a3e6f3a07a07dc67151e6a88d4a8c3e8edb24").reverse, 1), SignData("76a914e093fbc19866b98e0fbc25d79d0ad0f0375170af88ac", Base58Check.decode("cU1YgK56oUKAtV6XXHZeJQjEx1KGXkZS1pGiKpyW4mUyKYFJwWFg")._2))
|
val anchorInput = AnchorInput(100100000L) //, OutPoint(Hex.decode("7727730d21428276a4d6b0e16f3a3e6f3a07a07dc67151e6a88d4a8c3e8edb24").reverse, 1), SignData("76a914e093fbc19866b98e0fbc25d79d0ad0f0375170af88ac", Base58Check.decode("cU1YgK56oUKAtV6XXHZeJQjEx1KGXkZS1pGiKpyW4mUyKYFJwWFg")._2))
|
||||||
|
|
||||||
val alice_commit_priv = Base58Check.decode("cQPmcNr6pwBQPyGfab3SksE9nTCtx9ism9T4dkS9dETNU2KKtJHk")._2
|
val alice_commit_priv = Base58Check.decode("cQPmcNr6pwBQPyGfab3SksE9nTCtx9ism9T4dkS9dETNU2KKtJHk")._2
|
||||||
val alice_final_priv = Base58Check.decode("cUrAtLtV7GGddqdkhUxnbZVDWGJBTducpPoon3eKp9Vnr1zxs6BG")._2
|
val alice_final_priv = Base58Check.decode("cUrAtLtV7GGddqdkhUxnbZVDWGJBTducpPoon3eKp9Vnr1zxs6BG")._2
|
||||||
|
@ -10,7 +10,7 @@ import scala.concurrent.{ExecutionContext, Future}
|
|||||||
import scala.concurrent.duration._
|
import scala.concurrent.duration._
|
||||||
|
|
||||||
// @formatter:off
|
// @formatter:off
|
||||||
case class CreateChannel(connection: ActorRef, our_anchor: Boolean)
|
case class CreateChannel(connection: ActorRef, our_anchor: Boolean, amount: Long = 0)
|
||||||
case class GetChannels()
|
case class GetChannels()
|
||||||
case class RegisterChannel(nodeId: String, state: ChannelState)
|
case class RegisterChannel(nodeId: String, state: ChannelState)
|
||||||
// @formatter:on
|
// @formatter:on
|
||||||
@ -30,7 +30,7 @@ class RegisterActor extends Actor with ActorLogging {
|
|||||||
override def receive: Receive = ???
|
override def receive: Receive = ???
|
||||||
|
|
||||||
def main(channels: Map[String, ChannelState]): Receive = {
|
def main(channels: Map[String, ChannelState]): Receive = {
|
||||||
case CreateChannel(connection, our_anchor) => context.actorOf(Props(classOf[AuthHandler], connection, Boot.blockchain, our_anchor), name = s"handler-${i = i + 1; i}")
|
case CreateChannel(connection, our_anchor, amount) => context.actorOf(Props(classOf[AuthHandler], connection, Boot.blockchain, our_anchor, amount), name = s"handler-${i = i + 1; i}")
|
||||||
case GetChannels =>
|
case GetChannels =>
|
||||||
val s = sender()
|
val s = sender()
|
||||||
Future.sequence(context.children.map(c => c ? CMD_GETINFO)).map(s ! _)
|
Future.sequence(context.children.map(c => c ? CMD_GETINFO)).map(s ! _)
|
||||||
|
@ -53,7 +53,7 @@ trait Service extends HttpService with Logging {
|
|||||||
implicit val formats = org.json4s.DefaultFormats + new BinaryDataSerializer + new StateSerializer + new Sha256Serializer
|
implicit val formats = org.json4s.DefaultFormats + new BinaryDataSerializer + new StateSerializer + new Sha256Serializer
|
||||||
implicit val timeout = Timeout(30 seconds)
|
implicit val timeout = Timeout(30 seconds)
|
||||||
|
|
||||||
def connect(addr: InetSocketAddress): Unit
|
def connect(addr: InetSocketAddress, amount: Long): Unit // amount in satoshis
|
||||||
def register: ActorRef
|
def register: ActorRef
|
||||||
|
|
||||||
def sendCommand(channel: String, cmd: Command): Future[String] = {
|
def sendCommand(channel: String, cmd: Command): Future[String] = {
|
||||||
@ -71,8 +71,7 @@ trait Service extends HttpService with Logging {
|
|||||||
val json = parse(body).extract[JsonRPCBody]
|
val json = parse(body).extract[JsonRPCBody]
|
||||||
val f_res: Future[AnyRef] = json match {
|
val f_res: Future[AnyRef] = json match {
|
||||||
case JsonRPCBody(_, _, "connect", JString(host) :: JInt(port) :: JInt(anchor_amount) :: Nil) =>
|
case JsonRPCBody(_, _, "connect", JString(host) :: JInt(port) :: JInt(anchor_amount) :: Nil) =>
|
||||||
//TODO : anchor_amount not implemented
|
connect(new InetSocketAddress(host, port.toInt), anchor_amount.toLong)
|
||||||
connect(new InetSocketAddress(host, port.toInt))
|
|
||||||
Future.successful("")
|
Future.successful("")
|
||||||
case JsonRPCBody(_, _, "list", _) =>
|
case JsonRPCBody(_, _, "list", _) =>
|
||||||
(register ? GetChannels).mapTo[Iterable[RES_GETINFO]]
|
(register ? GetChannels).mapTo[Iterable[RES_GETINFO]]
|
||||||
|
@ -56,6 +56,9 @@ class PollingWatcher(client: BitcoinJsonRPCClient)(implicit ec: ExecutionContext
|
|||||||
|
|
||||||
case Publish(tx) =>
|
case Publish(tx) =>
|
||||||
log.info(s"publishing tx $tx")
|
log.info(s"publishing tx $tx")
|
||||||
|
PollingWatcher.publishTransaction(client, tx).onFailure {
|
||||||
|
case t: Throwable => log.error(t, s"cannot publish tx ${Hex.toHexString(Transaction.write(tx))}")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -128,6 +131,14 @@ object PollingWatcher {
|
|||||||
|
|
||||||
def signTransaction(client: BitcoinJsonRPCClient, tx: Transaction)(implicit ec: ExecutionContext): Future[SignTransactionResponse] =
|
def signTransaction(client: BitcoinJsonRPCClient, tx: Transaction)(implicit ec: ExecutionContext): Future[SignTransactionResponse] =
|
||||||
signTransaction(client, Hex.toHexString(Transaction.write(tx)))
|
signTransaction(client, Hex.toHexString(Transaction.write(tx)))
|
||||||
|
|
||||||
|
def publishTransaction(client: BitcoinJsonRPCClient, hex: String)(implicit ec: ExecutionContext): Future[String] =
|
||||||
|
client.invoke("sendrawtransaction", hex).map {
|
||||||
|
case JString(txid) => txid
|
||||||
|
}
|
||||||
|
|
||||||
|
def publishTransaction(client: BitcoinJsonRPCClient, tx: Transaction)(implicit ec: ExecutionContext): Future[String] =
|
||||||
|
publishTransaction(client, Hex.toHexString(Transaction.write(tx)))
|
||||||
}
|
}
|
||||||
|
|
||||||
/*object MyTest extends App {
|
/*object MyTest extends App {
|
||||||
|
@ -45,7 +45,7 @@ object Anchor extends App {
|
|||||||
val finalPub = Crypto.publicKeyFromPrivateKey(finalPriv)
|
val finalPub = Crypto.publicKeyFromPrivateKey(finalPriv)
|
||||||
}
|
}
|
||||||
|
|
||||||
val amount = (0.5 * Coin).asInstanceOf[Long]
|
val amount = (0.06 * Coin).asInstanceOf[Long]
|
||||||
|
|
||||||
val config = ConfigFactory.load()
|
val config = ConfigFactory.load()
|
||||||
val bitcoind = new BitcoinJsonRPCClient(
|
val bitcoind = new BitcoinJsonRPCClient(
|
||||||
@ -54,14 +54,14 @@ object Anchor extends App {
|
|||||||
host = config.getString("eclair.bitcoind.address"),
|
host = config.getString("eclair.bitcoind.address"),
|
||||||
port = config.getInt("eclair.bitcoind.port"))
|
port = config.getInt("eclair.bitcoind.port"))
|
||||||
|
|
||||||
val (anchorTx, pos) = Await.result(makeAnchorTx(bitcoind, Alice.commitPub, Bob.commitPub, amount), 10 seconds)
|
val (anchorTx, pos) = (Transaction.read("010000000164345d5e5f6d3f8489740bc4e3f8bf8686b2ac221af48f0a2e88f601496182f1010000006a47304402204db8a977f275e74c92d28b18d82f09b5291111d0435cb3e653268a1d35dbbe02022074ada818ff9ea49ec613132423c42a5eecc223dbaa6ec1719a8de75539f659ca012103b8e06b059d35f1a3447ed834d265cb194f0f67dc50da30d18e569a40af697565feffffff02808d5b000000000017a91408bc5c0400edc31cbca9204fe1b8463b8c912f0187d99f0602000000001976a9148cda43313910281fe08a9d1659249e1f97152f8588ac00000000"), 0) //Await.result(makeAnchorTx(bitcoind, Alice.commitPub, Bob.commitPub, amount), 10 seconds)
|
||||||
println(anchorTx)
|
println(anchorTx)
|
||||||
println(Hex.toHexString(Transaction.write(anchorTx)))
|
println(s"anchor tx: ${Hex.toHexString(Transaction.write(anchorTx))}")
|
||||||
bitcoind.client.close()
|
bitcoind.client.close()
|
||||||
|
|
||||||
val spending = Transaction(version = 1,
|
val spending = Transaction(version = 1,
|
||||||
txIn = TxIn(OutPoint(anchorTx, pos), Array.emptyByteArray, 0xffffffffL) :: Nil,
|
txIn = TxIn(OutPoint(anchorTx, pos), Array.emptyByteArray, 0xffffffffL) :: Nil,
|
||||||
txOut = TxOut(10, OP_DUP :: OP_HASH160 :: OP_PUSHDATA(Crypto.hash160(Alice.commitPub)) :: OP_EQUALVERIFY :: OP_CHECKSIG :: Nil) :: Nil,
|
txOut = TxOut(amount - 10, OP_DUP :: OP_HASH160 :: OP_PUSHDATA(Crypto.hash160(Alice.commitPub)) :: OP_EQUALVERIFY :: OP_CHECKSIG :: Nil) :: Nil,
|
||||||
lockTime = 0)
|
lockTime = 0)
|
||||||
|
|
||||||
val redeemScript = Scripts.multiSig2of2(Alice.commitPub, Bob.commitPub)
|
val redeemScript = Scripts.multiSig2of2(Alice.commitPub, Bob.commitPub)
|
||||||
@ -70,4 +70,5 @@ object Anchor extends App {
|
|||||||
val scriptSig = Scripts.sigScript2of2(sig1, sig2, Alice.commitPub, Bob.commitPub)
|
val scriptSig = Scripts.sigScript2of2(sig1, sig2, Alice.commitPub, Bob.commitPub)
|
||||||
val signedTx = spending.updateSigScript(0, scriptSig)
|
val signedTx = spending.updateSigScript(0, scriptSig)
|
||||||
Transaction.correctlySpends(signedTx, Seq(anchorTx), ScriptFlags.STANDARD_SCRIPT_VERIFY_FLAGS)
|
Transaction.correctlySpends(signedTx, Seq(anchorTx), ScriptFlags.STANDARD_SCRIPT_VERIFY_FLAGS)
|
||||||
|
println(s"spending tx: ${Hex.toHexString(Transaction.write(signedTx))}")
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package fr.acinq.eclair.channel
|
package fr.acinq.eclair.channel
|
||||||
|
|
||||||
import akka.actor.{ActorRef, LoggingFSM, Stash}
|
import akka.actor.{ActorRef, LoggingFSM, Stash}
|
||||||
|
import akka.pattern.pipe
|
||||||
import com.google.protobuf.ByteString
|
import com.google.protobuf.ByteString
|
||||||
import fr.acinq.bitcoin._
|
import fr.acinq.bitcoin._
|
||||||
import fr.acinq.eclair._
|
import fr.acinq.eclair._
|
||||||
@ -10,8 +11,9 @@ import Scripts._
|
|||||||
import lightning._
|
import lightning._
|
||||||
import lightning.open_channel.anchor_offer.{WILL_CREATE_ANCHOR, WONT_CREATE_ANCHOR}
|
import lightning.open_channel.anchor_offer.{WILL_CREATE_ANCHOR, WONT_CREATE_ANCHOR}
|
||||||
import lightning.update_decline_htlc.Reason.{CannotRoute, InsufficientFunds}
|
import lightning.update_decline_htlc.Reason.{CannotRoute, InsufficientFunds}
|
||||||
|
import org.bouncycastle.util.encoders.Hex
|
||||||
|
|
||||||
import scala.util.Try
|
import scala.util.{Failure, Success, Try}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by PM on 20/08/2015.
|
* Created by PM on 20/08/2015.
|
||||||
@ -153,7 +155,7 @@ final case class RES_GETINFO(name: String, state: State, data: Data)
|
|||||||
|
|
||||||
sealed trait Data
|
sealed trait Data
|
||||||
case object Nothing extends Data
|
case object Nothing extends Data
|
||||||
final case class AnchorInput(amount: Long, previousTxOutput: OutPoint, signData: SignData) extends Data
|
final case class AnchorInput(amount: Long) extends Data
|
||||||
final case class OurChannelParams(delay: locktime, commitPrivKey: BinaryData, finalPrivKey: BinaryData, minDepth: Int, commitmentFee: Long, shaSeed: BinaryData) {
|
final case class OurChannelParams(delay: locktime, commitPrivKey: BinaryData, finalPrivKey: BinaryData, minDepth: Int, commitmentFee: Long, shaSeed: BinaryData) {
|
||||||
val commitPubKey: BinaryData = Crypto.publicKeyFromPrivateKey(commitPrivKey)
|
val commitPubKey: BinaryData = Crypto.publicKeyFromPrivateKey(commitPrivKey)
|
||||||
val finalPubKey: BinaryData = Crypto.publicKeyFromPrivateKey(finalPrivKey)
|
val finalPubKey: BinaryData = Crypto.publicKeyFromPrivateKey(finalPrivKey)
|
||||||
@ -171,6 +173,7 @@ trait CurrentCommitment {
|
|||||||
|
|
||||||
final case class DATA_OPEN_WAIT_FOR_OPEN_NOANCHOR(ourParams: OurChannelParams) extends Data
|
final case class DATA_OPEN_WAIT_FOR_OPEN_NOANCHOR(ourParams: OurChannelParams) extends Data
|
||||||
final case class DATA_OPEN_WAIT_FOR_OPEN_WITHANCHOR(ourParams: OurChannelParams, anchorInput: AnchorInput) extends Data
|
final case class DATA_OPEN_WAIT_FOR_OPEN_WITHANCHOR(ourParams: OurChannelParams, anchorInput: AnchorInput) extends Data
|
||||||
|
final case class DATA_OPEN_WITH_ANCHOR_WAIT_FOR_ANCHOR(ourParams: OurChannelParams, theirParams: TheirChannelParams, theirRevocationHash: BinaryData) extends Data
|
||||||
final case class DATA_OPEN_WAIT_FOR_ANCHOR(ourParams: OurChannelParams, theirParams: TheirChannelParams, theirRevocationHash: sha256_hash) extends Data
|
final case class DATA_OPEN_WAIT_FOR_ANCHOR(ourParams: OurChannelParams, theirParams: TheirChannelParams, theirRevocationHash: sha256_hash) extends Data
|
||||||
final case class DATA_OPEN_WAIT_FOR_COMMIT_SIG(ourParams: OurChannelParams, theirParams: TheirChannelParams, anchorTx: Transaction, anchorOutputIndex: Int, newCommitmentUnsigned: Commitment) extends Data
|
final case class DATA_OPEN_WAIT_FOR_COMMIT_SIG(ourParams: OurChannelParams, theirParams: TheirChannelParams, anchorTx: Transaction, anchorOutputIndex: Int, newCommitmentUnsigned: Commitment) extends Data
|
||||||
final case class DATA_OPEN_WAITING(ourParams: OurChannelParams, theirParams: TheirChannelParams, shaChain: ShaChain, commitment: Commitment) extends Data with CurrentCommitment
|
final case class DATA_OPEN_WAITING(ourParams: OurChannelParams, theirParams: TheirChannelParams, shaChain: ShaChain, commitment: Commitment) extends Data with CurrentCommitment
|
||||||
@ -188,6 +191,7 @@ final case class DATA_CLOSING(ourParams: OurChannelParams, theirParams: TheirCha
|
|||||||
// @formatter:on
|
// @formatter:on
|
||||||
|
|
||||||
class Channel(val blockchain: ActorRef, val params: OurChannelParams, val anchorDataOpt: Option[AnchorInput]) extends LoggingFSM[State, Data] with Stash {
|
class Channel(val blockchain: ActorRef, val params: OurChannelParams, val anchorDataOpt: Option[AnchorInput]) extends LoggingFSM[State, Data] with Stash {
|
||||||
|
import context.dispatcher
|
||||||
|
|
||||||
val ourCommitPubKey = bitcoin_pubkey(ByteString.copyFrom(params.commitPubKey))
|
val ourCommitPubKey = bitcoin_pubkey(ByteString.copyFrom(params.commitPubKey))
|
||||||
val ourFinalPubKey = bitcoin_pubkey(ByteString.copyFrom(params.finalPubKey))
|
val ourFinalPubKey = bitcoin_pubkey(ByteString.copyFrom(params.finalPubKey))
|
||||||
@ -249,13 +253,17 @@ class Channel(val blockchain: ActorRef, val params: OurChannelParams, val anchor
|
|||||||
when(OPEN_WAIT_FOR_OPEN_WITHANCHOR) {
|
when(OPEN_WAIT_FOR_OPEN_WITHANCHOR) {
|
||||||
case Event(open_channel(delay, theirRevocationHash, commitKey, finalKey, WONT_CREATE_ANCHOR, minDepth, commitmentFee), DATA_OPEN_WAIT_FOR_OPEN_WITHANCHOR(ourParams, anchorInput)) =>
|
case Event(open_channel(delay, theirRevocationHash, commitKey, finalKey, WONT_CREATE_ANCHOR, minDepth, commitmentFee), DATA_OPEN_WAIT_FOR_OPEN_WITHANCHOR(ourParams, anchorInput)) =>
|
||||||
val theirParams = TheirChannelParams(delay, commitKey, finalKey, minDepth, commitmentFee)
|
val theirParams = TheirChannelParams(delay, commitKey, finalKey, minDepth, commitmentFee)
|
||||||
val (anchorTx, anchorOutputIndex) = makeAnchorTx(ourCommitPubKey, theirParams.commitPubKey, anchorInput.amount, anchorInput.previousTxOutput, anchorInput.signData)
|
Anchor.makeAnchorTx(Globals.bitcoin_client, ourCommitPubKey, theirParams.commitPubKey, anchorInput.amount).pipeTo(self)
|
||||||
|
stay using DATA_OPEN_WITH_ANCHOR_WAIT_FOR_ANCHOR(ourParams, theirParams, theirRevocationHash)
|
||||||
|
|
||||||
|
case Event((anchorTx: Transaction, anchorOutputIndex: Int), DATA_OPEN_WITH_ANCHOR_WAIT_FOR_ANCHOR(ourParams, theirParams, theirRevocationHash)) =>
|
||||||
log.info(s"anchor txid=${anchorTx.txid}")
|
log.info(s"anchor txid=${anchorTx.txid}")
|
||||||
// we fund the channel with the anchor tx, so the money is ours
|
val amount = anchorTx.txOut(anchorOutputIndex).amount
|
||||||
val state = ChannelState(them = ChannelOneSide(0, 0, Seq()), us = ChannelOneSide((anchorInput.amount - ourParams.commitmentFee) * 1000, ourParams.commitmentFee * 1000, Seq()))
|
val state = ChannelState(them = ChannelOneSide(0, 0, Seq()), us = ChannelOneSide((amount - ourParams.commitmentFee) * 1000, ourParams.commitmentFee * 1000, Seq()))
|
||||||
val ourRevocationHash = Crypto.sha256(ShaChain.shaChainFromSeed(ourParams.shaSeed, 0))
|
val ourRevocationHash = Crypto.sha256(ShaChain.shaChainFromSeed(ourParams.shaSeed, 0))
|
||||||
val (ourCommitTx, ourSigForThem) = sign_their_commitment_tx(ourParams, theirParams, TxIn(OutPoint(anchorTx.hash, anchorOutputIndex), Array.emptyByteArray, 0xffffffffL) :: Nil, state, ourRevocationHash, theirRevocationHash)
|
val (ourCommitTx, ourSigForThem) = sign_their_commitment_tx(ourParams, theirParams, TxIn(OutPoint(anchorTx.hash, anchorOutputIndex), Array.emptyByteArray, 0xffffffffL) :: Nil, state, ourRevocationHash, theirRevocationHash)
|
||||||
them ! open_anchor(anchorTx.hash, anchorOutputIndex, anchorInput.amount, ourSigForThem)
|
log.info(s"our commit tx: ${Hex.toHexString(Transaction.write(ourCommitTx))}")
|
||||||
|
them ! open_anchor(anchorTx.hash, anchorOutputIndex, amount, ourSigForThem)
|
||||||
goto(OPEN_WAIT_FOR_COMMIT_SIG) using DATA_OPEN_WAIT_FOR_COMMIT_SIG(ourParams, theirParams, anchorTx, anchorOutputIndex, Commitment(0, ourCommitTx, state, theirRevocationHash))
|
goto(OPEN_WAIT_FOR_COMMIT_SIG) using DATA_OPEN_WAIT_FOR_COMMIT_SIG(ourParams, theirParams, anchorTx, anchorOutputIndex, Commitment(0, ourCommitTx, state, theirRevocationHash))
|
||||||
|
|
||||||
case Event(CMD_CLOSE(_), _) => goto(CLOSED)
|
case Event(CMD_CLOSE(_), _) => goto(CLOSED)
|
||||||
|
@ -36,7 +36,7 @@ case object IO_NORMAL extends State
|
|||||||
|
|
||||||
// @formatter:on
|
// @formatter:on
|
||||||
|
|
||||||
class AuthHandler(them: ActorRef, blockchain: ActorRef, our_anchor: Boolean) extends LoggingFSM[State, Data] with Stash {
|
class AuthHandler(them: ActorRef, blockchain: ActorRef, our_anchor: Boolean, amount: Long) extends LoggingFSM[State, Data] with Stash {
|
||||||
|
|
||||||
import AuthHandler._
|
import AuthHandler._
|
||||||
|
|
||||||
@ -71,7 +71,10 @@ class AuthHandler(them: ActorRef, blockchain: ActorRef, our_anchor: Boolean) ext
|
|||||||
log.info(s"their_nodeid: ${BinaryData(auth.nodeId.key.toByteArray)}")
|
log.info(s"their_nodeid: ${BinaryData(auth.nodeId.key.toByteArray)}")
|
||||||
assert(Crypto.verifySignature(Crypto.hash256(session_key.pub), signature2bin(auth.sessionSig), pubkey2bin(auth.nodeId)), "auth failed")
|
assert(Crypto.verifySignature(Crypto.hash256(session_key.pub), signature2bin(auth.sessionSig), pubkey2bin(auth.nodeId)), "auth failed")
|
||||||
log.info(s"initializing channel actor")
|
log.info(s"initializing channel actor")
|
||||||
val anchorInput_opt = if (our_anchor) Some(AnchorInput(1000000L, OutPoint(Hex.decode("7727730d21428276a4d6b0e16f3a3e6f3a07a07dc67151e6a88d4a8c3e8edb24").reverse, 1), SignData("76a914e093fbc19866b98e0fbc25d79d0ad0f0375170af88ac", Base58Check.decode("cU1YgK56oUKAtV6XXHZeJQjEx1KGXkZS1pGiKpyW4mUyKYFJwWFg")._2))) else None
|
val anchorInput_opt = if (our_anchor)
|
||||||
|
Some(AnchorInput(amount))
|
||||||
|
else
|
||||||
|
None
|
||||||
val channel_params = OurChannelParams(Globals.default_locktime, Globals.commit_priv, Globals.final_priv, Globals.default_mindepth, Globals.default_commitfee, "sha-seed".getBytes())
|
val channel_params = OurChannelParams(Globals.default_locktime, Globals.commit_priv, Globals.final_priv, Globals.default_mindepth, Globals.default_commitfee, "sha-seed".getBytes())
|
||||||
val channel = context.actorOf(Props(new Channel(blockchain, channel_params, anchorInput_opt)), name = "channel")
|
val channel = context.actorOf(Props(new Channel(blockchain, channel_params, anchorInput_opt)), name = "channel")
|
||||||
channel ! INPUT_NONE
|
channel ! INPUT_NONE
|
||||||
|
@ -9,7 +9,7 @@ import fr.acinq.eclair.{CreateChannel, Boot}
|
|||||||
/**
|
/**
|
||||||
* Created by PM on 27/10/2015.
|
* Created by PM on 27/10/2015.
|
||||||
*/
|
*/
|
||||||
class Client(remote: InetSocketAddress) extends Actor with ActorLogging {
|
class Client(remote: InetSocketAddress, amount: Long) extends Actor with ActorLogging {
|
||||||
|
|
||||||
import Tcp._
|
import Tcp._
|
||||||
import context.system
|
import context.system
|
||||||
@ -22,7 +22,7 @@ class Client(remote: InetSocketAddress) extends Actor with ActorLogging {
|
|||||||
case c@Connected(remote, local) =>
|
case c@Connected(remote, local) =>
|
||||||
log.info(s"connected to $remote")
|
log.info(s"connected to $remote")
|
||||||
val connection = sender()
|
val connection = sender()
|
||||||
Boot.register ! CreateChannel(connection, true)
|
Boot.register ! CreateChannel(connection, true, amount)
|
||||||
// TODO : kill this actor ?
|
// TODO : kill this actor ?
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@ import java.net.InetSocketAddress
|
|||||||
|
|
||||||
import akka.actor.{Actor, ActorLogging, ActorSystem, Props}
|
import akka.actor.{Actor, ActorLogging, ActorSystem, Props}
|
||||||
import akka.io.{IO, Tcp}
|
import akka.io.{IO, Tcp}
|
||||||
|
import com.typesafe.config.ConfigFactory
|
||||||
import fr.acinq.eclair.{CreateChannel, Boot}
|
import fr.acinq.eclair.{CreateChannel, Boot}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -32,7 +33,8 @@ class Server(address: InetSocketAddress) extends Actor with ActorLogging {
|
|||||||
|
|
||||||
object Server extends App {
|
object Server extends App {
|
||||||
implicit val system = ActorSystem("system")
|
implicit val system = ActorSystem("system")
|
||||||
val server = system.actorOf(Props[Server], "server")
|
val config = ConfigFactory.load()
|
||||||
|
val server = system.actorOf(Server.props(config.getString("eclair.server.address"), config.getInt("eclair.server.port")), "server")
|
||||||
|
|
||||||
def props(address: InetSocketAddress): Props = Props(classOf[Server], address)
|
def props(address: InetSocketAddress): Props = Props(classOf[Server], address)
|
||||||
def props(address: String, port: Int): Props = props(new InetSocketAddress(address, port))
|
def props(address: String, port: Int): Props = props(new InetSocketAddress(address, port))
|
||||||
|
@ -27,7 +27,9 @@ abstract class TestHelper(_system: ActorSystem) extends TestKit(_system) with Im
|
|||||||
TestKit.shutdownActorSystem(system)
|
TestKit.shutdownActorSystem(system)
|
||||||
}
|
}
|
||||||
|
|
||||||
val anchorInput = AnchorInput(100100000L, OutPoint(Hex.decode("7727730d21428276a4d6b0e16f3a3e6f3a07a07dc67151e6a88d4a8c3e8edb24").reverse, 1), SignData("76a914e093fbc19866b98e0fbc25d79d0ad0f0375170af88ac", Base58Check.decode("cU1YgK56oUKAtV6XXHZeJQjEx1KGXkZS1pGiKpyW4mUyKYFJwWFg")._2))
|
val anchorInput = AnchorInput(100100000L)
|
||||||
|
val previousTxOutput = OutPoint(Hex.decode("7727730d21428276a4d6b0e16f3a3e6f3a07a07dc67151e6a88d4a8c3e8edb24").reverse, 1)
|
||||||
|
val signData = SignData("76a914e093fbc19866b98e0fbc25d79d0ad0f0375170af88ac", Base58Check.decode("cU1YgK56oUKAtV6XXHZeJQjEx1KGXkZS1pGiKpyW4mUyKYFJwWFg")._2)
|
||||||
|
|
||||||
val our_commitkey_priv = Base58Check.decode("cQPmcNr6pwBQPyGfab3SksE9nTCtx9ism9T4dkS9dETNU2KKtJHk")._2
|
val our_commitkey_priv = Base58Check.decode("cQPmcNr6pwBQPyGfab3SksE9nTCtx9ism9T4dkS9dETNU2KKtJHk")._2
|
||||||
val our_finalkey_priv = Base58Check.decode("cUrAtLtV7GGddqdkhUxnbZVDWGJBTducpPoon3eKp9Vnr1zxs6BG")._2
|
val our_finalkey_priv = Base58Check.decode("cUrAtLtV7GGddqdkhUxnbZVDWGJBTducpPoon3eKp9Vnr1zxs6BG")._2
|
||||||
@ -55,7 +57,7 @@ abstract class TestHelper(_system: ActorSystem) extends TestKit(_system) with Im
|
|||||||
if (expectMsgClass(classOf[State]) == targetState) return (node, channelDesc)
|
if (expectMsgClass(classOf[State]) == targetState) return (node, channelDesc)
|
||||||
channelDesc = channelDesc.copy(ourParams = Some(ourParams))
|
channelDesc = channelDesc.copy(ourParams = Some(ourParams))
|
||||||
node ! open_channel(ourParams.delay, ourRevocationHash, ourCommitPubKey, ourFinalPubKey, WILL_CREATE_ANCHOR, Some(ourParams.minDepth), ourParams.commitmentFee)
|
node ! open_channel(ourParams.delay, ourRevocationHash, ourCommitPubKey, ourFinalPubKey, WILL_CREATE_ANCHOR, Some(ourParams.minDepth), ourParams.commitmentFee)
|
||||||
val (anchorTx, anchorOutputIndex) = makeAnchorTx(ourCommitPubKey, theirParams.commitPubKey, anchorInput.amount, anchorInput.previousTxOutput, anchorInput.signData)
|
val (anchorTx, anchorOutputIndex) = makeAnchorTx(ourCommitPubKey, theirParams.commitPubKey, anchorInput.amount, previousTxOutput, signData)
|
||||||
// we fund the channel with the anchor tx, so the money is ours
|
// we fund the channel with the anchor tx, so the money is ours
|
||||||
val state = ChannelState(them = ChannelOneSide(0, 0, Seq()), us = ChannelOneSide(anchorInput.amount * 1000- ourParams.commitmentFee * 1000, ourParams.commitmentFee * 1000, Seq()))
|
val state = ChannelState(them = ChannelOneSide(0, 0, Seq()), us = ChannelOneSide(anchorInput.amount * 1000- ourParams.commitmentFee * 1000, ourParams.commitmentFee * 1000, Seq()))
|
||||||
// we build our commitment tx, leaving it unsigned
|
// we build our commitment tx, leaving it unsigned
|
||||||
|
Loading…
Reference in New Issue
Block a user