mirror of
https://github.com/ACINQ/eclair.git
synced 2025-02-23 14:40:34 +01:00
Wip bolt2 nakamoto (#9)
* use lightning.proto from lightning-c v0.3-2016-05-26 "Nakamoto's Genesis Coins"
* check that preimage size is 32 bytes (see 1245ffaae3
and
https://lists.linuxfoundation.org/pipermail/lightning-dev/2016-May/000529.html)
This commit is contained in:
parent
0396b5589d
commit
b055df5338
5 changed files with 20 additions and 36 deletions
|
@ -64,18 +64,16 @@ class Channel(val them: ActorRef, val blockchain: ActorRef, val params: OurChann
|
|||
log.info(s"anchor txid=${anchorTx.txid}")
|
||||
val amount = anchorTx.txOut(anchorOutputIndex).amount.toLong
|
||||
val theirSpec = CommitmentSpec(Set.empty[Htlc], feeRate = theirParams.initialFeeRate, initial_amount_us_msat = 0, initial_amount_them_msat = amount * 1000, amount_us_msat = 0, amount_them_msat = amount * 1000)
|
||||
val theirTx = makeTheirTx(ourParams, theirParams, TxIn(OutPoint(anchorTx.hash, anchorOutputIndex), Array.emptyByteArray, 0xffffffffL) :: Nil, theirRevocationHash, theirSpec)
|
||||
val ourSig = sign(ourParams, theirParams, amount, theirTx)
|
||||
them ! open_anchor(anchorTx.hash, anchorOutputIndex, amount, ourSig)
|
||||
them ! open_anchor(anchorTx.hash, anchorOutputIndex, amount)
|
||||
goto(OPEN_WAIT_FOR_COMMIT_SIG) using DATA_OPEN_WAIT_FOR_COMMIT_SIG(ourParams, theirParams, anchorTx, anchorOutputIndex, TheirCommit(0, theirSpec, theirRevocationHash), theirNextRevocationHash)
|
||||
|
||||
case Event(CMD_CLOSE(_), _) => goto(CLOSED)
|
||||
}
|
||||
|
||||
when(OPEN_WAIT_FOR_ANCHOR) {
|
||||
case Event(open_anchor(anchorTxHash, anchorOutputIndex, anchorAmount, theirSig), DATA_OPEN_WAIT_FOR_ANCHOR(ourParams, theirParams, theirRevocationHash, theirNextRevocationHash)) =>
|
||||
case Event(open_anchor(anchorTxHash, anchorOutputIndex, anchorAmount), DATA_OPEN_WAIT_FOR_ANCHOR(ourParams, theirParams, theirRevocationHash, theirNextRevocationHash)) =>
|
||||
val anchorTxid = anchorTxHash.reverse //see https://github.com/ElementsProject/lightning/issues/17
|
||||
val anchorOutput = TxOut(Satoshi(anchorAmount), publicKeyScript = Scripts.anchorPubkeyScript(ourParams.commitPubKey, theirParams.commitPubKey))
|
||||
val anchorOutput = TxOut(Satoshi(anchorAmount), publicKeyScript = Scripts.anchorPubkeyScript(ourParams.commitPubKey, theirParams.commitPubKey))
|
||||
|
||||
// they fund the channel with their anchor tx, so the money is theirs
|
||||
val ourSpec = CommitmentSpec(Set.empty[Htlc], feeRate = ourParams.initialFeeRate, initial_amount_them_msat = anchorAmount * 1000, initial_amount_us_msat = 0, amount_them_msat = anchorAmount * 1000, amount_us_msat = 0)
|
||||
|
@ -84,21 +82,14 @@ class Channel(val them: ActorRef, val blockchain: ActorRef, val params: OurChann
|
|||
// we build our commitment tx, sign it and check that it is spendable using the counterparty's sig
|
||||
val ourRevocationHash = Crypto.sha256(ShaChain.shaChainFromSeed(ourParams.shaSeed, 0))
|
||||
val ourTx = makeOurTx(ourParams, theirParams, TxIn(OutPoint(anchorTxHash, anchorOutputIndex), Array.emptyByteArray, 0xffffffffL) :: Nil, ourRevocationHash, ourSpec)
|
||||
val ourSig = sign(ourParams, theirParams, anchorAmount, ourTx)
|
||||
val signedTx = addSigs(ourParams, theirParams, anchorAmount, ourTx, ourSig, theirSig)
|
||||
checksig(ourParams, theirParams, anchorOutput, signedTx) match {
|
||||
case false =>
|
||||
them ! error(Some("Bad signature"))
|
||||
goto(CLOSED)
|
||||
case true =>
|
||||
val theirTx = makeTheirTx(ourParams, theirParams, TxIn(OutPoint(anchorTxHash, anchorOutputIndex), Array.emptyByteArray, 0xffffffffL) :: Nil, theirRevocationHash, theirSpec)
|
||||
log.info(s"signing their tx: $theirTx")
|
||||
val ourSigForThem = sign(ourParams, theirParams, anchorAmount, theirTx)
|
||||
them ! open_commit_sig(ourSigForThem)
|
||||
blockchain ! WatchConfirmed(self, anchorTxid, ourParams.minDepth, BITCOIN_ANCHOR_DEPTHOK)
|
||||
blockchain ! WatchSpent(self, anchorTxid, anchorOutputIndex, 0, BITCOIN_ANCHOR_SPENT)
|
||||
goto(OPEN_WAITING_THEIRANCHOR) using DATA_OPEN_WAITING(ourParams, theirParams, ShaChain.init, OurCommit(0, ourSpec, signedTx), TheirCommit(0, theirSpec, theirRevocationHash), theirNextRevocationHash, None, anchorOutput)
|
||||
}
|
||||
val theirTx = makeTheirTx(ourParams, theirParams, TxIn(OutPoint(anchorTxHash, anchorOutputIndex), Array.emptyByteArray, 0xffffffffL) :: Nil, theirRevocationHash, theirSpec)
|
||||
log.info(s"signing their tx: $theirTx")
|
||||
val ourSigForThem = sign(ourParams, theirParams, anchorAmount, theirTx)
|
||||
them ! open_commit_sig(ourSigForThem)
|
||||
blockchain ! WatchConfirmed(self, anchorTxid, ourParams.minDepth, BITCOIN_ANCHOR_DEPTHOK)
|
||||
blockchain ! WatchSpent(self, anchorTxid, anchorOutputIndex, 0, BITCOIN_ANCHOR_SPENT)
|
||||
// FIXME: ourTx is not signed by them and cannot be published
|
||||
goto(OPEN_WAITING_THEIRANCHOR) using DATA_OPEN_WAITING(ourParams, theirParams, ShaChain.init, OurCommit(0, ourSpec, ourTx), TheirCommit(0, theirSpec, theirRevocationHash), theirNextRevocationHash, None, anchorOutput)
|
||||
|
||||
case Event(CMD_CLOSE(_), _) => goto(CLOSED)
|
||||
}
|
||||
|
|
|
@ -116,6 +116,7 @@ object Scripts {
|
|||
|
||||
def scriptPubKeyHtlcSend(ourkey: BinaryData, theirkey: BinaryData, abstimeout: Long, reltimeout: Long, rhash: BinaryData, commit_revoke: BinaryData): Seq[ScriptElt] = {
|
||||
// @formatter:off
|
||||
OP_SIZE :: OP_PUSHDATA(Script.encodeNumber(32)) :: OP_EQUALVERIFY ::
|
||||
OP_HASH160 :: OP_DUP ::
|
||||
OP_PUSHDATA(ripemd160(rhash)) :: OP_EQUAL ::
|
||||
OP_SWAP :: OP_PUSHDATA(ripemd160(commit_revoke)) :: OP_EQUAL :: OP_ADD ::
|
||||
|
@ -130,6 +131,7 @@ object Scripts {
|
|||
|
||||
def scriptPubKeyHtlcReceive(ourkey: BinaryData, theirkey: BinaryData, abstimeout: Long, reltimeout: Long, rhash: BinaryData, commit_revoke: BinaryData): Seq[ScriptElt] = {
|
||||
// @formatter:off
|
||||
OP_SIZE :: OP_PUSHDATA(Script.encodeNumber(32)) :: OP_EQUALVERIFY ::
|
||||
OP_HASH160 :: OP_DUP ::
|
||||
OP_PUSHDATA(ripemd160(rhash)) :: OP_EQUAL ::
|
||||
OP_IF ::
|
||||
|
|
|
@ -14,7 +14,7 @@ class ClaimReceivedHtlcSpec extends FunSuite {
|
|||
val (_, finalKey) = Base58Check.decode("cRUfvpbRtMSqCFD1ADdvgPn5HfRLYuHCFYAr2noWnaRDNger2AoA")
|
||||
val commitPubKey = Crypto.publicKeyFromPrivateKey(commitKey)
|
||||
val finalPubKey = Crypto.publicKeyFromPrivateKey(finalKey)
|
||||
val R = "this is Alice's R".getBytes("UTF-8")
|
||||
val R = Crypto.sha256("this is Alice's R".getBytes("UTF-8"))
|
||||
val Rhash = Crypto.sha256(R)
|
||||
val H = Crypto.hash160(R)
|
||||
val revokeCommit = "Alice foo".getBytes("UTF-8")
|
||||
|
@ -26,7 +26,7 @@ class ClaimReceivedHtlcSpec extends FunSuite {
|
|||
val (_, finalKey) = Base58Check.decode("cQLk5fMydgVwJjygt9ta8GcUU4GXLumNiXJCQviibs2LE5vyMXey")
|
||||
val commitPubKey = Crypto.publicKeyFromPrivateKey(commitKey)
|
||||
val finalPubKey = Crypto.publicKeyFromPrivateKey(finalKey)
|
||||
val R: BinaryData = "this is Bob's R".getBytes("UTF-8")
|
||||
val R: BinaryData = Crypto.sha256("this is Bob's R".getBytes("UTF-8"))
|
||||
val Rhash: BinaryData = Crypto.sha256(R)
|
||||
val H: BinaryData = Crypto.hash160(R)
|
||||
val revokeCommit: BinaryData = Crypto.sha256("Alice revocation R".getBytes("UTF-8"))
|
||||
|
|
|
@ -81,24 +81,18 @@ class ProtocolSpec extends FunSuite {
|
|||
initialFeeRate = 1)
|
||||
|
||||
// we assume that Alice knows Bob's H
|
||||
val openAnchor = open_anchor(anchor.hash, anchorOutputIndex, 1000*1000, signature.defaultInstance) // commit sig will be computed later
|
||||
val openAnchor = open_anchor(anchor.hash, anchorOutputIndex, 1000*1000)
|
||||
val spec = CommitmentSpec(Set(), ours.initialFeeRate, 1000 *1000, 0, 1000 *1000, 0)
|
||||
val tx = makeCommitTx(ours.finalKey, theirs.finalKey, theirs.delay, openAnchor.txid, openAnchor.outputIndex, Bob.H, spec)
|
||||
val redeemScript = multiSig2of2(Alice.commitPubKey, Bob.commitPubKey)
|
||||
val sigA: BinaryData = Transaction.signInput(tx, 0, redeemScript, SIGHASH_ALL, anchor.txOut(anchorOutputIndex).amount.toLong, 1, Alice.commitKey)
|
||||
//val sigA: BinaryData = Transaction.signInput(tx, 0, redeemScript, SIGHASH_ALL, Alice.commitKey)
|
||||
val openAnchor1 = openAnchor.copy(commitSig = sigA)
|
||||
|
||||
// now Bob receives open anchor and wants to check that Alice's commit sig is valid
|
||||
// Bob can sign too and check that he can spend the anchox tx
|
||||
// now Bob receives open anchor, creates Alice's commit tx and sends backs its signature.
|
||||
// this first commit tx sends all the funds to Alice and nothing to Bob
|
||||
val sigB: BinaryData = Transaction.signInput(tx, 0, redeemScript, SIGHASH_ALL, anchor.txOut(anchorOutputIndex).amount.toLong, 1, Bob.commitKey)
|
||||
//val sigB = Transaction.signInput(tx, 0, redeemScript, SIGHASH_ALL, Bob.commitKey)
|
||||
val witness = witness2of2(openAnchor1.commitSig, sigB, Alice.commitPubKey, Bob.commitPubKey)
|
||||
val witness = witness2of2(sigA, sigB, Alice.commitPubKey, Bob.commitPubKey)
|
||||
val commitTx = tx.copy(witness = Seq(witness))
|
||||
Transaction.correctlySpends(commitTx, Seq(anchor), ScriptFlags.STANDARD_SCRIPT_VERIFY_FLAGS)
|
||||
// or Bob can just check that Alice's sig is valid
|
||||
val hash = Transaction.hashForSigning(commitTx, 0, redeemScript, SIGHASH_ALL, anchor.txOut(anchorOutputIndex).amount.toLong, signatureVersion = 1)
|
||||
assert(Crypto.verifySignature(hash, Crypto.decodeSignature(sigA.dropRight(1)), Alice.commitPubKey))
|
||||
|
||||
// how do we spend our commit tx ?
|
||||
|
||||
|
|
|
@ -97,9 +97,6 @@ message open_anchor {
|
|||
required uint32 output_index = 2;
|
||||
// Amount of anchor output.
|
||||
required uint64 amount = 3;
|
||||
|
||||
// Signature for your initial commitment tx.
|
||||
required signature commit_sig = 4;
|
||||
}
|
||||
|
||||
// Reply: signature for your initial commitment tx
|
||||
|
@ -153,7 +150,7 @@ message update_fail_htlc {
|
|||
required fail_reason reason = 2;
|
||||
}
|
||||
|
||||
// Commit all the staged HTLCs.
|
||||
// Commit all the staged changes.
|
||||
message update_commit {
|
||||
// Signature for your new commitment tx.
|
||||
required signature sig = 1;
|
||||
|
|
Loading…
Add table
Reference in a new issue