1
0
Fork 0
mirror of https://github.com/ACINQ/eclair.git synced 2025-02-23 14:40:34 +01:00

use Satoshi explicitely instead of Long when specifying amounts, add an "Amount" field to

our "Open Channel" dialog box
This commit is contained in:
sstone 2016-08-23 10:21:04 +02:00
parent c7145d6dbc
commit bdc66ff4ce
11 changed files with 147 additions and 66 deletions

View file

@ -15,7 +15,7 @@ import grizzled.slf4j.Logging
import scala.concurrent.{Await, ExecutionContext}
import scala.concurrent.duration._
import fr.acinq.bitcoin.BitcoinJsonRPCClient
import fr.acinq.bitcoin.{BitcoinJsonRPCClient, Satoshi}
import fr.acinq.eclair.gui.MainWindow
import fr.acinq.eclair.router.IRCRouter
@ -35,22 +35,22 @@ class Setup extends Logging {
logger.info(s"nodeid=${Globals.Node.publicKey}")
val config = ConfigFactory.load()
implicit lazy val system = ActorSystem()
implicit val materializer = ActorMaterializer()
implicit val timeout = Timeout(30 seconds)
implicit val formats = org.json4s.DefaultFormats
implicit val ec = ExecutionContext.Implicits.global
val bitcoin_client = new BitcoinJsonRPCClient(
user = config.getString("eclair.bitcoind.rpcuser"),
password = config.getString("eclair.bitcoind.rpcpassword"),
host = config.getString("eclair.bitcoind.host"),
port = config.getInt("eclair.bitcoind.port"))
implicit val formats = org.json4s.DefaultFormats
implicit val ec = ExecutionContext.Implicits.global
val chain = Await.result(bitcoin_client.invoke("getblockchaininfo").map(json => (json \ "chain").extract[String]), 10 seconds)
assert(chain == "testnet" || chain == "regtest" || chain == "segnet4", "you should be on testnet or regtest or segnet4")
val bitcoinVersion = Await.result(bitcoin_client.invoke("getinfo").map(json => (json \ "version").extract[String]), 10 seconds)
implicit lazy val system = ActorSystem()
implicit val materializer = ActorMaterializer()
implicit val timeout = Timeout(30 seconds)
val blockchain = system.actorOf(Props(new PollingWatcher(new ExtendedBitcoinClient(bitcoin_client))), name = "blockchain")
val paymentHandler = config.getString("eclair.payment-handler") match {
case "local" => system.actorOf(Props[LocalPaymentHandler], name = "payment-handler")
@ -67,7 +67,7 @@ class Setup extends Logging {
override def paymentHandler: ActorRef = _setup.paymentHandler
override def connect(host: String, port: Int, amount: Long): Unit = system.actorOf(Client.props(host, port, amount, register))
override def connect(host: String, port: Int, amount: Satoshi): Unit = system.actorOf(Client.props(host, port, amount, register))
}
Http().bindAndHandle(api.route, config.getString("eclair.api.host"), config.getInt("eclair.api.port"))
}

View file

@ -5,7 +5,7 @@ import akka.http.scaladsl.model.headers.RawHeader
import akka.http.scaladsl.model.{ContentTypes, HttpEntity, HttpResponse, StatusCodes}
import akka.util.Timeout
import akka.http.scaladsl.server.Directives._
import fr.acinq.bitcoin.BinaryData
import fr.acinq.bitcoin.{BinaryData, Satoshi}
import fr.acinq.eclair._
import fr.acinq.eclair.channel._
import grizzled.slf4j.Logging
@ -42,7 +42,7 @@ trait Service extends Logging {
implicit val formats = org.json4s.DefaultFormats + new BinaryDataSerializer + new StateSerializer + new Sha256Serializer + new ShaChainSerializer
implicit val timeout = Timeout(30 seconds)
def connect(host: String, port: Int, amount: Long): Unit
def connect(host: String, port: Int, amount: Satoshi): Unit
def register: ActorRef
@ -64,7 +64,7 @@ trait Service extends Logging {
val json = parse(body).extract[JsonRPCBody]
val f_res: Future[AnyRef] = json match {
case JsonRPCBody(_, _, "connect", JString(host) :: JInt(port) :: JInt(anchor_amount) :: Nil) =>
connect(host, port.toInt, anchor_amount.toLong)
connect(host, port.toInt, Satoshi(anchor_amount.toLong))
Future.successful("ok")
case JsonRPCBody(_, _, "info", _) =>
Future.successful(Status(Globals.Node.id))

View file

@ -44,9 +44,9 @@ class ExtendedBitcoinClient(val client: BitcoinJsonRPCClient) {
* @return a Future[txid] where txid (a String) is the is of the tx that sends the bitcoins
*/
def sendFromAccount(account: String, destination: String, amount: Double)(implicit ec: ExecutionContext): Future[String] =
client.invoke("sendfrom", account, destination, amount) collect {
case JString(txid) => txid
}
client.invoke("sendfrom", account, destination, amount) collect {
case JString(txid) => txid
}
def getRawTransaction(txId: String)(implicit ec: ExecutionContext): Future[String] =
client.invoke("getrawtransaction", txId) collect {
@ -110,9 +110,9 @@ class ExtendedBitcoinClient(val client: BitcoinJsonRPCClient) {
} yield tx
}
def makeAnchorTx(ourCommitPub: BinaryData, theirCommitPub: BinaryData, amount: Long)(implicit ec: ExecutionContext): Future[(Transaction, Int)] = {
def makeAnchorTx(ourCommitPub: BinaryData, theirCommitPub: BinaryData, amount: Satoshi)(implicit ec: ExecutionContext): Future[(Transaction, Int)] = {
val anchorOutputScript = channel.Scripts.anchorPubkeyScript(ourCommitPub, theirCommitPub)
val tx = Transaction(version = 2, txIn = Seq.empty[TxIn], txOut = TxOut(Satoshi(amount), anchorOutputScript) :: Nil, lockTime = 0)
val tx = Transaction(version = 2, txIn = Seq.empty[TxIn], txOut = TxOut(amount, anchorOutputScript) :: Nil, lockTime = 0)
val future = for {
FundTransactionResponse(tx1, changepos, fee) <- fundTransaction(tx)
SignTransactionResponse(anchorTx, true) <- signTransaction(tx1)
@ -151,7 +151,7 @@ class ExtendedBitcoinClient(val client: BitcoinJsonRPCClient) {
* @return the current number of blocks in the active chain
*/
def getBlockCount(implicit ec: ExecutionContext): Future[Long] =
client.invoke("getblockcount") collect {
case JInt(count) => count.toLong
}
client.invoke("getblockcount") collect {
case JInt(count) => count.toLong
}
}

View file

@ -1,7 +1,7 @@
package fr.acinq.eclair.blockchain
import akka.actor.ActorRef
import fr.acinq.bitcoin.{Transaction, TxOut, BinaryData}
import fr.acinq.bitcoin.{BinaryData, Satoshi, Transaction, TxOut}
import fr.acinq.eclair.channel.BlockchainEvent
/**
@ -13,10 +13,17 @@ import fr.acinq.eclair.channel.BlockchainEvent
trait Watch {
def channel: ActorRef
}
final case class WatchConfirmed(channel: ActorRef, txId: BinaryData, minDepth: Int, event: BlockchainEvent) extends Watch
final case class WatchSpent(channel: ActorRef, txId: BinaryData, outputIndex: Int, minDepth: Int, event: BlockchainEvent) extends Watch
final case class WatchLost(channel: ActorRef, txId: BinaryData, minDepth: Int, event: BlockchainEvent) extends Watch // notify me if confirmation number gets below minDepth
final case class WatchLost(channel: ActorRef, txId: BinaryData, minDepth: Int, event: BlockchainEvent) extends Watch
// notify me if confirmation number gets below minDepth
final case class Publish(tx: Transaction)
final case class MakeAnchor(ourCommitPub: BinaryData, theirCommitPub: BinaryData, amount: Long)
final case class MakeAnchor(ourCommitPub: BinaryData, theirCommitPub: BinaryData, amount: Satoshi)
// @formatter:on

View file

@ -1,6 +1,6 @@
package fr.acinq.eclair.channel
import fr.acinq.bitcoin.{BinaryData, Crypto, Transaction}
import fr.acinq.bitcoin.{BinaryData, Crypto, Satoshi, Transaction}
import lightning._
import scala.concurrent.duration.FiniteDuration
@ -23,23 +23,41 @@ import scala.concurrent.duration.FiniteDuration
"Y8888P" 888 d88P 888 888 8888888888 "Y8888P"
*/
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_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_OURANCHOR extends State
case object OPEN_WAIT_FOR_COMPLETE_THEIRANCHOR extends State
case object NORMAL extends State
case object CLEARING extends State
case object NEGOTIATING extends State
case object CLOSING extends State
case object CLOSED extends State
case object ERR_ANCHOR_LOST extends State
case object ERR_ANCHOR_TIMEOUT extends State
case object ERR_INFORMATION_LEAK extends State
/*
@ -54,18 +72,28 @@ case object ERR_INFORMATION_LEAK extends State
*/
case object INPUT_NO_MORE_HTLCS
// when requesting a mutual close, we wait for as much as this timeout, then unilateral close
case object INPUT_CLOSE_COMPLETE_TIMEOUT
sealed trait BlockchainEvent
case object BITCOIN_ANCHOR_DEPTHOK extends BlockchainEvent
case object BITCOIN_ANCHOR_LOST extends BlockchainEvent
case object BITCOIN_ANCHOR_TIMEOUT extends BlockchainEvent
case object BITCOIN_ANCHOR_SPENT extends BlockchainEvent
case object BITCOIN_ANCHOR_OURCOMMIT_DELAYPASSED extends BlockchainEvent
case object BITCOIN_SPEND_THEIRS_DONE extends BlockchainEvent
case object BITCOIN_SPEND_OURS_DONE extends BlockchainEvent
case object BITCOIN_STEAL_DONE extends BlockchainEvent
case object BITCOIN_CLOSE_DONE extends BlockchainEvent
/*
@ -80,17 +108,26 @@ case object BITCOIN_CLOSE_DONE extends BlockchainEvent
*/
sealed trait Command
/**
* @param id should only be provided in tests otherwise it will be assigned automatically
*/
final case class CMD_ADD_HTLC(amountMsat: Int, rHash: sha256_hash, expiry: locktime, payment_route: route = route(route_step(0, next = route_step.Next.End(true)) :: Nil), originChannelId: Option[BinaryData] = None, id: Option[Long] = None, commit: Boolean = false) extends Command
final case class CMD_FULFILL_HTLC(id: Long, r: rval, commit: Boolean = false) extends Command
final case class CMD_FAIL_HTLC(id: Long, reason: String, commit: Boolean = false) extends Command
case object CMD_SIGN extends Command
final case class CMD_CLOSE(scriptPubKey: Option[BinaryData]) extends Command
case object CMD_GETSTATE extends Command
case object CMD_GETSTATEDATA extends Command
case object CMD_GETINFO extends Command
final case class RES_GETINFO(nodeid: BinaryData, channelid: BinaryData, state: State, data: Data)
/*
@ -105,23 +142,29 @@ final case class RES_GETINFO(nodeid: BinaryData, channelid: BinaryData, state: S
*/
sealed trait Data
case object Nothing extends Data
final case class OurChannelParams(delay: locktime, commitPrivKey: BinaryData, finalPrivKey: BinaryData, minDepth: Int, initialFeeRate: Long, shaSeed: BinaryData, anchorAmount: Option[Long], autoSignInterval: Option[FiniteDuration] = None) {
final case class OurChannelParams(delay: locktime, commitPrivKey: BinaryData, finalPrivKey: BinaryData, minDepth: Int, initialFeeRate: Long, shaSeed: BinaryData, anchorAmount: Option[Satoshi], autoSignInterval: Option[FiniteDuration] = None) {
val commitPubKey: BinaryData = Crypto.publicKeyFromPrivateKey(commitPrivKey)
val finalPubKey: BinaryData = Crypto.publicKeyFromPrivateKey(finalPrivKey)
}
final case class TheirChannelParams(delay: locktime, commitPubKey: BinaryData, finalPubKey: BinaryData, minDepth: Option[Int], initialFeeRate: Long)
object TheirChannelParams {
def apply(params: OurChannelParams) = new TheirChannelParams(params.delay, params.commitPubKey, params.finalPubKey, Some(params.minDepth), params.initialFeeRate)
}
sealed trait Direction
case object IN extends Direction
case object OUT extends Direction
case class Htlc(direction: Direction, add: update_add_htlc, val previousChannelId: Option[BinaryData])
final case class CommitmentSpec(htlcs: Set[Htlc], feeRate: Long, initial_amount_us_msat : Long, initial_amount_them_msat: Long, amount_us_msat: Long, amount_them_msat: Long) {
final case class CommitmentSpec(htlcs: Set[Htlc], feeRate: Long, initial_amount_us_msat: Long, initial_amount_them_msat: Long, amount_us_msat: Long, amount_them_msat: Long) {
val totalFunds = amount_us_msat + amount_them_msat + htlcs.toSeq.map(_.add.amountMsat).sum
}
@ -131,25 +174,33 @@ trait HasCommitments {
def commitments: Commitments
}
final case class DATA_OPEN_WAIT_FOR_OPEN (ourParams: OurChannelParams) extends Data
final case class DATA_OPEN_WAIT_FOR_OPEN(ourParams: OurChannelParams) extends Data
final case class DATA_OPEN_WITH_ANCHOR_WAIT_FOR_ANCHOR(ourParams: OurChannelParams, theirParams: TheirChannelParams, theirRevocationHash: BinaryData, theirNextRevocationHash: sha256_hash) extends Data
final case class DATA_OPEN_WAIT_FOR_ANCHOR (ourParams: OurChannelParams, theirParams: TheirChannelParams, theirRevocationHash: sha256_hash, theirNextRevocationHash: sha256_hash) extends Data
final case class DATA_OPEN_WAIT_FOR_COMMIT_SIG (ourParams: OurChannelParams, theirParams: TheirChannelParams, anchorTx: Transaction, anchorOutputIndex: Int, initialCommitment: TheirCommit, theirNextRevocationHash: sha256_hash) extends Data
final case class DATA_OPEN_WAITING (commitments: Commitments, deferred: Option[open_complete]) extends Data with HasCommitments
final case class DATA_NORMAL (commitments: Commitments,
ourClearing: Option[close_clearing],
downstreams: Map[Long, Option[BinaryData]]) extends Data with HasCommitments
final case class DATA_CLEARING (commitments: Commitments,
ourClearing: close_clearing, theirClearing: close_clearing,
downstreams: Map[Long, Option[BinaryData]]) extends Data with HasCommitments
final case class DATA_NEGOTIATING (commitments: Commitments,
ourClearing: close_clearing, theirClearing: close_clearing, ourSignature: close_signature) extends Data with HasCommitments
final case class DATA_CLOSING (commitments: Commitments,
ourSignature: Option[close_signature] = None,
mutualClosePublished: Option[Transaction] = None,
ourCommitPublished: Option[Transaction] = None,
theirCommitPublished: Option[Transaction] = None,
revokedPublished: Seq[Transaction] = Seq()) extends Data with HasCommitments {
final case class DATA_OPEN_WAIT_FOR_ANCHOR(ourParams: OurChannelParams, theirParams: TheirChannelParams, theirRevocationHash: sha256_hash, theirNextRevocationHash: sha256_hash) extends Data
final case class DATA_OPEN_WAIT_FOR_COMMIT_SIG(ourParams: OurChannelParams, theirParams: TheirChannelParams, anchorTx: Transaction, anchorOutputIndex: Int, initialCommitment: TheirCommit, theirNextRevocationHash: sha256_hash) extends Data
final case class DATA_OPEN_WAITING(commitments: Commitments, deferred: Option[open_complete]) extends Data with HasCommitments
final case class DATA_NORMAL(commitments: Commitments,
ourClearing: Option[close_clearing],
downstreams: Map[Long, Option[BinaryData]]) extends Data with HasCommitments
final case class DATA_CLEARING(commitments: Commitments,
ourClearing: close_clearing, theirClearing: close_clearing,
downstreams: Map[Long, Option[BinaryData]]) extends Data with HasCommitments
final case class DATA_NEGOTIATING(commitments: Commitments,
ourClearing: close_clearing, theirClearing: close_clearing, ourSignature: close_signature) extends Data with HasCommitments
final case class DATA_CLOSING(commitments: Commitments,
ourSignature: Option[close_signature] = None,
mutualClosePublished: Option[Transaction] = None,
ourCommitPublished: Option[Transaction] = None,
theirCommitPublished: Option[Transaction] = None,
revokedPublished: Seq[Transaction] = Seq()) extends Data with HasCommitments {
assert(mutualClosePublished.isDefined || ourCommitPublished.isDefined || theirCommitPublished.isDefined || revokedPublished.size > 0, "there should be at least one tx published in this state")
}

View file

@ -2,7 +2,7 @@ package fr.acinq.eclair.channel
import akka.actor._
import akka.util.Timeout
import fr.acinq.bitcoin.{BinaryData, DeterministicWallet}
import fr.acinq.bitcoin.{BinaryData, DeterministicWallet, Satoshi}
import fr.acinq.eclair.io.AuthHandler
import fr.acinq.eclair.Globals
@ -58,7 +58,7 @@ object Register {
def props(blockchain: ActorRef, paymentHandler: ActorRef) = Props(classOf[Register], blockchain, paymentHandler)
// @formatter:off
case class CreateChannel(connection: ActorRef, anchorAmount: Option[Long])
case class CreateChannel(connection: ActorRef, anchorAmount: Option[Satoshi])
case class ListChannels()

View file

@ -1,13 +1,15 @@
package fr.acinq.eclair.gui
import javafx.collections.FXCollections
import javafx.event.{ActionEvent, EventHandler}
import javafx.geometry.{Insets, Pos}
import javafx.scene.{Node, Scene}
import javafx.scene.control.{Button, Label, TextField}
import javafx.scene.input.{KeyCode, KeyEvent}
import javafx.scene.control.{Button, ComboBox, Label, TextField}
import javafx.scene.layout.GridPane
import javafx.scene.{Node, Scene}
import javafx.stage.{Modality, Stage, StageStyle}
import fr.acinq.bitcoin.Satoshi
/**
* Created by PM on 16/08/2016.
*/
@ -15,12 +17,12 @@ class DialogOpen(primaryStage: Stage, handlers: Handlers) extends Stage() {
initModality(Modality.WINDOW_MODAL)
initStyle(StageStyle.UTILITY)
initOwner(primaryStage)
setWidth(300)
setHeight(100)
setWidth(500)
setHeight(300)
// center on parent
setX(primaryStage.getX() + primaryStage.getWidth() / 2 - getWidth() / 2)
setY(primaryStage.getY() + primaryStage.getHeight() / 2 - getHeight() / 2)
setTitle("Open a new channel")
setTitle("Create a new channel")
setResizable(false)
val grid = new GridPane()
@ -35,16 +37,37 @@ class DialogOpen(primaryStage: Stage, handlers: Handlers) extends Stage() {
val textFieldHostPort = new TextField()
grid.add(textFieldHostPort, 1, 0)
val btn = new Button("Connect")
val labelAmount = new Label("Amount (msat)")
grid.add(labelAmount, 0, 1)
val textFieldAmount = new TextField("10")
grid.add(textFieldAmount, 1, 1)
val units = FXCollections.observableArrayList(
"milliBTC",
"Satoshi",
"milliSatoshi"
)
val unitChooser = new ComboBox(units)
unitChooser.setValue(units.get(0))
grid.add(unitChooser, 2, 1)
val btn = new Button("Create channel")
btn.setOnAction(new EventHandler[ActionEvent] {
override def handle(event: ActionEvent): Unit = {
handlers.open(textFieldHostPort.getText)
val raw = textFieldAmount.getText.toLong
val amount = unitChooser.getValue match {
case "milliBTC" => Satoshi(raw * 100000L)
case "Satoshi" => Satoshi(raw)
case "milliSatoshi" => Satoshi(raw / 1000L)
}
handlers.open(textFieldHostPort.getText, amount)
event.getSource.asInstanceOf[Node].getScene.getWindow.hide()
}
})
// click on enter
btn.defaultButtonProperty().bind(btn.focusedProperty())
grid.add(btn, 1, 1)
grid.add(btn, 1, 2)
val scene = new Scene(grid)
setScene(scene)

View file

@ -4,7 +4,7 @@ package fr.acinq.eclair.gui
import javafx.application.Platform
import javafx.scene.control.{TextArea, TextField}
import fr.acinq.bitcoin.BinaryData
import fr.acinq.bitcoin.{BinaryData, Satoshi}
import fr.acinq.eclair.io.Client
import fr.acinq.eclair.router.CreatePayment
import fr.acinq.eclair._
@ -17,12 +17,11 @@ class Handlers(setup: Setup) extends Logging {
import setup._
def open(hostPort: String) = {
def open(hostPort: String, amount: Satoshi) = {
val regex = "([a-zA-Z0-9\\.\\-_]+):([0-9]+)".r
hostPort match {
case regex(host, port) =>
logger.info(s"connecting to $host:$port")
val amount = 1000000L
system.actorOf(Client.props(host, port.toInt, amount, register))
case _ => {}
}

View file

@ -4,12 +4,13 @@ import java.net.InetSocketAddress
import akka.actor._
import akka.io.{IO, Tcp}
import fr.acinq.bitcoin.Satoshi
import fr.acinq.eclair.channel.Register.CreateChannel
/**
* Created by PM on 27/10/2015.
*/
class Client(remote: InetSocketAddress, amount: Long, register: ActorRef) extends Actor with ActorLogging {
* Created by PM on 27/10/2015.
*/
class Client(remote: InetSocketAddress, amount: Satoshi, register: ActorRef) extends Actor with ActorLogging {
import Tcp._
import context.system
@ -23,14 +24,14 @@ class Client(remote: InetSocketAddress, amount: Long, register: ActorRef) extend
log.info(s"connected to $remote")
val connection = sender()
register ! CreateChannel(connection, Some(amount))
// TODO : kill this actor ?
// TODO : kill this actor ?
}
}
object Client extends App {
def props(address: InetSocketAddress, amount: Long, register: ActorRef): Props = Props(classOf[Client], address, register)
def props(address: InetSocketAddress, amount: Satoshi, register: ActorRef): Props = Props(classOf[Client], address, amount, register)
def props(host: String, port: Int, amount: Long, register: ActorRef): Props = Props(classOf[Client], new InetSocketAddress(host, port), amount, register)
def props(host: String, port: Int, amount: Satoshi, register: ActorRef): Props = Props(classOf[Client], new InetSocketAddress(host, port), amount, register)
}

View file

@ -13,10 +13,10 @@ class TestBitcoinClient extends ExtendedBitcoinClient(new BitcoinJsonRPCClient("
client.client.close()
override def makeAnchorTx(ourCommitPub: BinaryData, theirCommitPub: BinaryData, amount: Long)(implicit ec: ExecutionContext): Future[(Transaction, Int)] = {
override def makeAnchorTx(ourCommitPub: BinaryData, theirCommitPub: BinaryData, amount: Satoshi)(implicit ec: ExecutionContext): Future[(Transaction, Int)] = {
val anchorTx = Transaction(version = 1,
txIn = Seq.empty[TxIn],
txOut = TxOut(Satoshi(amount), Scripts.anchorPubkeyScript(ourCommitPub, theirCommitPub)) :: Nil,
txOut = TxOut(amount, Scripts.anchorPubkeyScript(ourCommitPub, theirCommitPub)) :: Nil,
lockTime = 0
)
Future.successful((anchorTx, 0))

View file

@ -19,7 +19,7 @@ object TestConstants {
object Alice {
val (Base58.Prefix.SecretKeyTestnet, commitPrivKey) = Base58Check.decode("cQPmcNr6pwBQPyGfab3SksE9nTCtx9ism9T4dkS9dETNU2KKtJHk")
val (Base58.Prefix.SecretKeyTestnet, finalPrivKey) = Base58Check.decode("cUrAtLtV7GGddqdkhUxnbZVDWGJBTducpPoon3eKp9Vnr1zxs6BG")
val channelParams = OurChannelParams(locktime(Blocks(4)), commitPrivKey, finalPrivKey, 1, 10000, Crypto.sha256("alice-seed".getBytes()), Some(anchorAmount))
val channelParams = OurChannelParams(locktime(Blocks(4)), commitPrivKey, finalPrivKey, 1, 10000, Crypto.sha256("alice-seed".getBytes()), Some(Satoshi(anchorAmount)))
val finalPubKey = channelParams.finalPubKey
def revocationHash(index: Long) = Helpers.revocationHash(channelParams.shaSeed, index)