mirror of
https://github.com/ACINQ/eclair.git
synced 2024-11-20 02:27:32 +01:00
dummy impl non-functional, compiles and run
This commit is contained in:
parent
2899aff02d
commit
d5640fdd07
@ -50,5 +50,11 @@
|
||||
<artifactId>logback-classic</artifactId>
|
||||
<version>1.1.3</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<!--conditional logging -->
|
||||
<groupId>janino</groupId>
|
||||
<artifactId>janino</artifactId>
|
||||
<version>2.5.10</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
56
eclair-demo/src/main/resources/logback.xml
Normal file
56
eclair-demo/src/main/resources/logback.xml
Normal file
@ -0,0 +1,56 @@
|
||||
<?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>
|
||||
<withJansi>false</withJansi>
|
||||
<filter class="ch.qos.logback.core.filter.EvaluatorFilter">
|
||||
<evaluator> <!-- defaults to type ch.qos.logback.classic.boolex.JaninoEventEvaluator -->
|
||||
<expression>return logger.contains("Node");</expression>
|
||||
</evaluator>
|
||||
<OnMatch>DENY</OnMatch>
|
||||
<OnMismatch>ACCEPT</OnMismatch>
|
||||
</filter>
|
||||
<encoder>
|
||||
<pattern>%yellow(${HOSTNAME} %d) %highlight(%-5level) %logger{36} %X{akkaSource} - %msg%ex{12}%n</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<appender name="ALICE" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<target>System.out</target>
|
||||
<withJansi>false</withJansi>
|
||||
<filter class="ch.qos.logback.core.filter.EvaluatorFilter">
|
||||
<evaluator> <!-- defaults to type ch.qos.logback.classic.boolex.JaninoEventEvaluator -->
|
||||
<expression>return ((String) mdc.get("akkaSource")).contains("alice");</expression>
|
||||
</evaluator>
|
||||
<OnMismatch>DENY</OnMismatch>
|
||||
<OnMatch>ACCEPT</OnMatch>
|
||||
</filter>
|
||||
<encoder>
|
||||
<pattern>%yellow(${HOSTNAME} %d) %highlight(%-5level) %logger{36} %X{akkaSource} - %blue(%msg) %ex{12}%n</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<appender name="BOB" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<target>System.out</target>
|
||||
<withJansi>false</withJansi>
|
||||
<filter class="ch.qos.logback.core.filter.EvaluatorFilter">
|
||||
<evaluator> <!-- defaults to type ch.qos.logback.classic.boolex.JaninoEventEvaluator -->
|
||||
<expression>return ((String) mdc.get("akkaSource")).contains("bob");</expression>
|
||||
</evaluator>
|
||||
<OnMismatch>DENY</OnMismatch>
|
||||
<OnMatch>ACCEPT</OnMatch>
|
||||
</filter>
|
||||
<encoder>
|
||||
<pattern>%yellow(${HOSTNAME} %d) %highlight(%-5level) %logger{36} %X{akkaSource} - %red(%msg) %ex{12}%n</pattern>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<root level="DEBUG">
|
||||
<appender-ref ref="ALICE"/>
|
||||
<appender-ref ref="BOB"/>
|
||||
<appender-ref ref="CONSOLE"/>
|
||||
|
||||
</root>
|
||||
|
||||
</configuration>
|
@ -1,10 +1,8 @@
|
||||
package fr.acinq.eclair
|
||||
|
||||
import akka.actor.{Props, ActorSystem}
|
||||
import com.google.protobuf.ByteString
|
||||
import lightning._
|
||||
import lightning.locktime.Locktime._
|
||||
import lightning.open_channel.anchor_offer.WILL_CREATE_ANCHOR
|
||||
import lightning.sha256_hash
|
||||
import org.bouncycastle.util.encoders.Hex
|
||||
|
||||
/**
|
||||
* Created by PM on 20/08/2015.
|
||||
@ -13,46 +11,18 @@ object Boot extends App {
|
||||
|
||||
val system = ActorSystem()
|
||||
|
||||
val node = system.actorOf(Props(classOf[Node]))
|
||||
val alice = system.actorOf(Props(new Node(Hex.decode("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"), Hex.decode("bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"), INIT_WITHANCHOR)), name = "alice")
|
||||
val bob = system.actorOf(Props(new Node(Hex.decode("cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc"), Hex.decode("dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd"), INIT_NOANCHOR)), name = "bob")
|
||||
|
||||
node ! open_channel(
|
||||
delay = locktime(Blocks(1)),
|
||||
revocationHash = sha256_hash(1, 1, 1, 1),
|
||||
commitKey = bitcoin_pubkey(ByteString.copyFromUtf8("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")),
|
||||
finalKey = bitcoin_pubkey(ByteString.copyFromUtf8("bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb")),
|
||||
anch = WILL_CREATE_ANCHOR,
|
||||
minDepth = Some(2),
|
||||
commitmentFee = 100)
|
||||
bob.tell(INPUT_NONE, alice)
|
||||
alice.tell(INPUT_NONE, bob)
|
||||
|
||||
node ! open_anchor(
|
||||
txid = sha256_hash(1, 1, 1, 1),
|
||||
outputIndex = 1,
|
||||
amount = 100000000L,
|
||||
commitSig = signature(1, 1, 1, 1, 0, 0, 0, 0))
|
||||
Thread.sleep(3000)
|
||||
alice ! TxConfirmed(sha256_hash(1, 2, 3, 4), 1)
|
||||
bob ! TxConfirmed(sha256_hash(1, 2, 3, 4), 1)
|
||||
|
||||
node ! TxConfirmed(1)
|
||||
node ! TxConfirmed(2)
|
||||
Thread.sleep(2000)
|
||||
alice ! TxConfirmed(sha256_hash(1, 2, 3, 4), 2)
|
||||
bob ! TxConfirmed(sha256_hash(1, 2, 3, 4), 2)
|
||||
|
||||
node ! open_complete(
|
||||
blockid = Some(sha256_hash(1, 1, 1, 1))
|
||||
)
|
||||
|
||||
node ! update_add_htlc(
|
||||
revocationHash = sha256_hash(1, 1, 1, 1),
|
||||
amount = 1000,
|
||||
rHash = sha256_hash(1, 1, 1, 1),
|
||||
expiry = locktime(Blocks(4)))
|
||||
|
||||
node ! update_signature(
|
||||
sig = signature(1, 1, 1, 1, 0, 0, 0, 0),
|
||||
revocationPreimage = sha256_hash(1, 1, 1, 1))
|
||||
|
||||
// this is sent by the next node
|
||||
node ! update_complete_htlc(
|
||||
revocationHash = sha256_hash(1, 1, 1, 1),
|
||||
r = sha256_hash(1, 1, 1, 1))
|
||||
|
||||
node ! update_signature(
|
||||
sig = signature(1, 1, 1, 1, 0, 0, 0, 0),
|
||||
revocationPreimage = sha256_hash(1, 1, 1, 1))
|
||||
}
|
||||
|
@ -1,11 +1,16 @@
|
||||
package fr.acinq.eclair
|
||||
|
||||
import akka.actor.{LoggingFSM, FSM}
|
||||
import akka.actor.{ActorRef, LoggingFSM}
|
||||
import com.google.protobuf.ByteString
|
||||
import fr.acinq.bitcoin.Transaction
|
||||
import fr.acinq.bitcoin.Crypto._
|
||||
import fr.acinq.bitcoin._
|
||||
import fr.acinq.lightning._
|
||||
import lightning._
|
||||
import lightning.locktime.Locktime.Blocks
|
||||
import lightning.open_channel.anchor_offer.WILL_CREATE_ANCHOR
|
||||
import lightning.open_channel.anchor_offer.{WILL_CREATE_ANCHOR, WONT_CREATE_ANCHOR}
|
||||
import org.bouncycastle.util.encoders.Hex
|
||||
|
||||
import scala.util.Try
|
||||
|
||||
/**
|
||||
* Created by PM on 20/08/2015.
|
||||
@ -15,9 +20,13 @@ import lightning.open_channel.anchor_offer.WILL_CREATE_ANCHOR
|
||||
|
||||
sealed trait State
|
||||
case object INIT_NOANCHOR extends State
|
||||
case object INIT_WITHANCHOR extends State
|
||||
case object OPEN_WAIT_FOR_OPEN_NOANCHOR extends State
|
||||
case object OPEN_WAIT_FOR_OPEN_WITHANCHOR extends State
|
||||
case object OPEN_WAIT_FOR_ANCHOR extends State
|
||||
case object OPEN_WAITING extends State
|
||||
case object OPEN_WAIT_FOR_COMMIT_SIG extends State
|
||||
case object OPEN_WAITING_THEIRANCHOR extends State
|
||||
case object OPEN_WAITING_OURANCHOR extends State
|
||||
case object OPEN_WAIT_FOR_COMPLETE extends State
|
||||
case object NORMAL extends State
|
||||
case object WAIT_FOR_HTLC_ACCEPT extends State
|
||||
@ -30,7 +39,7 @@ case object CLOSED extends State
|
||||
case object INPUT_NONE
|
||||
|
||||
sealed trait BlockchainEvent
|
||||
final case class TxConfirmed(confirmations: Int)
|
||||
final case class TxConfirmed(blockId: sha256_hash, confirmations: Int)
|
||||
|
||||
sealed trait Commands
|
||||
final case class SendHtlcUpdate(amount: Long, finalPayee: String, rHash: sha256_hash)
|
||||
@ -40,68 +49,143 @@ final case class SendHtlcUpdate(amount: Long, finalPayee: String, rHash: sha256_
|
||||
sealed trait Data
|
||||
case object Uninitialized extends Data
|
||||
final case class ChannelParams(delay: locktime, commitKey: bitcoin_pubkey, finalKey: bitcoin_pubkey, minDepth: Int, commitmentFee: Long)
|
||||
final case class Anchor(txid: sha256_hash, outputIndex: Int, amount: Long)
|
||||
final case class CommitmentTx(tx: Transaction, theirSig: signature, ourRevocationPreimage: sha256_hash)
|
||||
final case class Anchor(txid: sha256_hash, outputIndex: Int, amount: Long, pubKeyScript: Seq[ScriptElt])
|
||||
final case class CommitmentTx(tx: Transaction, ourRevocationPreimage: sha256_hash)
|
||||
final case class DATA_OPEN_WAIT_FOR_OPEN_NOANCHOR(ourParams: ChannelParams, ourRevocationPreimage: sha256_hash) extends Data
|
||||
final case class DATA_OPEN_WAIT_FOR_OPEN_WITHANCHOR(ourParams: ChannelParams, ourRevocationPreimage: sha256_hash) extends Data
|
||||
final case class DATA_OPEN_WAIT_FOR_ANCHOR(ourParams: ChannelParams, theirParams: ChannelParams, ourRevocationPreimage: sha256_hash, theirRevocationHash: sha256_hash) extends Data
|
||||
final case class DATA_OPEN_WAIT_FOR_COMMIT_SIG(ourParams: ChannelParams, theirParams: ChannelParams, anchor: Anchor, ourRevocationPreimage: sha256_hash, theirRevocationHash: sha256_hash) extends Data
|
||||
final case class DATA_OPEN_WAITING(ourParams: ChannelParams, theirParams: ChannelParams, anchor: Anchor, commitmentTx: CommitmentTx, otherPartyOpen: Boolean = false) extends Data
|
||||
final case class DATA_NORMAL(ourParams: ChannelParams, theirParams: ChannelParams, anchor: Anchor, commitmentTx: CommitmentTx) extends Data
|
||||
|
||||
//
|
||||
|
||||
class Node extends LoggingFSM[State, Data] {
|
||||
class Node(val commitPrivKey: BinaryData, val finalPrivKey: BinaryData, val initialState: State = INIT_NOANCHOR) extends LoggingFSM[State, Data] {
|
||||
|
||||
val DEFAULT_delay = locktime(Blocks(1))
|
||||
val DEFAULT_commitKey = bitcoin_pubkey(ByteString.copyFromUtf8("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"))
|
||||
val DEFAULT_finalKey = bitcoin_pubkey(ByteString.copyFromUtf8("bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"))
|
||||
val DEFAULT_minDepth = 2
|
||||
val DEFAULT_commitmentFee = 100
|
||||
|
||||
startWith(INIT_NOANCHOR, Uninitialized)
|
||||
val commitPubKey = bitcoin_pubkey(ByteString.copyFrom(Crypto.publicKeyFromPrivateKey(commitPrivKey.key.toByteArray)))
|
||||
val finalPubKey = bitcoin_pubkey(ByteString.copyFrom(Crypto.publicKeyFromPrivateKey(finalPrivKey.key.toByteArray)))
|
||||
|
||||
// TODO
|
||||
var them: ActorRef = null
|
||||
|
||||
startWith(initialState, Uninitialized)
|
||||
|
||||
when(INIT_NOANCHOR) {
|
||||
case Event(INPUT_NONE, _) =>
|
||||
val ourParams = ChannelParams(DEFAULT_delay, DEFAULT_commitKey, DEFAULT_finalKey, DEFAULT_minDepth, DEFAULT_commitmentFee)
|
||||
val ourRevocationHashPreimage = sha256_hash(1, 1, 1, 1)
|
||||
val ourRevocationHash = sha256_hash(1, 1, 1, 1)
|
||||
// TODO : send open_channel(delay, ourRevocationHash, commitKey, finalKey, WONT_CREATE_ANCHOR, minDepth, commitmentFee)
|
||||
them = sender
|
||||
val ourParams = ChannelParams(DEFAULT_delay, commitPubKey, finalPubKey, DEFAULT_minDepth, DEFAULT_commitmentFee)
|
||||
val ourRevocationHashPreimage = sha256_hash(1, 2, 3, 4) //TODO : should be random
|
||||
val ourRevocationHash = Crypto.sha256(ourRevocationHashPreimage)
|
||||
sender ! open_channel(ourParams.delay, ourRevocationHash, ourParams.commitKey, ourParams.finalKey, WONT_CREATE_ANCHOR, Some(ourParams.minDepth), ourParams.commitmentFee)
|
||||
goto(OPEN_WAIT_FOR_OPEN_NOANCHOR) using DATA_OPEN_WAIT_FOR_OPEN_NOANCHOR(ourParams, ourRevocationHashPreimage)
|
||||
}
|
||||
|
||||
when(INIT_WITHANCHOR) {
|
||||
case Event(INPUT_NONE, _) =>
|
||||
them = sender
|
||||
val ourParams = ChannelParams(DEFAULT_delay, commitPubKey, finalPubKey, DEFAULT_minDepth, DEFAULT_commitmentFee)
|
||||
val ourRevocationHashPreimage = sha256_hash(1, 2, 3, 4) //TODO : should be random
|
||||
val ourRevocationHash = Crypto.sha256(ourRevocationHashPreimage)
|
||||
sender ! open_channel(ourParams.delay, ourRevocationHash, ourParams.commitKey, ourParams.finalKey, WILL_CREATE_ANCHOR, Some(ourParams.minDepth), ourParams.commitmentFee)
|
||||
goto(OPEN_WAIT_FOR_OPEN_WITHANCHOR) using DATA_OPEN_WAIT_FOR_OPEN_WITHANCHOR(ourParams, ourRevocationHashPreimage)
|
||||
}
|
||||
|
||||
when(OPEN_WAIT_FOR_OPEN_NOANCHOR) {
|
||||
case Event(open_channel(delay, revocationHash, commitKey, finalKey, WILL_CREATE_ANCHOR, minDepth, commitmentFee), DATA_OPEN_WAIT_FOR_OPEN_NOANCHOR(ourParams, ourRevocationPreimage)) =>
|
||||
val theirParams = ChannelParams(delay, commitKey, finalKey, minDepth.get, commitmentFee)
|
||||
goto(OPEN_WAIT_FOR_ANCHOR) using DATA_OPEN_WAIT_FOR_ANCHOR(ourParams, theirParams, ourRevocationPreimage, revocationHash)
|
||||
}
|
||||
|
||||
when(OPEN_WAIT_FOR_ANCHOR) {
|
||||
case Event(open_anchor(txid, outputIndex, amount, commitSig), DATA_OPEN_WAIT_FOR_ANCHOR(ourParams, theirParams, ourRevocationPreimage, theirRevocationHash)) =>
|
||||
val anchor = Anchor(txid, outputIndex, amount)
|
||||
// TODO : build our commitment tx and check counterparty's sig
|
||||
// TODO : build counterparty's commitment tx and sign it
|
||||
val ourSig = signature(1, 1, 1, 1, 0, 0, 0, 0)
|
||||
// TODO : reply with open_commit_sig(sig)
|
||||
// TODO : register for confirmations of anchor tx on the bitcoin network
|
||||
goto(OPEN_WAITING) using DATA_OPEN_WAITING(ourParams, theirParams, anchor, null, false)
|
||||
when(OPEN_WAIT_FOR_OPEN_WITHANCHOR) {
|
||||
case Event(open_channel(delay, revocationHash, commitKey, finalKey, WONT_CREATE_ANCHOR, minDepth, commitmentFee), DATA_OPEN_WAIT_FOR_OPEN_WITHANCHOR(ourParams, ourRevocationHashPreimage)) =>
|
||||
val theirParams = ChannelParams(delay, commitKey, finalKey, minDepth.get, commitmentFee)
|
||||
// TODO create the anchor
|
||||
val anchor = Anchor(sha256_hash(1, 2, 3, 4), 0, 100000, OP_HASH160 :: OP_PUSHDATA(hash160(Script.createMultiSigMofN(2, Seq(pubkey2bin(theirParams.commitKey), pubkey2bin(ourParams.commitKey))))) :: OP_EQUAL :: Nil)
|
||||
// then we build their commitment tx and sign it
|
||||
val state = ChannelState(ChannelOneSide(anchor.amount, 0, Seq()), ChannelOneSide(0, 0, Seq()))
|
||||
val theirCommitTx = makeCommitTx(theirParams.finalKey, ourParams.finalKey, ourParams.delay, anchor.txid, anchor.outputIndex, Crypto.sha256(ourRevocationHashPreimage), state.copy(a = state.b, b = state.a))
|
||||
val ourSig = bin2signature(Transaction.signInput(theirCommitTx, 0, Script.createMultiSigMofN(2, Seq(pubkey2bin(theirParams.commitKey), pubkey2bin(ourParams.commitKey))), SIGHASH_ALL, pubkey2bin(commitPrivKey)))
|
||||
sender ! open_anchor(anchor.txid, anchor.outputIndex, anchor.amount, ourSig)
|
||||
goto(OPEN_WAIT_FOR_COMMIT_SIG) using DATA_OPEN_WAIT_FOR_COMMIT_SIG(ourParams, theirParams, anchor, ourRevocationHashPreimage, revocationHash)
|
||||
}
|
||||
|
||||
when(OPEN_WAITING) {
|
||||
case Event(TxConfirmed(confirmations), DATA_OPEN_WAITING(ourParams, _, _, _, _)) if confirmations < ourParams.minDepth =>
|
||||
when(OPEN_WAIT_FOR_ANCHOR) {
|
||||
case Event(open_anchor(txid, outputIndex, amount, commitSig), DATA_OPEN_WAIT_FOR_ANCHOR(ourParams, theirParams, ourRevocationHashPreimage, theirRevocationHash)) =>
|
||||
val anchor = Anchor(txid, outputIndex, amount, OP_HASH160 :: OP_PUSHDATA(hash160(Script.createMultiSigMofN(2, Seq(pubkey2bin(theirParams.commitKey), pubkey2bin(ourParams.commitKey))))) :: OP_EQUAL :: Nil)
|
||||
val state = ChannelState(ChannelOneSide(amount, 0, Seq()), ChannelOneSide(0, 0, Seq()))
|
||||
// we build our commitment tx, sign it and check that it is spendable using the counterparty's sig
|
||||
val ourCommitTx = makeCommitTx(ourParams.finalKey, theirParams.finalKey, theirParams.delay, anchor.txid, anchor.outputIndex, theirRevocationHash, state)
|
||||
val sigB = Transaction.signInput(ourCommitTx, 0, Script.createMultiSigMofN(2, Seq(pubkey2bin(theirParams.commitKey), pubkey2bin(ourParams.commitKey))), SIGHASH_ALL, pubkey2bin(commitPrivKey))
|
||||
val scriptSig = Script.write(OP_0 :: OP_PUSHDATA(commitSig) :: OP_PUSHDATA(sigB) :: OP_PUSHDATA(Script.createMultiSigMofN(2, Seq(pubkey2bin(theirParams.commitKey), pubkey2bin(ourParams.commitKey)))) :: Nil)
|
||||
val signedCommitTx = ourCommitTx.updateSigScript(0, scriptSig)
|
||||
val ok = Try(Transaction.correctlySpends(signedCommitTx, Map(OutPoint(txid, outputIndex) -> BinaryData(Script.write(anchor.pubKeyScript))), ScriptFlags.STANDARD_SCRIPT_VERIFY_FLAGS)).isSuccess
|
||||
// TODO : return Error and close channel if !ok
|
||||
// then we build their commitment tx and sign it
|
||||
val theirCommitTx = makeCommitTx(theirParams.finalKey, ourParams.finalKey, ourParams.delay, anchor.txid, anchor.outputIndex, Crypto.sha256(ourRevocationHashPreimage), state.copy(a = state.b, b = state.a))
|
||||
val ourSig = bin2signature(Transaction.signInput(theirCommitTx, 0, Script.createMultiSigMofN(2, Seq(pubkey2bin(theirParams.commitKey), pubkey2bin(ourParams.commitKey))), SIGHASH_ALL, pubkey2bin(commitPrivKey)))
|
||||
sender ! open_commit_sig(ourSig)
|
||||
// TODO : register for confirmations of anchor tx on the bitcoin network
|
||||
goto(OPEN_WAITING_THEIRANCHOR) using DATA_OPEN_WAITING(ourParams, theirParams, anchor, CommitmentTx(ourCommitTx, ourRevocationHashPreimage), false)
|
||||
}
|
||||
|
||||
when(OPEN_WAIT_FOR_COMMIT_SIG) {
|
||||
case Event(open_commit_sig(theirSig), DATA_OPEN_WAIT_FOR_COMMIT_SIG(ourParams, theirParams, anchor, ourRevocationHashPreimage, theirRevocationHash)) =>
|
||||
val state = ChannelState(ChannelOneSide(anchor.amount, 0, Seq()), ChannelOneSide(0, 0, Seq()))
|
||||
// we build our commitment tx, sign it and check that it is spendable using the counterparty's sig
|
||||
val ourCommitTx = makeCommitTx(ourParams.finalKey, theirParams.finalKey, theirParams.delay, anchor.txid, anchor.outputIndex, theirRevocationHash, state)
|
||||
val sigB = Transaction.signInput(ourCommitTx, 0, Script.createMultiSigMofN(2, Seq(pubkey2bin(theirParams.commitKey), pubkey2bin(ourParams.commitKey))), SIGHASH_ALL, pubkey2bin(commitPrivKey))
|
||||
val scriptSig = Script.write(OP_0 :: OP_PUSHDATA(theirSig) :: OP_PUSHDATA(sigB) :: OP_PUSHDATA(Script.createMultiSigMofN(2, Seq(pubkey2bin(theirParams.commitKey), pubkey2bin(ourParams.commitKey)))) :: Nil)
|
||||
val signedCommitTx = ourCommitTx.updateSigScript(0, scriptSig)
|
||||
val ok = Try(Transaction.correctlySpends(signedCommitTx, Map(OutPoint(anchor.txid, anchor.outputIndex) -> BinaryData(Script.write(anchor.pubKeyScript))), ScriptFlags.STANDARD_SCRIPT_VERIFY_FLAGS)).isSuccess
|
||||
// TODO : return Error and close channel if !ok
|
||||
goto(OPEN_WAITING_OURANCHOR) using DATA_OPEN_WAITING(ourParams, theirParams, anchor, CommitmentTx(ourCommitTx, ourRevocationHashPreimage), false)
|
||||
}
|
||||
|
||||
when(OPEN_WAITING_THEIRANCHOR) {
|
||||
case Event(TxConfirmed(blockId, confirmations), DATA_OPEN_WAITING(ourParams, _, _, _, _)) if confirmations < ourParams.minDepth =>
|
||||
// TODO : check anchor pub key script
|
||||
log.info(s"got $confirmations confirmation(s) for anchor tx")
|
||||
stay
|
||||
|
||||
case Event(TxConfirmed(confirmations), d@DATA_OPEN_WAITING(ourParams, _, _, _, false)) if confirmations >= ourParams.minDepth =>
|
||||
case Event(TxConfirmed(blockId, confirmations), d@DATA_OPEN_WAITING(ourParams, _, _, _, false)) if confirmations >= ourParams.minDepth =>
|
||||
// TODO : check anchor pub key script
|
||||
log.info(s"got $confirmations confirmation(s) for anchor tx, minDepth reached")
|
||||
// TODO : send open_complete(blockid)
|
||||
them ! open_complete(Some(blockId))
|
||||
goto(OPEN_WAIT_FOR_COMPLETE) using DATA_NORMAL(d.ourParams, d.theirParams, d.anchor, d.commitmentTx)
|
||||
|
||||
case Event(TxConfirmed(confirmations), d@DATA_OPEN_WAITING(ourParams, _, _, _, true)) if confirmations >= ourParams.minDepth =>
|
||||
case Event(TxConfirmed(blockId, confirmations), d@DATA_OPEN_WAITING(ourParams, _, _, _, true)) if confirmations >= ourParams.minDepth =>
|
||||
log.info(s"got $confirmations confirmation(s) for anchor tx, minDepth reached, and already received their open_complete")
|
||||
// TODO : send open_complete(blockid)
|
||||
them ! open_complete(Some(blockId))
|
||||
goto(NORMAL) using DATA_NORMAL(d.ourParams, d.theirParams, d.anchor, d.commitmentTx)
|
||||
|
||||
case Event(open_complete(blockid_opt), d@DATA_OPEN_WAITING(ourParams, _, _, _, _)) =>
|
||||
log.info(s"received their open_complete")
|
||||
case Event(open_complete(blockId_opt), d@DATA_OPEN_WAITING(ourParams, _, _, _, _)) =>
|
||||
log.info(s"received their open_complete, blockId=${blockId_opt.map(x => Hex.toHexString(sha2562bin(x))).getOrElse("unknown")}")
|
||||
stay using d.copy(otherPartyOpen = true)
|
||||
}
|
||||
|
||||
when(OPEN_WAITING_OURANCHOR) {
|
||||
case Event(TxConfirmed(blockId, confirmations), DATA_OPEN_WAITING(ourParams, _, _, _, _)) if confirmations < ourParams.minDepth =>
|
||||
// TODO : check anchor pub key script
|
||||
log.info(s"got $confirmations confirmation(s) for anchor tx")
|
||||
stay
|
||||
|
||||
case Event(TxConfirmed(blockId, confirmations), d@DATA_OPEN_WAITING(ourParams, _, _, _, false)) if confirmations >= ourParams.minDepth =>
|
||||
// TODO : check anchor pub key script
|
||||
log.info(s"got $confirmations confirmation(s) for anchor tx, minDepth reached")
|
||||
them ! open_complete(Some(blockId))
|
||||
goto(OPEN_WAIT_FOR_COMPLETE) using DATA_NORMAL(d.ourParams, d.theirParams, d.anchor, d.commitmentTx)
|
||||
|
||||
case Event(TxConfirmed(blockId, confirmations), d@DATA_OPEN_WAITING(ourParams, _, _, _, true)) if confirmations >= ourParams.minDepth =>
|
||||
log.info(s"got $confirmations confirmation(s) for anchor tx, minDepth reached, and already received their open_complete")
|
||||
them ! open_complete(Some(blockId))
|
||||
goto(NORMAL) using DATA_NORMAL(d.ourParams, d.theirParams, d.anchor, d.commitmentTx)
|
||||
|
||||
case Event(open_complete(blockId_opt), d@DATA_OPEN_WAITING(ourParams, _, _, _, _)) =>
|
||||
log.info(s"received their open_complete, blockId=${blockId_opt.map(x => Hex.toHexString(sha2562bin(x))).getOrElse("unknown")}")
|
||||
stay using d.copy(otherPartyOpen = true)
|
||||
}
|
||||
|
||||
|
@ -35,6 +35,9 @@ package object lightning {
|
||||
bos.toByteArray
|
||||
}
|
||||
|
||||
// TODO : redundant with above, needed for seamless Crypto.sha256(sha256_hash)
|
||||
implicit def sha2562seq(in: sha256_hash): Seq[Byte] = sha2562bin(in)
|
||||
|
||||
implicit def bin2pubkey(in: BinaryData) = bitcoin_pubkey(ByteString.copyFrom(in))
|
||||
|
||||
implicit def array2pubkey(in: Array[Byte]) = bin2pubkey(in)
|
||||
@ -132,24 +135,28 @@ package object lightning {
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
def makeCommitTx(ours: open_channel, theirs: open_channel, anchor: open_anchor, rhash: BinaryData, channelState: ChannelState): Transaction = {
|
||||
val txIn = TxIn(OutPoint(sha2562bin(anchor.txid), anchor.outputIndex), Array.emptyByteArray, 0xffffffffL)
|
||||
val redeemScript = redeemSecretOrDelay(ours.finalKey, theirs.delay, theirs.finalKey, rhash)
|
||||
//TODO : do we really need this ?
|
||||
def makeCommitTx(ours: open_channel, theirs: open_channel, anchor: open_anchor, rhash: BinaryData, channelState: ChannelState): Transaction =
|
||||
makeCommitTx(ours.finalKey, theirs.finalKey, theirs.delay, anchor.txid, anchor.outputIndex, rhash, channelState)
|
||||
|
||||
def makeCommitTx(ourFinalKey: BinaryData, theirFinalKey: BinaryData, theirDelay: Long, anchorTxId: BinaryData, anchorOutputIndex: Int, rhash: BinaryData, channelState: ChannelState): Transaction = {
|
||||
val txIn = TxIn(OutPoint(anchorTxId, anchorOutputIndex), Array.emptyByteArray, 0xffffffffL)
|
||||
val redeemScript = redeemSecretOrDelay(ourFinalKey, theirDelay, theirFinalKey, rhash)
|
||||
|
||||
val tx = Transaction(
|
||||
version = 1,
|
||||
txIn = TxIn(OutPoint(sha2562bin(anchor.txid), anchor.outputIndex), Array.emptyByteArray, 0xffffffffL) :: Nil,
|
||||
txIn = TxIn(OutPoint(anchorTxId, anchorOutputIndex), Array.emptyByteArray, 0xffffffffL) :: Nil,
|
||||
txOut = Seq(
|
||||
TxOut(amount = channelState.a.pay, publicKeyScript = pay2sh(redeemScript)),
|
||||
TxOut(amount = channelState.b.pay, publicKeyScript = pay2sh(OP_PUSHDATA(theirs.finalKey) :: OP_CHECKSIG :: Nil))
|
||||
TxOut(amount = channelState.b.pay, publicKeyScript = pay2sh(OP_PUSHDATA(theirFinalKey) :: OP_CHECKSIG :: Nil))
|
||||
),
|
||||
lockTime = 0)
|
||||
|
||||
val sendOuts = channelState.a.htlcs.map(htlc => {
|
||||
TxOut(htlc.amount, pay2sh(scriptPubKeyHtlcSend(ours.finalKey, theirs.finalKey, htlc.amount, htlc.expiry, theirs.delay, rhash, htlc.revocationHash)))
|
||||
TxOut(htlc.amount, pay2sh(scriptPubKeyHtlcSend(ourFinalKey, theirFinalKey, htlc.amount, htlc.expiry, theirDelay, rhash, htlc.revocationHash)))
|
||||
})
|
||||
val receiveOuts = channelState.b.htlcs.map(htlc => {
|
||||
TxOut(htlc.amount, pay2sh(scriptPubKeyHtlcReceive(ours.finalKey, theirs.finalKey, htlc.amount, htlc.expiry, theirs.delay, rhash, htlc.revocationHash)))
|
||||
TxOut(htlc.amount, pay2sh(scriptPubKeyHtlcReceive(ourFinalKey, theirFinalKey, htlc.amount, htlc.expiry, theirDelay, rhash, htlc.revocationHash)))
|
||||
})
|
||||
val tx1 = tx.copy(txOut = tx.txOut ++ sendOuts ++ receiveOuts)
|
||||
tx1
|
||||
@ -163,3 +170,5 @@ package object lightning {
|
||||
if (isFunder(a)) ChannelState(c1, c2) else ChannelState(c2, c1)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user