mirror of
https://github.com/ACINQ/eclair.git
synced 2025-02-23 14:40:34 +01:00
Merge branch 'master' of github.com:ACINQ/eclair
This commit is contained in:
commit
af9524f320
2 changed files with 48 additions and 4 deletions
|
@ -9,6 +9,8 @@ import com.google.protobuf.ByteString
|
||||||
import fr.acinq.bitcoin.Crypto._
|
import fr.acinq.bitcoin.Crypto._
|
||||||
import fr.acinq.bitcoin._
|
import fr.acinq.bitcoin._
|
||||||
|
|
||||||
|
import scala.annotation.tailrec
|
||||||
|
|
||||||
package lightning {
|
package lightning {
|
||||||
|
|
||||||
case class ChannelOneSide(pay: Long, fee: Long, htlcs: Seq[update_add_htlc])
|
case class ChannelOneSide(pay: Long, fee: Long, htlcs: Seq[update_add_htlc])
|
||||||
|
@ -81,10 +83,41 @@ package object lightning {
|
||||||
case locktime(Seconds(seconds)) => seconds
|
case locktime(Seconds(seconds)) => seconds
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def isLess(a: Seq[Byte], b: Seq[Byte]) : Boolean = {
|
||||||
|
val a1 = a.dropWhile(_ == 0)
|
||||||
|
val b1 = b.dropWhile(_ == 0)
|
||||||
|
if (a1.length != b1.length)
|
||||||
|
a1.length <= b1.length
|
||||||
|
else {
|
||||||
|
@tailrec
|
||||||
|
def isLess0(x: List[Byte], y: List[Byte]) : Boolean = (x, y) match {
|
||||||
|
case (Nil, Nil) => false
|
||||||
|
case (hx :: tx, hy :: ty) if (hx == hy) => isLess0(tx, ty)
|
||||||
|
case (hx :: _, hy :: _) => ((hx & 0xff) < (hy & 0xff))
|
||||||
|
}
|
||||||
|
isLess0(a1.toList, b1.toList)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def multiSig2of2(pubkey1: Array[Byte], pubkey2: Array[Byte]) : Array[Byte] = if (isLess(pubkey1, pubkey2))
|
||||||
|
Script.createMultiSigMofN(2, Seq(pubkey1, pubkey2))
|
||||||
|
else
|
||||||
|
Script.createMultiSigMofN(2, Seq(pubkey2, pubkey1))
|
||||||
|
|
||||||
|
|
||||||
|
def sigScript2of2(sig1: Array[Byte], sig2: Array[Byte], pubkey1: Array[Byte], pubkey2: Array[Byte]) = if (isLess(pubkey1, pubkey2))
|
||||||
|
Script.write(OP_0 :: OP_PUSHDATA(sig1) :: OP_PUSHDATA(sig2) :: OP_PUSHDATA(multiSig2of2(pubkey1, pubkey2)) :: Nil)
|
||||||
|
else
|
||||||
|
Script.write(OP_0 :: OP_PUSHDATA(sig2) :: OP_PUSHDATA(sig1) :: OP_PUSHDATA(multiSig2of2(pubkey1, pubkey2)) :: Nil)
|
||||||
|
|
||||||
def pay2sh(script: Seq[ScriptElt]) = OP_HASH160 :: OP_PUSHDATA(hash160(Script.write(script))) :: OP_EQUAL :: Nil
|
def pay2sh(script: Seq[ScriptElt]) = OP_HASH160 :: OP_PUSHDATA(hash160(Script.write(script))) :: OP_EQUAL :: Nil
|
||||||
|
|
||||||
def makeAnchorTx(pubkey1: BinaryData, pubkey2: BinaryData, amount: Long, previousTxOutput: OutPoint, signData: SignData): Transaction = {
|
def makeAnchorTx(pubkey1: BinaryData, pubkey2: BinaryData, amount: Long, previousTxOutput: OutPoint, signData: SignData): Transaction = {
|
||||||
val scriptPubKey = Script.createMultiSigMofN(2, Seq(pubkey1, pubkey2))
|
val scriptPubKey = if (isLess(pubkey1, pubkey2))
|
||||||
|
Script.createMultiSigMofN(2, Seq(pubkey1, pubkey2))
|
||||||
|
else
|
||||||
|
Script.createMultiSigMofN(2, Seq(pubkey2, pubkey1))
|
||||||
|
|
||||||
val tx = Transaction(version = 1,
|
val tx = Transaction(version = 1,
|
||||||
txIn = TxIn(outPoint = previousTxOutput, signatureScript = Array.emptyByteArray, sequence = 0xffffffffL) :: Nil,
|
txIn = TxIn(outPoint = previousTxOutput, signatureScript = Array.emptyByteArray, sequence = 0xffffffffL) :: Nil,
|
||||||
txOut = TxOut(amount, publicKeyScript = OP_HASH160 :: OP_PUSHDATA(hash160(scriptPubKey)) :: OP_EQUAL :: Nil) :: Nil,
|
txOut = TxOut(amount, publicKeyScript = OP_HASH160 :: OP_PUSHDATA(hash160(scriptPubKey)) :: OP_EQUAL :: Nil) :: Nil,
|
||||||
|
|
|
@ -72,14 +72,19 @@ class ProtocolSpec extends FlatSpec {
|
||||||
val openAnchor = open_anchor(anchor.hash, 0, 10, signature.defaultInstance) // commit sig will be computed later
|
val openAnchor = open_anchor(anchor.hash, 0, 10, signature.defaultInstance) // commit sig will be computed later
|
||||||
val channelState = initialFunding(ours, theirs, openAnchor, fee = 0)
|
val channelState = initialFunding(ours, theirs, openAnchor, fee = 0)
|
||||||
val tx = makeCommitTx(ours, theirs, openAnchor, Bob.H, channelState)
|
val tx = makeCommitTx(ours, theirs, openAnchor, Bob.H, channelState)
|
||||||
val sigA = Transaction.signInput(tx, 0, Script.createMultiSigMofN(2, Seq(Alice.commitPubKey, Bob.commitPubKey)), SIGHASH_ALL, Alice.commitKey)
|
val redeemScript = multiSig2of2(Alice.commitPubKey, Bob.commitPubKey)
|
||||||
|
val sigA = Transaction.signInput(tx, 0, redeemScript, SIGHASH_ALL, Alice.commitKey)
|
||||||
val openAnchor1 = openAnchor.copy(commitSig = sigA)
|
val openAnchor1 = openAnchor.copy(commitSig = sigA)
|
||||||
|
|
||||||
// now Bob receives open anchor and wants to check that Alice's commit sig is valid
|
// now Bob receives open anchor and wants to check that Alice's commit sig is valid
|
||||||
val sigB = Transaction.signInput(tx, 0, Script.createMultiSigMofN(2, Seq(Alice.commitPubKey, Bob.commitPubKey)), SIGHASH_ALL, Bob.commitKey)
|
// Bob can sign too and check that he can spend the anchox tx
|
||||||
val scriptSig = Script.write(OP_0 :: OP_PUSHDATA(sigA) :: OP_PUSHDATA(sigB) :: OP_PUSHDATA(Script.createMultiSigMofN(2, Seq(Alice.commitPubKey, Bob.commitPubKey))) :: Nil)
|
val sigB = Transaction.signInput(tx, 0, redeemScript, SIGHASH_ALL, Bob.commitKey)
|
||||||
|
val scriptSig = sigScript2of2(sigA, sigB, Alice.commitPubKey, Bob.commitPubKey)
|
||||||
val commitTx = tx.updateSigScript(0, scriptSig)
|
val commitTx = tx.updateSigScript(0, scriptSig)
|
||||||
Transaction.correctlySpends(commitTx, Seq(anchor), ScriptFlags.STANDARD_SCRIPT_VERIFY_FLAGS)
|
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)
|
||||||
|
assert(Crypto.verifySignature(hash, Crypto.decodeSignature(sigA.dropRight(1)), Alice.commitPubKey))
|
||||||
|
|
||||||
// how do we spend our commit tx ?
|
// how do we spend our commit tx ?
|
||||||
|
|
||||||
|
@ -99,4 +104,10 @@ class ProtocolSpec extends FlatSpec {
|
||||||
|
|
||||||
Transaction.correctlySpends(spendingTx, Seq(commitTx), ScriptFlags.STANDARD_SCRIPT_VERIFY_FLAGS | ScriptFlags.SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY | ScriptFlags.SCRIPT_VERIFY_CHECKSEQUENCEVERIFY)
|
Transaction.correctlySpends(spendingTx, Seq(commitTx), ScriptFlags.STANDARD_SCRIPT_VERIFY_FLAGS | ScriptFlags.SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY | ScriptFlags.SCRIPT_VERIFY_CHECKSEQUENCEVERIFY)
|
||||||
}
|
}
|
||||||
|
it should "sort binary data" in {
|
||||||
|
assert(!isLess(Array.emptyByteArray, Array.emptyByteArray))
|
||||||
|
assert(isLess(fromHexString("aa"), fromHexString("bb")))
|
||||||
|
assert(isLess(fromHexString("aabbcc"), fromHexString("bbbbcc")))
|
||||||
|
assert(isLess(fromHexString("aa"), fromHexString("11aa")))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue