Skip to content

Commit

Permalink
InputInfo refactor step 3: remove version 5 codecs
Browse files Browse the repository at this point in the history
  • Loading branch information
sstone committed Jul 18, 2024
1 parent 146c769 commit 786cfa1
Show file tree
Hide file tree
Showing 5 changed files with 59 additions and 798 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ import fr.acinq.eclair.wire.internal.channel.version1.ChannelCodecs1
import fr.acinq.eclair.wire.internal.channel.version2.ChannelCodecs2
import fr.acinq.eclair.wire.internal.channel.version3.ChannelCodecs3
import fr.acinq.eclair.wire.internal.channel.version4.ChannelCodecs4
import fr.acinq.eclair.wire.internal.channel.version5.ChannelCodecs5
import grizzled.slf4j.Logging
import scodec.Codec
import scodec.codecs.{byte, discriminated}
Expand Down Expand Up @@ -68,8 +67,7 @@ object ChannelCodecs extends Logging {
* More info here: https://github.com/scodec/scodec/issues/122
*/
val channelDataCodec: Codec[PersistentChannelData] = discriminated[PersistentChannelData].by(byte)
.typecase(5, ChannelCodecs5.channelDataCodec)
.typecase(4, ChannelCodecs4.channelDataCodec.decodeOnly)
.typecase(4, ChannelCodecs4.channelDataCodec)
.typecase(3, ChannelCodecs3.channelDataCodec.decodeOnly)
.typecase(2, ChannelCodecs2.channelDataCodec.decodeOnly)
.typecase(1, ChannelCodecs1.channelDataCodec.decodeOnly)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import fr.acinq.bitcoin.ScriptTree
import fr.acinq.bitcoin.crypto.musig2.IndividualNonce
import fr.acinq.bitcoin.scalacompat.Crypto.PublicKey
import fr.acinq.bitcoin.scalacompat.DeterministicWallet.KeyPath
import fr.acinq.bitcoin.scalacompat.{Crypto, OutPoint, ScriptWitness, Transaction, TxOut}
import fr.acinq.bitcoin.scalacompat.{ByteVector64, OutPoint, ScriptWitness, Transaction, TxOut}
import fr.acinq.eclair.blockchain.fee.{ConfirmationPriority, ConfirmationTarget}
import fr.acinq.eclair.channel.LocalFundingStatus._
import fr.acinq.eclair.channel._
Expand Down Expand Up @@ -111,12 +111,27 @@ private[channel] object ChannelCodecs4 {

val txCodec: Codec[Transaction] = lengthDelimited(bytes.xmap(d => Transaction.read(d.toArray), d => Transaction.write(d)))

val dummyScriptTreeCodec: Codec[ScriptTreeAndInternalKey] = provide(ScriptTreeAndInternalKey(new ScriptTree.Leaf(0, java.util.List.of(), 0), Crypto.PrivateKey(ByteVector.fromValidHex("01" * 32)).xOnlyPublicKey()))
val scriptTreeCodec: Codec[ScriptTree] = lengthDelimited(bytes.xmap(d => ScriptTree.read(d.toArray), d => ByteVector.view(d.write())))

val inputInfoCodec: Codec[InputInfo] = (
val scriptTreeAndInternalKey: Codec[ScriptTreeAndInternalKey] = (scriptTreeCodec :: xonlyPublicKey).as[ScriptTreeAndInternalKey]


private case class InputInfoEx(outPoint: OutPoint, txOut: TxOut, redeemScript: ByteVector, redeemScriptOrScriptTree: Either[ByteVector, ScriptTreeAndInternalKey], dummy: Boolean)

// To support the change from redeemScript to "either redeem script or script tree" while remaining backwards-compatible with the previous version 4 codec, we use
// the redeem script itself as a left/write indicator: empty -> right, not empty -> left
private val inputInfoExCodec: Codec[InputInfoEx] = (
("outPoint" | outPointCodec) ::
("txOut" | txOutCodec) ::
("redeemScript" | either[ByteVector, ScriptTreeAndInternalKey](provide(false), lengthDelimited(bytes), dummyScriptTreeCodec))).as[InputInfo]
(("redeemScript" | lengthDelimited(bytes)) >>:~ { redeemScript =>
("redeemScriptOrScriptTree" | either(provide(redeemScript.isEmpty), provide(redeemScript), scriptTreeAndInternalKey)) :: ("dummy" | provide(false))
})
).as[InputInfoEx]

val inputInfoCodec: Codec[InputInfo] = inputInfoExCodec.xmap(
iex => InputInfo(iex.outPoint, iex.txOut, iex.redeemScriptOrScriptTree),
i => InputInfoEx(i.outPoint, i.txOut, i.redeemScriptOrScriptTree.swap.toOption.getOrElse(ByteVector.empty), i.redeemScriptOrScriptTree, false)
)

val outputInfoCodec: Codec[OutputInfo] = (
("index" | uint32) ::
Expand Down Expand Up @@ -187,9 +202,19 @@ private[channel] object ChannelCodecs4 {
("txinfo" | htlcTxCodec) ::
("remoteSig" | bytes64)).as[HtlcTxAndRemoteSig]

val commitTxAndRemoteSigCodec: Codec[CommitTxAndRemoteSig] = (
private case class CommitTxAndRemoteSigEx(commitTx: CommitTx, remoteSig: ByteVector64, partialSig: Either[ByteVector64, PartialSignatureWithNonce], dummy: Boolean)

// remoteSig is now either a signature or a partial signature with nonce. To retain compatibility with the previous codec, we use remoteSig as a left/write indicator,
// a value of all zeroes meaning right (a valid signature cannot be all zeroes)
private val commitTxAndRemoteSigExCodec: Codec[CommitTxAndRemoteSigEx] = (
("commitTx" | commitTxCodec) ::
("remoteSig" | either(provide(false), bytes64, partialSignatureWithNonce))).as[CommitTxAndRemoteSig]
(("remoteSig" | bytes64) >>:~ { remoteSig => either(provide(remoteSig == ByteVector64.Zeroes), provide(remoteSig), partialSignatureWithNonce) :: ("dummy" | provide(false)) })
).as[CommitTxAndRemoteSigEx]

val commitTxAndRemoteSigCodec: Codec[CommitTxAndRemoteSig] = commitTxAndRemoteSigExCodec.xmap(
ce => CommitTxAndRemoteSig(ce.commitTx, ce.partialSig),
c => CommitTxAndRemoteSigEx(c.commitTx, c.remoteSig.swap.toOption.getOrElse(fr.acinq.bitcoin.scalacompat.ByteVector64.Zeroes), c.remoteSig, false)
)

val updateMessageCodec: Codec[UpdateMessage] = lengthDelimited(lightningMessageCodec.narrow[UpdateMessage](f => Attempt.successful(f.asInstanceOf[UpdateMessage]), g => g))

Expand Down Expand Up @@ -252,8 +277,15 @@ private[channel] object ChannelCodecs4 {
("fundingTxIndex" | uint32) ::
("remoteFundingPubkey" | publicKey)).as[InteractiveTxBuilder.Multisig2of2Input]

private val musig2of2InputCodec: Codec[InteractiveTxBuilder.Musig2Input] = (
("info" | inputInfoCodec) ::
("fundingTxIndex" | uint32) ::
("remoteFundingPubkey" | publicKey) ::
("commitIndex" | uint32)).as[InteractiveTxBuilder.Musig2Input]

private val sharedFundingInputCodec: Codec[InteractiveTxBuilder.SharedFundingInput] = discriminated[InteractiveTxBuilder.SharedFundingInput].by(uint16)
.typecase(0x01, multisig2of2InputCodec)
.typecase(0x02, musig2of2InputCodec)

private val requireConfirmedInputsCodec: Codec[InteractiveTxBuilder.RequireConfirmedInputs] = (("forLocal" | bool8) :: ("forRemote" | bool8)).as[InteractiveTxBuilder.RequireConfirmedInputs]

Expand Down Expand Up @@ -638,6 +670,15 @@ private[channel] object ChannelCodecs4 {
val DATA_WAIT_FOR_CHANNEL_READY_0b_Codec: Codec[DATA_WAIT_FOR_CHANNEL_READY] = (
("commitments" | versionedCommitmentsCodec) ::
("shortIds" | shortids)).as[DATA_WAIT_FOR_CHANNEL_READY]

val DATA_WAIT_FOR_DUAL_FUNDING_SIGNED_13_Codec: Codec[DATA_WAIT_FOR_DUAL_FUNDING_SIGNED] = (
("channelParams" | paramsCodec) ::
("secondRemotePerCommitmentPoint" | publicKey) ::
("localPushAmount" | millisatoshi) ::
("remotePushAmount" | millisatoshi) ::
("status" | interactiveTxWaitingForSigsCodec) ::
("remoteChannelData_opt" | optional(bool8, varsizebinarydata)) ::
("secondRemoteNonce_opt" | optional(bool8, publicNonce))).as[DATA_WAIT_FOR_DUAL_FUNDING_SIGNED]

val DATA_WAIT_FOR_DUAL_FUNDING_SIGNED_09_Codec: Codec[DATA_WAIT_FOR_DUAL_FUNDING_SIGNED] = (
("channelParams" | paramsCodec) ::
Expand Down Expand Up @@ -755,6 +796,7 @@ private[channel] object ChannelCodecs4 {

// Order matters!
val channelDataCodec: Codec[PersistentChannelData] = discriminated[PersistentChannelData].by(uint16)
.typecase(0x13, Codecs.DATA_WAIT_FOR_DUAL_FUNDING_SIGNED_13_Codec)
.typecase(0x12, Codecs.DATA_WAIT_FOR_REMOTE_PUBLISH_FUTURE_COMMITMENT_12_Codec)
.typecase(0x11, Codecs.DATA_CLOSING_11_Codec)
.typecase(0x10, Codecs.DATA_NEGOTIATING_10_Codec)
Expand Down
Loading

0 comments on commit 786cfa1

Please sign in to comment.