From 9aee109b160c48cb2060ac9bdb0f896768802330 Mon Sep 17 00:00:00 2001 From: t-bast Date: Thu, 7 Apr 2022 13:45:14 +0200 Subject: [PATCH 1/6] Move ASCII art comment --- .../fr/acinq/eclair/channel/fsm/Channel.scala | 24 ------------------- .../channel/fsm/ChannelOpenSingleFunder.scala | 24 +++++++++++++++++++ 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/channel/fsm/Channel.scala b/eclair-core/src/main/scala/fr/acinq/eclair/channel/fsm/Channel.scala index 5852e4d086..3a019951ea 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/channel/fsm/Channel.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/channel/fsm/Channel.scala @@ -205,30 +205,6 @@ class Channel(val nodeParams: NodeParams, val wallet: OnChainChannelFunder, val 8888888 888 Y888 8888888 888 */ - /* - NEW - FUNDER FUNDEE - | | - | open_channel |WAIT_FOR_OPEN_CHANNEL - |------------------------------->| - WAIT_FOR_ACCEPT_CHANNEL| | - | accept_channel | - |<-------------------------------| - | |WAIT_FOR_FUNDING_CREATED - | funding_created | - |------------------------------->| - WAIT_FOR_FUNDING_SIGNED| | - | funding_signed | - |<-------------------------------| - WAIT_FOR_FUNDING_LOCKED| |WAIT_FOR_FUNDING_LOCKED - | funding_locked funding_locked | - |--------------- ---------------| - | \/ | - | /\ | - |<-------------- -------------->| - NORMAL| |NORMAL - */ - startWith(WAIT_FOR_INIT_INTERNAL, Nothing) when(WAIT_FOR_INIT_INTERNAL)(handleExceptions { diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/channel/fsm/ChannelOpenSingleFunder.scala b/eclair-core/src/main/scala/fr/acinq/eclair/channel/fsm/ChannelOpenSingleFunder.scala index 12cc7a27e9..0f974a150e 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/channel/fsm/ChannelOpenSingleFunder.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/channel/fsm/ChannelOpenSingleFunder.scala @@ -49,6 +49,30 @@ trait ChannelOpenSingleFunder extends FundingHandlers with ErrorHandlers { this: Channel => + /* + NEW + FUNDER FUNDEE + | | + | open_channel |WAIT_FOR_OPEN_CHANNEL + |------------------------------->| + WAIT_FOR_ACCEPT_CHANNEL| | + | accept_channel | + |<-------------------------------| + | |WAIT_FOR_FUNDING_CREATED + | funding_created | + |------------------------------->| + WAIT_FOR_FUNDING_SIGNED| | + | funding_signed | + |<-------------------------------| + WAIT_FOR_FUNDING_LOCKED| |WAIT_FOR_FUNDING_LOCKED + | funding_locked funding_locked | + |--------------- ---------------| + | \/ | + | /\ | + |<-------------- -------------->| + NORMAL| |NORMAL + */ + when(WAIT_FOR_OPEN_CHANNEL)(handleExceptions { case Event(open: OpenChannel, d@DATA_WAIT_FOR_OPEN_CHANNEL(INPUT_INIT_FUNDEE(_, localParams, _, remoteInit, channelConfig, channelType))) => Helpers.validateParamsFundee(nodeParams, channelType, localParams.initFeatures, open, remoteNodeId, remoteInit.features) match { From fe347be48d1122f68cc51d7947fecaad151ae9a2 Mon Sep 17 00:00:00 2001 From: t-bast Date: Thu, 7 Apr 2022 14:17:11 +0200 Subject: [PATCH 2/6] Rename HasCommitments * Also introduce a TransientChannelData trait, which lets us have complete pattern matching in a few places. * Remove channel data from the ChannelErrorOccured event. * Rename channel data codec. --- .../acinq/eclair/balance/BalanceActor.scala | 4 +- .../eclair/balance/ChannelsListener.scala | 8 +-- .../acinq/eclair/balance/CheckBalance.scala | 4 +- .../fr/acinq/eclair/channel/ChannelData.scala | 54 ++++++++-------- .../acinq/eclair/channel/ChannelEvents.scala | 6 +- .../fr/acinq/eclair/channel/Helpers.scala | 10 +-- .../fr/acinq/eclair/channel/fsm/Channel.scala | 61 ++++++++++--------- .../eclair/channel/fsm/CommonHandlers.scala | 4 +- .../eclair/channel/fsm/ErrorHandlers.scala | 26 ++++---- .../eclair/channel/fsm/FundingHandlers.scala | 8 +-- .../scala/fr/acinq/eclair/db/ChannelsDb.scala | 8 +-- .../fr/acinq/eclair/db/DualDatabases.scala | 11 ++-- .../db/migration/CompareChannelsDb.scala | 14 ++--- .../db/migration/MigrateChannelsDb.scala | 4 +- .../fr/acinq/eclair/db/pg/PgChannelsDb.scala | 28 ++++----- .../eclair/db/sqlite/SqliteChannelsDb.scala | 30 ++++----- .../main/scala/fr/acinq/eclair/io/Peer.scala | 2 +- .../fr/acinq/eclair/io/Switchboard.scala | 2 +- .../relay/PostRestartHtlcCleaner.scala | 6 +- .../wire/internal/channel/ChannelCodecs.scala | 12 ++-- .../channel/version0/ChannelCodecs0.scala | 2 +- .../channel/version1/ChannelCodecs1.scala | 2 +- .../channel/version2/ChannelCodecs2.scala | 2 +- .../channel/version3/ChannelCodecs3.scala | 2 +- .../scala/fr/acinq/eclair/TestDatabases.scala | 10 +-- .../eclair/balance/CheckBalanceSpec.scala | 4 +- .../fr/acinq/eclair/channel/RestoreSpec.scala | 2 +- .../ChannelStateTestsHelperMethods.scala | 30 ++++----- .../channel/states/e/NormalStateSpec.scala | 6 +- .../channel/states/e/OfflineStateSpec.scala | 6 +- .../states/g/NegotiatingStateSpec.scala | 8 +-- .../channel/states/h/ClosingStateSpec.scala | 2 +- .../fr/acinq/eclair/db/AuditDbSpec.scala | 12 ++-- .../fr/acinq/eclair/db/ChannelsDbSpec.scala | 4 +- .../integration/ChannelIntegrationSpec.scala | 2 +- .../scala/fr/acinq/eclair/io/PeerSpec.scala | 2 +- .../eclair/json/JsonSerializersSpec.scala | 10 +-- .../internal/channel/ChannelCodecsSpec.scala | 42 ++++++------- .../channel/version2/ChannelCodecs2Spec.scala | 14 ++--- .../channel/version3/ChannelCodecs3Spec.scala | 14 ++--- 40 files changed, 240 insertions(+), 238 deletions(-) diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/balance/BalanceActor.scala b/eclair-core/src/main/scala/fr/acinq/eclair/balance/BalanceActor.scala index 49b60e0da2..966ae3024d 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/balance/BalanceActor.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/balance/BalanceActor.scala @@ -11,7 +11,7 @@ import fr.acinq.eclair.balance.CheckBalance.GlobalBalance import fr.acinq.eclair.balance.Monitoring.{Metrics, Tags} import fr.acinq.eclair.blockchain.bitcoind.rpc.BitcoinCoreClient import fr.acinq.eclair.blockchain.bitcoind.rpc.BitcoinCoreClient.Utxo -import fr.acinq.eclair.channel.HasCommitments +import fr.acinq.eclair.channel.PersistentChannelData import fr.acinq.eclair.db.Databases import grizzled.slf4j.Logger import org.json4s.JsonAST.JInt @@ -25,7 +25,7 @@ object BalanceActor { // @formatter:off sealed trait Command private final case object TickBalance extends Command - final case class GetGlobalBalance(replyTo: ActorRef[Try[GlobalBalance]], channels: Map[ByteVector32, HasCommitments]) extends Command + final case class GetGlobalBalance(replyTo: ActorRef[Try[GlobalBalance]], channels: Map[ByteVector32, PersistentChannelData]) extends Command private final case class WrappedChannels(wrapped: ChannelsListener.GetChannelsResponse) extends Command private final case class WrappedGlobalBalanceWithChannels(wrapped: Try[GlobalBalance], channelsCount: Int) extends Command private final case class WrappedUtxoInfo(wrapped: Try[UtxoInfo]) extends Command diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/balance/ChannelsListener.scala b/eclair-core/src/main/scala/fr/acinq/eclair/balance/ChannelsListener.scala index 4051781fb2..64a41c3724 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/balance/ChannelsListener.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/balance/ChannelsListener.scala @@ -9,7 +9,7 @@ import akka.actor.typed.scaladsl.{ActorContext, Behaviors} import fr.acinq.bitcoin.scalacompat.ByteVector32 import fr.acinq.eclair.balance.ChannelsListener._ import fr.acinq.eclair.channel.Helpers.Closing -import fr.acinq.eclair.channel.{ChannelPersisted, ChannelRestored, HasCommitments} +import fr.acinq.eclair.channel.{ChannelPersisted, ChannelRestored, PersistentChannelData} import scala.concurrent.Promise import scala.concurrent.duration.DurationInt @@ -18,14 +18,14 @@ object ChannelsListener { // @formatter:off sealed trait Command - private final case class ChannelData(channelId: ByteVector32, channel: akka.actor.ActorRef, data: HasCommitments) extends Command + private final case class ChannelData(channelId: ByteVector32, channel: akka.actor.ActorRef, data: PersistentChannelData) extends Command private final case class ChannelDied(channelId: ByteVector32) extends Command final case class GetChannels(replyTo: typed.ActorRef[GetChannelsResponse]) extends Command final case object SendDummyEvent extends Command final case object DummyEvent extends Command // @formatter:on - case class GetChannelsResponse(channels: Map[ByteVector32, HasCommitments]) + case class GetChannelsResponse(channels: Map[ByteVector32, PersistentChannelData]) def apply(ready: Promise[Done]): Behavior[Command] = Behaviors.setup { context => @@ -55,7 +55,7 @@ private class ChannelsListener(context: ActorContext[Command]) { private val log = context.log - def running(channels: Map[ByteVector32, HasCommitments]): Behavior[Command] = + def running(channels: Map[ByteVector32, PersistentChannelData]): Behavior[Command] = Behaviors.receiveMessage { case ChannelData(channelId, channel, data) => Closing.isClosed(data, additionalConfirmedTx_opt = None) match { diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/balance/CheckBalance.scala b/eclair-core/src/main/scala/fr/acinq/eclair/balance/CheckBalance.scala index 0a5269d78b..8dd65b359c 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/balance/CheckBalance.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/balance/CheckBalance.scala @@ -197,7 +197,7 @@ object CheckBalance { * - In the other cases, we simply take our local amount * - TODO?: we disregard anchor outputs */ - def computeOffChainBalance(channels: Iterable[HasCommitments], knownPreimages: Set[(ByteVector32, Long)]): OffChainBalance = { + def computeOffChainBalance(channels: Iterable[PersistentChannelData], knownPreimages: Set[(ByteVector32, Long)]): OffChainBalance = { channels .foldLeft(OffChainBalance()) { case (r, d: DATA_WAIT_FOR_FUNDING_CONFIRMED) => r.modify(_.waitForFundingConfirmed).using(updateMainBalance(d.commitments.localCommit)) @@ -293,7 +293,7 @@ object CheckBalance { val total: Btc = onChain.total + offChain.total } - def computeGlobalBalance(channels: Map[ByteVector32, HasCommitments], db: Databases, bitcoinClient: BitcoinCoreClient)(implicit ec: ExecutionContext): Future[GlobalBalance] = for { + def computeGlobalBalance(channels: Map[ByteVector32, PersistentChannelData], db: Databases, bitcoinClient: BitcoinCoreClient)(implicit ec: ExecutionContext): Future[GlobalBalance] = for { onChain <- CheckBalance.computeOnChainBalance(bitcoinClient) knownPreimages = db.pendingCommands.listSettlementCommands().collect { case (channelId, cmd: CMD_FULFILL_HTLC) => (channelId, cmd.id) }.toSet offChainRaw = CheckBalance.computeOffChainBalance(channels.values, knownPreimages) diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/channel/ChannelData.scala b/eclair-core/src/main/scala/fr/acinq/eclair/channel/ChannelData.scala index ca4f6f3b03..380db8a67b 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/channel/ChannelData.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/channel/ChannelData.scala @@ -96,7 +96,7 @@ case class INPUT_INIT_FUNDEE(temporaryChannelId: ByteVector32, case object INPUT_CLOSE_COMPLETE_TIMEOUT // when requesting a mutual close, we wait for as much as this timeout, then unilateral close case object INPUT_DISCONNECTED case class INPUT_RECONNECTED(remote: ActorRef, localInit: Init, remoteInit: Init) -case class INPUT_RESTORED(data: HasCommitments) +case class INPUT_RESTORED(data: PersistentChannelData) /* .d8888b. .d88888b. 888b d888 888b d888 d8888 888b 888 8888888b. .d8888b. @@ -252,19 +252,6 @@ object ChannelOpenResponse { 8888888P" d88P 888 888 d88P 888 */ -sealed trait ChannelData extends PossiblyHarmful { - def channelId: ByteVector32 -} - -case object Nothing extends ChannelData { - val channelId: ByteVector32 = ByteVector32.Zeroes -} - -sealed trait HasCommitments extends ChannelData { - val channelId: ByteVector32 = commitments.channelId - def commitments: Commitments -} - case class ClosingTxProposed(unsignedTx: ClosingTx, localClosingSigned: ClosingSigned) sealed trait CommitPublished { @@ -375,10 +362,25 @@ case class RevokedCommitPublished(commitTx: Transaction, claimMainOutputTx: Opti } } -final case class DATA_WAIT_FOR_OPEN_CHANNEL(initFundee: INPUT_INIT_FUNDEE) extends ChannelData { +sealed trait ChannelData extends PossiblyHarmful { + def channelId: ByteVector32 +} + +sealed trait TransientChannelData extends ChannelData + +case object Nothing extends TransientChannelData { + val channelId: ByteVector32 = ByteVector32.Zeroes +} + +sealed trait PersistentChannelData extends ChannelData { + val channelId: ByteVector32 = commitments.channelId + def commitments: Commitments +} + +final case class DATA_WAIT_FOR_OPEN_CHANNEL(initFundee: INPUT_INIT_FUNDEE) extends TransientChannelData { val channelId: ByteVector32 = initFundee.temporaryChannelId } -final case class DATA_WAIT_FOR_ACCEPT_CHANNEL(initFunder: INPUT_INIT_FUNDER, lastSent: OpenChannel) extends ChannelData { +final case class DATA_WAIT_FOR_ACCEPT_CHANNEL(initFunder: INPUT_INIT_FUNDER, lastSent: OpenChannel) extends TransientChannelData { val channelId: ByteVector32 = initFunder.temporaryChannelId } final case class DATA_WAIT_FOR_FUNDING_INTERNAL(temporaryChannelId: ByteVector32, @@ -390,7 +392,7 @@ final case class DATA_WAIT_FOR_FUNDING_INTERNAL(temporaryChannelId: ByteVector32 remoteFirstPerCommitmentPoint: PublicKey, channelConfig: ChannelConfig, channelFeatures: ChannelFeatures, - lastSent: OpenChannel) extends ChannelData { + lastSent: OpenChannel) extends TransientChannelData { val channelId: ByteVector32 = temporaryChannelId } final case class DATA_WAIT_FOR_FUNDING_CREATED(temporaryChannelId: ByteVector32, @@ -403,7 +405,7 @@ final case class DATA_WAIT_FOR_FUNDING_CREATED(temporaryChannelId: ByteVector32, channelFlags: ChannelFlags, channelConfig: ChannelConfig, channelFeatures: ChannelFeatures, - lastSent: AcceptChannel) extends ChannelData { + lastSent: AcceptChannel) extends TransientChannelData { val channelId: ByteVector32 = temporaryChannelId } final case class DATA_WAIT_FOR_FUNDING_SIGNED(channelId: ByteVector32, @@ -417,13 +419,13 @@ final case class DATA_WAIT_FOR_FUNDING_SIGNED(channelId: ByteVector32, channelFlags: ChannelFlags, channelConfig: ChannelConfig, channelFeatures: ChannelFeatures, - lastSent: FundingCreated) extends ChannelData + lastSent: FundingCreated) extends TransientChannelData final case class DATA_WAIT_FOR_FUNDING_CONFIRMED(commitments: Commitments, fundingTx: Option[Transaction], waitingSince: BlockHeight, // how long have we been waiting for the funding tx to confirm deferred: Option[FundingLocked], - lastSent: Either[FundingCreated, FundingSigned]) extends ChannelData with HasCommitments -final case class DATA_WAIT_FOR_FUNDING_LOCKED(commitments: Commitments, shortChannelId: ShortChannelId, lastSent: FundingLocked) extends ChannelData with HasCommitments + lastSent: Either[FundingCreated, FundingSigned]) extends PersistentChannelData +final case class DATA_WAIT_FOR_FUNDING_LOCKED(commitments: Commitments, shortChannelId: ShortChannelId, lastSent: FundingLocked) extends PersistentChannelData final case class DATA_NORMAL(commitments: Commitments, shortChannelId: ShortChannelId, buried: Boolean, @@ -431,12 +433,12 @@ final case class DATA_NORMAL(commitments: Commitments, channelUpdate: ChannelUpdate, localShutdown: Option[Shutdown], remoteShutdown: Option[Shutdown], - closingFeerates: Option[ClosingFeerates]) extends ChannelData with HasCommitments -final case class DATA_SHUTDOWN(commitments: Commitments, localShutdown: Shutdown, remoteShutdown: Shutdown, closingFeerates: Option[ClosingFeerates]) extends ChannelData with HasCommitments + closingFeerates: Option[ClosingFeerates]) extends PersistentChannelData +final case class DATA_SHUTDOWN(commitments: Commitments, localShutdown: Shutdown, remoteShutdown: Shutdown, closingFeerates: Option[ClosingFeerates]) extends PersistentChannelData final case class DATA_NEGOTIATING(commitments: Commitments, localShutdown: Shutdown, remoteShutdown: Shutdown, closingTxProposed: List[List[ClosingTxProposed]], // one list for every negotiation (there can be several in case of disconnection) - bestUnpublishedClosingTx_opt: Option[ClosingTx]) extends ChannelData with HasCommitments { + bestUnpublishedClosingTx_opt: Option[ClosingTx]) extends PersistentChannelData { require(closingTxProposed.nonEmpty, "there must always be a list for the current negotiation") require(!commitments.localParams.isFunder || closingTxProposed.forall(_.nonEmpty), "funder must have at least one closing signature for every negotiation attempt because it initiates the closing") } @@ -449,12 +451,12 @@ final case class DATA_CLOSING(commitments: Commitments, remoteCommitPublished: Option[RemoteCommitPublished] = None, nextRemoteCommitPublished: Option[RemoteCommitPublished] = None, futureRemoteCommitPublished: Option[RemoteCommitPublished] = None, - revokedCommitPublished: List[RevokedCommitPublished] = Nil) extends ChannelData with HasCommitments { + revokedCommitPublished: List[RevokedCommitPublished] = Nil) extends PersistentChannelData { val spendingTxs: List[Transaction] = mutualClosePublished.map(_.tx) ::: localCommitPublished.map(_.commitTx).toList ::: remoteCommitPublished.map(_.commitTx).toList ::: nextRemoteCommitPublished.map(_.commitTx).toList ::: futureRemoteCommitPublished.map(_.commitTx).toList ::: revokedCommitPublished.map(_.commitTx) require(spendingTxs.nonEmpty, "there must be at least one tx published in this state") } -final case class DATA_WAIT_FOR_REMOTE_PUBLISH_FUTURE_COMMITMENT(commitments: Commitments, remoteChannelReestablish: ChannelReestablish) extends ChannelData with HasCommitments +final case class DATA_WAIT_FOR_REMOTE_PUBLISH_FUTURE_COMMITMENT(commitments: Commitments, remoteChannelReestablish: ChannelReestablish) extends PersistentChannelData /** * @param initFeatures current connection features, or last features used if the channel is disconnected. Note that these diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/channel/ChannelEvents.scala b/eclair-core/src/main/scala/fr/acinq/eclair/channel/ChannelEvents.scala index f49958df04..1e5f71afea 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/channel/ChannelEvents.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/channel/ChannelEvents.scala @@ -40,7 +40,7 @@ trait AbstractChannelRestored extends ChannelEvent { val remoteNodeId: PublicKey } -case class ChannelRestored(channel: ActorRef, channelId: ByteVector32, peer: ActorRef, remoteNodeId: PublicKey, data: HasCommitments) extends AbstractChannelRestored +case class ChannelRestored(channel: ActorRef, channelId: ByteVector32, peer: ActorRef, remoteNodeId: PublicKey, data: PersistentChannelData) extends AbstractChannelRestored case class ChannelIdAssigned(channel: ActorRef, remoteNodeId: PublicKey, temporaryChannelId: ByteVector32, channelId: ByteVector32) extends ChannelEvent @@ -58,7 +58,7 @@ case class ChannelSignatureSent(channel: ActorRef, commitments: Commitments) ext case class ChannelSignatureReceived(channel: ActorRef, commitments: Commitments) extends ChannelEvent -case class ChannelErrorOccurred(channel: ActorRef, channelId: ByteVector32, remoteNodeId: PublicKey, data: ChannelData, error: ChannelOpenError, isFatal: Boolean) extends ChannelEvent +case class ChannelErrorOccurred(channel: ActorRef, channelId: ByteVector32, remoteNodeId: PublicKey, error: ChannelOpenError, isFatal: Boolean) extends ChannelEvent // NB: the fee should be set to 0 when we're not paying it. case class TransactionPublished(channelId: ByteVector32, remoteNodeId: PublicKey, tx: Transaction, miningFee: Satoshi, desc: String) extends ChannelEvent @@ -68,7 +68,7 @@ case class TransactionConfirmed(channelId: ByteVector32, remoteNodeId: PublicKey // NB: this event is only sent when the channel is available. case class AvailableBalanceChanged(channel: ActorRef, channelId: ByteVector32, shortChannelId: ShortChannelId, commitments: AbstractCommitments) extends ChannelEvent -case class ChannelPersisted(channel: ActorRef, remoteNodeId: PublicKey, channelId: ByteVector32, data: HasCommitments) extends ChannelEvent +case class ChannelPersisted(channel: ActorRef, remoteNodeId: PublicKey, channelId: ByteVector32, data: PersistentChannelData) extends ChannelEvent case class LocalCommitConfirmed(channel: ActorRef, remoteNodeId: PublicKey, channelId: ByteVector32, refundAtBlock: BlockHeight) extends ChannelEvent diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/channel/Helpers.scala b/eclair-core/src/main/scala/fr/acinq/eclair/channel/Helpers.scala index f31e24743d..3ff8c60375 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/channel/Helpers.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/channel/Helpers.scala @@ -50,7 +50,7 @@ object Helpers { /** * We update local/global features at reconnection */ - def updateFeatures(data: HasCommitments, localInit: Init, remoteInit: Init): HasCommitments = { + def updateFeatures(data: PersistentChannelData, localInit: Init, remoteInit: Init): PersistentChannelData = { val commitments1 = data.commitments.copy( localParams = data.commitments.localParams.copy(initFeatures = localInit.features), remoteParams = data.commitments.remoteParams.copy(initFeatures = remoteInit.features)) @@ -335,7 +335,7 @@ object Helpers { /** * Check whether we are in sync with our peer. */ - def checkSync(keyManager: ChannelKeyManager, d: HasCommitments, remoteChannelReestablish: ChannelReestablish): SyncResult = { + def checkSync(keyManager: ChannelKeyManager, d: PersistentChannelData, remoteChannelReestablish: ChannelReestablish): SyncResult = { // This is done in two steps: // - step 1: we check our local commitment @@ -343,7 +343,7 @@ object Helpers { // step 2 depends on step 1 because we need to preserve ordering between commit_sig and revocation // step 2: we check the remote commitment - def checkRemoteCommit(d: HasCommitments, remoteChannelReestablish: ChannelReestablish, retransmitRevocation_opt: Option[RevokeAndAck]): SyncResult = { + def checkRemoteCommit(d: PersistentChannelData, remoteChannelReestablish: ChannelReestablish, retransmitRevocation_opt: Option[RevokeAndAck]): SyncResult = { d.commitments.remoteNextCommitInfo match { case Left(waitingForRevocation) if remoteChannelReestablish.nextLocalCommitmentNumber == waitingForRevocation.nextRemoteCommit.index => // we just sent a new commit_sig but they didn't receive it @@ -441,7 +441,7 @@ object Helpers { * * @return true if channel was never open, or got closed immediately, had never any htlcs and local never had a positive balance */ - def nothingAtStake(data: HasCommitments): Boolean = + def nothingAtStake(data: PersistentChannelData): Boolean = data.commitments.localCommit.index == 0 && data.commitments.localCommit.spec.toLocal == 0.msat && data.commitments.remoteCommit.index == 0 && @@ -483,7 +483,7 @@ object Helpers { * because we don't store the closing tx in the channel state * @return the channel closing type, if applicable */ - def isClosed(data: HasCommitments, additionalConfirmedTx_opt: Option[Transaction]): Option[ClosingType] = data match { + def isClosed(data: PersistentChannelData, additionalConfirmedTx_opt: Option[Transaction]): Option[ClosingType] = data match { case closing: DATA_CLOSING if additionalConfirmedTx_opt.exists(closing.mutualClosePublished.map(_.tx).contains) => val closingTx = closing.mutualClosePublished.find(_.tx.txid == additionalConfirmedTx_opt.get.txid).get Some(MutualClose(closingTx)) diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/channel/fsm/Channel.scala b/eclair-core/src/main/scala/fr/acinq/eclair/channel/fsm/Channel.scala index 3a019951ea..0d930e556a 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/channel/fsm/Channel.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/channel/fsm/Channel.scala @@ -1230,10 +1230,10 @@ class Channel(val nodeParams: NodeParams, val wallet: OnChainChannelFunder, val when(CLOSED)(handleExceptions { case Event(Symbol("shutdown"), _) => stateData match { - case d: HasCommitments => + case d: PersistentChannelData => log.info(s"deleting database record for channelId=${d.channelId}") nodeParams.db.channels.removeChannel(d.channelId) - case _ => + case _: TransientChannelData => // nothing was stored in the DB } log.info("shutting down") stop(FSM.Normal) @@ -1257,7 +1257,7 @@ class Channel(val nodeParams: NodeParams, val wallet: OnChainChannelFunder, val val d1 = Helpers.updateFeatures(d, localInit, remoteInit) goto(WAIT_FOR_REMOTE_PUBLISH_FUTURE_COMMITMENT) using d1 sending error - case Event(INPUT_RECONNECTED(r, localInit, remoteInit), d: HasCommitments) => + case Event(INPUT_RECONNECTED(r, localInit, remoteInit), d: PersistentChannelData) => activeConnection = r val yourLastPerCommitmentSecret = d.commitments.remotePerCommitmentSecrets.lastIndex.flatMap(d.commitments.remotePerCommitmentSecrets.getHash).getOrElse(ByteVector32.Zeroes) @@ -1280,9 +1280,9 @@ class Channel(val nodeParams: NodeParams, val wallet: OnChainChannelFunder, val // note: this can only happen if state is NORMAL or SHUTDOWN // -> in NEGOTIATING there are no more htlcs // -> in CLOSING we either have mutual closed (so no more htlcs), or already have unilaterally closed (so no action required), and we can't be in OFFLINE state anyway - case Event(ProcessCurrentBlockHeight(c), d: HasCommitments) => handleNewBlock(c, d) + case Event(ProcessCurrentBlockHeight(c), d: PersistentChannelData) => handleNewBlock(c, d) - case Event(c: CurrentFeerates, d: HasCommitments) => handleCurrentFeerateDisconnected(c, d) + case Event(c: CurrentFeerates, d: PersistentChannelData) => handleCurrentFeerateDisconnected(c, d) case Event(c: CMD_ADD_HTLC, d: DATA_NORMAL) => handleAddDisconnected(c, d) @@ -1302,13 +1302,13 @@ class Channel(val nodeParams: NodeParams, val wallet: OnChainChannelFunder, val case Event(WatchFundingSpentTriggered(tx), d: DATA_NEGOTIATING) if d.closingTxProposed.flatten.exists(_.unsignedTx.tx.txid == tx.txid) => handleMutualClose(getMutualClosePublished(tx, d.closingTxProposed), Left(d)) - case Event(WatchFundingSpentTriggered(tx), d: HasCommitments) if tx.txid == d.commitments.remoteCommit.txid => handleRemoteSpentCurrent(tx, d) + case Event(WatchFundingSpentTriggered(tx), d: PersistentChannelData) if tx.txid == d.commitments.remoteCommit.txid => handleRemoteSpentCurrent(tx, d) - case Event(WatchFundingSpentTriggered(tx), d: HasCommitments) if d.commitments.remoteNextCommitInfo.left.toOption.exists(_.nextRemoteCommit.txid == tx.txid) => handleRemoteSpentNext(tx, d) + case Event(WatchFundingSpentTriggered(tx), d: PersistentChannelData) if d.commitments.remoteNextCommitInfo.left.toOption.exists(_.nextRemoteCommit.txid == tx.txid) => handleRemoteSpentNext(tx, d) case Event(WatchFundingSpentTriggered(tx), d: DATA_WAIT_FOR_REMOTE_PUBLISH_FUTURE_COMMITMENT) => handleRemoteSpentFuture(tx, d) - case Event(WatchFundingSpentTriggered(tx), d: HasCommitments) => handleRemoteSpentOther(tx, d) + case Event(WatchFundingSpentTriggered(tx), d: PersistentChannelData) => handleRemoteSpentOther(tx, d) }) @@ -1464,9 +1464,9 @@ class Channel(val nodeParams: NodeParams, val wallet: OnChainChannelFunder, val context.system.scheduler.scheduleOnce(5 seconds, self, remoteAnnSigs) stay() sending Warning(d.channelId, "spec violation: you sent announcement_signatures before channel_reestablish") - case Event(ProcessCurrentBlockHeight(c), d: HasCommitments) => handleNewBlock(c, d) + case Event(ProcessCurrentBlockHeight(c), d: PersistentChannelData) => handleNewBlock(c, d) - case Event(c: CurrentFeerates, d: HasCommitments) => handleCurrentFeerateDisconnected(c, d) + case Event(c: CurrentFeerates, d: PersistentChannelData) => handleCurrentFeerateDisconnected(c, d) case Event(getTxResponse: GetTxWithMetaResponse, d: DATA_WAIT_FOR_FUNDING_CONFIRMED) if getTxResponse.txid == d.commitments.commitInput.outPoint.txid => handleGetFundingTx(getTxResponse, d.waitingSince, d.fundingTx) @@ -1482,13 +1482,13 @@ class Channel(val nodeParams: NodeParams, val wallet: OnChainChannelFunder, val case Event(WatchFundingSpentTriggered(tx), d: DATA_NEGOTIATING) if d.closingTxProposed.flatten.exists(_.unsignedTx.tx.txid == tx.txid) => handleMutualClose(getMutualClosePublished(tx, d.closingTxProposed), Left(d)) - case Event(WatchFundingSpentTriggered(tx), d: HasCommitments) if tx.txid == d.commitments.remoteCommit.txid => handleRemoteSpentCurrent(tx, d) + case Event(WatchFundingSpentTriggered(tx), d: PersistentChannelData) if tx.txid == d.commitments.remoteCommit.txid => handleRemoteSpentCurrent(tx, d) - case Event(WatchFundingSpentTriggered(tx), d: HasCommitments) if d.commitments.remoteNextCommitInfo.left.toOption.exists(_.nextRemoteCommit.txid == tx.txid) => handleRemoteSpentNext(tx, d) + case Event(WatchFundingSpentTriggered(tx), d: PersistentChannelData) if d.commitments.remoteNextCommitInfo.left.toOption.exists(_.nextRemoteCommit.txid == tx.txid) => handleRemoteSpentNext(tx, d) - case Event(WatchFundingSpentTriggered(tx), d: HasCommitments) => handleRemoteSpentOther(tx, d) + case Event(WatchFundingSpentTriggered(tx), d: PersistentChannelData) => handleRemoteSpentOther(tx, d) - case Event(e: Error, d: HasCommitments) => handleRemoteError(e, d) + case Event(e: Error, d: PersistentChannelData) => handleRemoteError(e, d) }) when(WAIT_FOR_REMOTE_PUBLISH_FUTURE_COMMITMENT)(handleExceptions { @@ -1524,7 +1524,7 @@ class Channel(val nodeParams: NodeParams, val wallet: OnChainChannelFunder, val replyTo ! RES_GETINFO(remoteNodeId, stateData.channelId, stateName, stateData) stay() - case Event(c: CMD_ADD_HTLC, d: HasCommitments) => + case Event(c: CMD_ADD_HTLC, d: PersistentChannelData) => log.info(s"rejecting htlc request in state=$stateName") val error = ChannelUnavailable(d.channelId) handleAddHtlcCommandError(c, error, None) // we don't provide a channel_update: this will be a permanent channel failure @@ -1533,12 +1533,13 @@ class Channel(val nodeParams: NodeParams, val wallet: OnChainChannelFunder, val case Event(c: CMD_FORCECLOSE, d) => d match { - case data: HasCommitments => + case data: PersistentChannelData => val replyTo = if (c.replyTo == ActorRef.noSender) sender() else c.replyTo replyTo ! RES_SUCCESS(c, data.channelId) val failure = ForcedLocalCommit(data.channelId) handleLocalError(failure, data, Some(c)) - case _ => handleCommandError(CommandUnavailableInThisState(d.channelId, "forceclose", stateName), c) + case _: TransientChannelData => + handleCommandError(CommandUnavailableInThisState(d.channelId, "forceclose", stateName), c) } // In states where we don't explicitly handle this command, we won't broadcast a new channel update immediately, @@ -1572,12 +1573,12 @@ class Channel(val nodeParams: NodeParams, val wallet: OnChainChannelFunder, val case Event("disconnecting", _) => stay() // funding tx was confirmed in time, let's just ignore this - case Event(BITCOIN_FUNDING_TIMEOUT, _: HasCommitments) => stay() + case Event(BITCOIN_FUNDING_TIMEOUT, _: PersistentChannelData) => stay() // peer doesn't cancel the timer case Event(TickChannelOpenTimeout, _) => stay() - case Event(WatchFundingSpentTriggered(tx), d: HasCommitments) if tx.txid == d.commitments.localCommit.commitTxAndRemoteSig.commitTx.tx.txid => + case Event(WatchFundingSpentTriggered(tx), d: PersistentChannelData) if tx.txid == d.commitments.localCommit.commitTxAndRemoteSig.commitTx.tx.txid => log.warning(s"processing local commit spent in catch-all handler") spendLocalCurrent(d) } @@ -1587,8 +1588,8 @@ class Channel(val nodeParams: NodeParams, val wallet: OnChainChannelFunder, val case state -> nextState => if (state != nextState) { val commitments_opt = nextStateData match { - case hasCommitments: HasCommitments => Some(hasCommitments.commitments) - case _ => None + case d: PersistentChannelData => Some(d.commitments) + case _: TransientChannelData => None } context.system.eventStream.publish(ChannelStateChanged(self, nextStateData.channelId, peer, remoteNodeId, state, nextState, commitments_opt)) } @@ -1661,7 +1662,7 @@ class Channel(val nodeParams: NodeParams, val wallet: OnChainChannelFunder, val /** Check pending settlement commands */ onTransition { case _ -> CLOSING => - PendingCommandsDb.getSettlementCommands(nodeParams.db.pendingCommands, nextStateData.asInstanceOf[HasCommitments].channelId) match { + PendingCommandsDb.getSettlementCommands(nodeParams.db.pendingCommands, nextStateData.channelId) match { case Nil => log.debug("nothing to replay") case cmds => @@ -1669,7 +1670,7 @@ class Channel(val nodeParams: NodeParams, val wallet: OnChainChannelFunder, val cmds.foreach(self ! _) // they all have commit = false } case SYNCING -> (NORMAL | SHUTDOWN) => - PendingCommandsDb.getSettlementCommands(nodeParams.db.pendingCommands, nextStateData.asInstanceOf[HasCommitments].channelId) match { + PendingCommandsDb.getSettlementCommands(nodeParams.db.pendingCommands, nextStateData.channelId) match { case Nil => log.debug("nothing to replay") case cmds => @@ -1701,7 +1702,7 @@ class Channel(val nodeParams: NodeParams, val wallet: OnChainChannelFunder, val 888 888 d88P 888 888 Y888 8888888P" 88888888 8888888888 888 T88b "Y8888P" */ - private def handleCurrentFeerate(c: CurrentFeerates, d: HasCommitments) = { + private def handleCurrentFeerate(c: CurrentFeerates, d: PersistentChannelData) = { val networkFeeratePerKw = nodeParams.onChainFeeConf.getCommitmentFeerate(remoteNodeId, d.commitments.channelType, d.commitments.capacity, Some(c)) val currentFeeratePerKw = d.commitments.localCommit.spec.commitTxFeerate val shouldUpdateFee = d.commitments.localParams.isFunder && nodeParams.onChainFeeConf.shouldUpdateFee(currentFeeratePerKw, networkFeeratePerKw) @@ -1725,7 +1726,7 @@ class Channel(val nodeParams: NodeParams, val wallet: OnChainChannelFunder, val * @param d the channel commtiments * @return */ - private def handleCurrentFeerateDisconnected(c: CurrentFeerates, d: HasCommitments) = { + private def handleCurrentFeerateDisconnected(c: CurrentFeerates, d: PersistentChannelData) = { val networkFeeratePerKw = nodeParams.onChainFeeConf.getCommitmentFeerate(remoteNodeId, d.commitments.channelType, d.commitments.capacity, Some(c)) val currentFeeratePerKw = d.commitments.localCommit.spec.commitTxFeerate // if the network fees are too high we risk to not be able to confirm our current commitment @@ -1760,7 +1761,7 @@ class Channel(val nodeParams: NodeParams, val wallet: OnChainChannelFunder, val log.warning(s"${cause.getMessage} while processing cmd=${c.getClass.getSimpleName} in state=$stateName") val replyTo = if (c.replyTo == ActorRef.noSender) sender() else c.replyTo replyTo ! RES_ADD_FAILED(c, cause, channelUpdate) - context.system.eventStream.publish(ChannelErrorOccurred(self, stateData.channelId, remoteNodeId, stateData, LocalError(cause), isFatal = false)) + context.system.eventStream.publish(ChannelErrorOccurred(self, stateData.channelId, remoteNodeId, LocalError(cause), isFatal = false)) stay() } @@ -1771,11 +1772,11 @@ class Channel(val nodeParams: NodeParams, val wallet: OnChainChannelFunder, val case hasReplyTo: HasReplyToCommand => if (hasReplyTo.replyTo == ActorRef.noSender) Some(sender()) else Some(hasReplyTo.replyTo) } replyTo_opt.foreach(replyTo => replyTo ! RES_FAILURE(c, cause)) - context.system.eventStream.publish(ChannelErrorOccurred(self, stateData.channelId, remoteNodeId, stateData, LocalError(cause), isFatal = false)) + context.system.eventStream.publish(ChannelErrorOccurred(self, stateData.channelId, remoteNodeId, LocalError(cause), isFatal = false)) stay() } - private def handleRevocationTimeout(revocationTimeout: RevocationTimeout, d: HasCommitments) = { + private def handleRevocationTimeout(revocationTimeout: RevocationTimeout, d: PersistentChannelData) = { d.commitments.remoteNextCommitInfo match { case Left(waitingForRevocation) if revocationTimeout.remoteCommitNumber + 1 == waitingForRevocation.nextRemoteCommit.index => log.warning(s"waited for too long for a revocation to remoteCommitNumber=${revocationTimeout.remoteCommitNumber}, disconnecting") @@ -1817,7 +1818,7 @@ class Channel(val nodeParams: NodeParams, val wallet: OnChainChannelFunder, val stay() using d.copy(channelUpdate = channelUpdate1) storing() } - private def handleSyncFailure(channelReestablish: ChannelReestablish, syncFailure: SyncResult.Failure, d: HasCommitments) = { + private def handleSyncFailure(channelReestablish: ChannelReestablish, syncFailure: SyncResult.Failure, d: PersistentChannelData) = { syncFailure match { case res: SyncResult.LocalLateProven => log.error(s"counterparty proved that we have an outdated (revoked) local commitment!!! ourLocalCommitmentNumber=${res.ourLocalCommitmentNumber} theirRemoteCommitmentNumber=${res.theirRemoteCommitmentNumber}") @@ -1846,7 +1847,7 @@ class Channel(val nodeParams: NodeParams, val wallet: OnChainChannelFunder, val } } - private def handleNewBlock(c: CurrentBlockHeight, d: HasCommitments) = { + private def handleNewBlock(c: CurrentBlockHeight, d: PersistentChannelData) = { val timedOutOutgoing = d.commitments.timedOutOutgoingHtlcs(c.blockHeight) val almostTimedOutIncoming = d.commitments.almostTimedOutIncomingHtlcs(c.blockHeight, nodeParams.channelConf.fulfillSafetyBeforeTimeout) if (timedOutOutgoing.nonEmpty) { diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/channel/fsm/CommonHandlers.scala b/eclair-core/src/main/scala/fr/acinq/eclair/channel/fsm/CommonHandlers.scala index 5c199d33d9..3fd98cd9a3 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/channel/fsm/CommonHandlers.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/channel/fsm/CommonHandlers.scala @@ -49,12 +49,12 @@ trait CommonHandlers { def storing(unused: Unit = ()): FSM.State[ChannelState, ChannelData] = { state.stateData match { - case d: HasCommitments => + case d: PersistentChannelData => log.debug("updating database record for channelId={}", d.channelId) nodeParams.db.channels.addOrUpdateChannel(d) context.system.eventStream.publish(ChannelPersisted(self, remoteNodeId, d.channelId, d)) state - case _ => + case _: TransientChannelData => log.error(s"can't store data=${state.stateData} in state=${state.stateName}") state } diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/channel/fsm/ErrorHandlers.scala b/eclair-core/src/main/scala/fr/acinq/eclair/channel/fsm/ErrorHandlers.scala index b03158d1cd..1856a67ab3 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/channel/fsm/ErrorHandlers.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/channel/fsm/ErrorHandlers.scala @@ -80,15 +80,15 @@ trait ErrorHandlers extends CommonHandlers { } val error = Error(d.channelId, cause.getMessage) - context.system.eventStream.publish(ChannelErrorOccurred(self, stateData.channelId, remoteNodeId, stateData, LocalError(cause), isFatal = true)) + context.system.eventStream.publish(ChannelErrorOccurred(self, stateData.channelId, remoteNodeId, LocalError(cause), isFatal = true)) d match { - case dd: HasCommitments if Closing.nothingAtStake(dd) => goto(CLOSED) + case dd: PersistentChannelData if Closing.nothingAtStake(dd) => goto(CLOSED) case negotiating@DATA_NEGOTIATING(_, _, _, _, Some(bestUnpublishedClosingTx)) => log.info(s"we have a valid closing tx, publishing it instead of our commitment: closingTxId=${bestUnpublishedClosingTx.tx.txid}") // if we were in the process of closing and already received a closing sig from the counterparty, it's always better to use that handleMutualClose(bestUnpublishedClosingTx, Left(negotiating)) - case dd: HasCommitments => + case dd: PersistentChannelData => cause match { case _: ChannelException => // known channel exception: we force close using our current commitment @@ -113,14 +113,14 @@ trait ErrorHandlers extends CommonHandlers { stop(FSM.Shutdown) } } - case _ => goto(CLOSED) sending error // when there is no commitment yet, we just send an error to our peer and go to CLOSED state + case _: TransientChannelData => goto(CLOSED) sending error // when there is no commitment yet, we just send an error to our peer and go to CLOSED state } } def handleRemoteError(e: Error, d: ChannelData) = { // see BOLT 1: only print out data verbatim if is composed of printable ASCII characters log.error(s"peer sent error: ascii='${e.toAscii}' bin=${e.data.toHex}") - context.system.eventStream.publish(ChannelErrorOccurred(self, stateData.channelId, remoteNodeId, stateData, RemoteError(e), isFatal = true)) + context.system.eventStream.publish(ChannelErrorOccurred(self, stateData.channelId, remoteNodeId, RemoteError(e), isFatal = true)) d match { case _: DATA_CLOSING => stay() // nothing to do, there is already a spending tx published @@ -128,8 +128,8 @@ trait ErrorHandlers extends CommonHandlers { // if we were in the process of closing and already received a closing sig from the counterparty, it's always better to use that handleMutualClose(bestUnpublishedClosingTx, Left(negotiating)) case d: DATA_WAIT_FOR_FUNDING_CONFIRMED if Closing.nothingAtStake(d) => goto(CLOSED) // the channel was never used and the funding tx may be double-spent - case hasCommitments: HasCommitments => spendLocalCurrent(hasCommitments) // NB: we publish the commitment even if we have nothing at stake (in a dataloss situation our peer will send us an error just for that) - case _ => goto(CLOSED) // when there is no commitment yet, we just go to CLOSED state in case an error occurs + case hasCommitments: PersistentChannelData => spendLocalCurrent(hasCommitments) // NB: we publish the commitment even if we have nothing at stake (in a dataloss situation our peer will send us an error just for that) + case _: TransientChannelData => goto(CLOSED) // when there is no commitment yet, we just go to CLOSED state in case an error occurs } } @@ -166,7 +166,7 @@ trait ErrorHandlers extends CommonHandlers { skip.foreach(output => log.info(s"no need to watch output=${output.txid}:${output.index}, it has already been spent by txid=${irrevocablySpent.get(output).map(_.txid)}")) } - def spendLocalCurrent(d: HasCommitments) = { + def spendLocalCurrent(d: PersistentChannelData) = { val outdatedCommitment = d match { case _: DATA_WAIT_FOR_REMOTE_PUBLISH_FUTURE_COMMITMENT => true case closing: DATA_CLOSING if closing.futureRemoteCommitPublished.isDefined => true @@ -217,7 +217,7 @@ trait ErrorHandlers extends CommonHandlers { watchSpentIfNeeded(commitTx, watchSpentQueue, irrevocablySpent) } - def handleRemoteSpentCurrent(commitTx: Transaction, d: HasCommitments) = { + def handleRemoteSpentCurrent(commitTx: Transaction, d: PersistentChannelData) = { log.warning(s"they published their current commit in txid=${commitTx.txid}") require(commitTx.txid == d.commitments.remoteCommit.txid, "txid mismatch") @@ -246,7 +246,7 @@ trait ErrorHandlers extends CommonHandlers { goto(CLOSING) using nextData storing() calling doPublish(remoteCommitPublished, d.commitments) } - def handleRemoteSpentNext(commitTx: Transaction, d: HasCommitments) = { + def handleRemoteSpentNext(commitTx: Transaction, d: PersistentChannelData) = { log.warning(s"they published their next commit in txid=${commitTx.txid}") require(d.commitments.remoteNextCommitInfo.isLeft, "next remote commit must be defined") val Left(waitingForRevocation) = d.commitments.remoteNextCommitInfo @@ -282,7 +282,7 @@ trait ErrorHandlers extends CommonHandlers { watchSpentIfNeeded(commitTx, watchSpentQueue, irrevocablySpent) } - def handleRemoteSpentOther(tx: Transaction, d: HasCommitments) = { + def handleRemoteSpentOther(tx: Transaction, d: PersistentChannelData) = { log.warning(s"funding tx spent in txid=${tx.txid}") Closing.RevokedClose.claimCommitTxOutputs(keyManager, d.commitments, tx, nodeParams.db.channels, nodeParams.onChainFeeConf.feeEstimator, nodeParams.onChainFeeConf.feeTargets) match { case Some(revokedCommitPublished) => @@ -323,7 +323,7 @@ trait ErrorHandlers extends CommonHandlers { watchSpentIfNeeded(commitTx, watchSpentQueue, irrevocablySpent) } - def handleInformationLeak(tx: Transaction, d: HasCommitments) = { + def handleInformationLeak(tx: Transaction, d: PersistentChannelData) = { // this is never supposed to happen !! log.error(s"our funding tx ${d.commitments.commitInput.outPoint.txid} was spent by txid=${tx.txid}!!") context.system.eventStream.publish(NotifyNodeOperator(NotificationsLogger.Error, s"funding tx ${d.commitments.commitInput.outPoint.txid} of channel ${d.channelId} was spent by an unknown transaction, indicating that your DB has lost data or your node has been breached: please contact the dev team.")) @@ -337,7 +337,7 @@ trait ErrorHandlers extends CommonHandlers { goto(ERR_INFORMATION_LEAK) calling doPublish(localCommitPublished, d.commitments) sending error } - def handleOutdatedCommitment(channelReestablish: ChannelReestablish, d: HasCommitments) = { + def handleOutdatedCommitment(channelReestablish: ChannelReestablish, d: PersistentChannelData) = { val exc = PleasePublishYourCommitment(d.channelId) val error = Error(d.channelId, exc.getMessage) goto(WAIT_FOR_REMOTE_PUBLISH_FUTURE_COMMITMENT) using DATA_WAIT_FOR_REMOTE_PUBLISH_FUTURE_COMMITMENT(d.commitments, channelReestablish) storing() sending error diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/channel/fsm/FundingHandlers.scala b/eclair-core/src/main/scala/fr/acinq/eclair/channel/fsm/FundingHandlers.scala index 2b3eb92b02..f478859c2f 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/channel/fsm/FundingHandlers.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/channel/fsm/FundingHandlers.scala @@ -102,21 +102,21 @@ trait FundingHandlers extends CommonHandlers { stay() } - def handleFundingPublishFailed(d: HasCommitments) = { + def handleFundingPublishFailed(d: PersistentChannelData) = { log.error(s"failed to publish funding tx") val exc = ChannelFundingError(d.channelId) val error = Error(d.channelId, exc.getMessage) // NB: we don't use the handleLocalError handler because it would result in the commit tx being published, which we don't want: // implementation *guarantees* that in case of BITCOIN_FUNDING_PUBLISH_FAILED, the funding tx hasn't and will never be published, so we can close the channel right away - context.system.eventStream.publish(ChannelErrorOccurred(self, stateData.channelId, remoteNodeId, stateData, LocalError(exc), isFatal = true)) + context.system.eventStream.publish(ChannelErrorOccurred(self, stateData.channelId, remoteNodeId, LocalError(exc), isFatal = true)) goto(CLOSED) sending error } - def handleFundingTimeout(d: HasCommitments) = { + def handleFundingTimeout(d: PersistentChannelData) = { log.warning(s"funding tx hasn't been confirmed in time, cancelling channel delay=$FUNDING_TIMEOUT_FUNDEE") val exc = FundingTxTimedout(d.channelId) val error = Error(d.channelId, exc.getMessage) - context.system.eventStream.publish(ChannelErrorOccurred(self, stateData.channelId, remoteNodeId, stateData, LocalError(exc), isFatal = true)) + context.system.eventStream.publish(ChannelErrorOccurred(self, stateData.channelId, remoteNodeId, LocalError(exc), isFatal = true)) goto(CLOSED) sending error } diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/db/ChannelsDb.scala b/eclair-core/src/main/scala/fr/acinq/eclair/db/ChannelsDb.scala index 585191cf63..621862caed 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/db/ChannelsDb.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/db/ChannelsDb.scala @@ -18,22 +18,22 @@ package fr.acinq.eclair.db import fr.acinq.bitcoin.scalacompat.ByteVector32 import fr.acinq.eclair.CltvExpiry -import fr.acinq.eclair.channel.HasCommitments +import fr.acinq.eclair.channel.PersistentChannelData import fr.acinq.eclair.db.DbEventHandler.ChannelEvent import java.io.Closeable trait ChannelsDb extends Closeable { - def addOrUpdateChannel(state: HasCommitments): Unit + def addOrUpdateChannel(data: PersistentChannelData): Unit - def getChannel(channelId: ByteVector32): Option[HasCommitments] + def getChannel(channelId: ByteVector32): Option[PersistentChannelData] def updateChannelMeta(channelId: ByteVector32, event: ChannelEvent.EventType): Unit def removeChannel(channelId: ByteVector32): Unit - def listLocalChannels(): Seq[HasCommitments] + def listLocalChannels(): Seq[PersistentChannelData] def addHtlcInfo(channelId: ByteVector32, commitmentNumber: Long, paymentHash: ByteVector32, cltvExpiry: CltvExpiry): Unit diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/db/DualDatabases.scala b/eclair-core/src/main/scala/fr/acinq/eclair/db/DualDatabases.scala index 512d166355..3d64cd57a0 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/db/DualDatabases.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/db/DualDatabases.scala @@ -6,7 +6,6 @@ import fr.acinq.eclair.channel._ import fr.acinq.eclair.db.Databases.{FileBackup, PostgresDatabases, SqliteDatabases} import fr.acinq.eclair.db.DbEventHandler.ChannelEvent import fr.acinq.eclair.db.DualDatabases.runAsync -import fr.acinq.eclair.io.Peer import fr.acinq.eclair.payment._ import fr.acinq.eclair.payment.relay.Relayer.RelayFees import fr.acinq.eclair.router.Router @@ -224,12 +223,12 @@ case class DualChannelsDb(primary: ChannelsDb, secondary: ChannelsDb) extends Ch private implicit val ec: ExecutionContext = ExecutionContext.fromExecutor(Executors.newSingleThreadExecutor(new ThreadFactoryBuilder().setNameFormat("db-channels").build())) - override def addOrUpdateChannel(state: HasCommitments): Unit = { - runAsync(secondary.addOrUpdateChannel(state)) - primary.addOrUpdateChannel(state) + override def addOrUpdateChannel(data: PersistentChannelData): Unit = { + runAsync(secondary.addOrUpdateChannel(data)) + primary.addOrUpdateChannel(data) } - override def getChannel(channelId: ByteVector32): Option[HasCommitments] = { + override def getChannel(channelId: ByteVector32): Option[PersistentChannelData] = { runAsync(secondary.getChannel(channelId)) primary.getChannel(channelId) } @@ -244,7 +243,7 @@ case class DualChannelsDb(primary: ChannelsDb, secondary: ChannelsDb) extends Ch primary.removeChannel(channelId) } - override def listLocalChannels(): Seq[HasCommitments] = { + override def listLocalChannels(): Seq[PersistentChannelData] = { runAsync(secondary.listLocalChannels()) primary.listLocalChannels() } diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/db/migration/CompareChannelsDb.scala b/eclair-core/src/main/scala/fr/acinq/eclair/db/migration/CompareChannelsDb.scala index 7f166a4d36..3905503b0f 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/db/migration/CompareChannelsDb.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/db/migration/CompareChannelsDb.scala @@ -3,7 +3,7 @@ package fr.acinq.eclair.db.migration import fr.acinq.eclair.BlockHeight import fr.acinq.eclair.channel.{DATA_CLOSING, DATA_WAIT_FOR_FUNDING_CONFIRMED} import fr.acinq.eclair.db.migration.CompareDb._ -import fr.acinq.eclair.wire.internal.channel.ChannelCodecs.stateDataCodec +import fr.acinq.eclair.wire.internal.channel.ChannelCodecs.channelDataCodec import scodec.bits.ByteVector import java.sql.{Connection, ResultSet} @@ -16,9 +16,9 @@ object CompareChannelsDb { def hash1(rs: ResultSet): ByteVector = { val data = ByteVector(rs.getBytes("data")) - val data_modified = stateDataCodec.decode(data.bits).require.value match { - case c: DATA_WAIT_FOR_FUNDING_CONFIRMED => stateDataCodec.encode(c.copy(waitingSince = BlockHeight(0))).require.toByteVector - case c: DATA_CLOSING => stateDataCodec.encode(c.copy(waitingSince = BlockHeight(0))).require.toByteVector + val data_modified = channelDataCodec.decode(data.bits).require.value match { + case c: DATA_WAIT_FOR_FUNDING_CONFIRMED => channelDataCodec.encode(c.copy(waitingSince = BlockHeight(0))).require.toByteVector + case c: DATA_CLOSING => channelDataCodec.encode(c.copy(waitingSince = BlockHeight(0))).require.toByteVector case _ => data } bytes(rs, "channel_id") ++ @@ -33,9 +33,9 @@ object CompareChannelsDb { def hash2(rs: ResultSet): ByteVector = { val data = ByteVector(rs.getBytes("data")) - val data_modified = stateDataCodec.decode(data.bits).require.value match { - case c: DATA_WAIT_FOR_FUNDING_CONFIRMED => stateDataCodec.encode(c.copy(waitingSince = BlockHeight(0))).require.toByteVector - case c: DATA_CLOSING => stateDataCodec.encode(c.copy(waitingSince = BlockHeight(0))).require.toByteVector + val data_modified = channelDataCodec.decode(data.bits).require.value match { + case c: DATA_WAIT_FOR_FUNDING_CONFIRMED => channelDataCodec.encode(c.copy(waitingSince = BlockHeight(0))).require.toByteVector + case c: DATA_CLOSING => channelDataCodec.encode(c.copy(waitingSince = BlockHeight(0))).require.toByteVector case _ => data } hex(rs, "channel_id") ++ diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/db/migration/MigrateChannelsDb.scala b/eclair-core/src/main/scala/fr/acinq/eclair/db/migration/MigrateChannelsDb.scala index 0758b1efe5..37055d465b 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/db/migration/MigrateChannelsDb.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/db/migration/MigrateChannelsDb.scala @@ -2,7 +2,7 @@ package fr.acinq.eclair.db.migration import fr.acinq.eclair.db.jdbc.JdbcUtils.ExtendedResultSet._ import fr.acinq.eclair.db.migration.MigrateDb.{checkVersions, migrateTable} -import fr.acinq.eclair.wire.internal.channel.ChannelCodecs.stateDataCodec +import fr.acinq.eclair.wire.internal.channel.ChannelCodecs.channelDataCodec import scodec.bits.BitVector import java.sql.{Connection, PreparedStatement, ResultSet, Timestamp} @@ -19,7 +19,7 @@ object MigrateChannelsDb { def migrate(rs: ResultSet, insertStatement: PreparedStatement): Unit = { insertStatement.setString(1, rs.getByteVector32("channel_id").toHex) insertStatement.setBytes(2, rs.getBytes("data")) - val state = stateDataCodec.decode(BitVector(rs.getBytes("data"))).require.value + val state = channelDataCodec.decode(BitVector(rs.getBytes("data"))).require.value val json = serialization.writePretty(state) insertStatement.setString(3, json) insertStatement.setBoolean(4, rs.getBoolean("is_closed")) diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/db/pg/PgChannelsDb.scala b/eclair-core/src/main/scala/fr/acinq/eclair/db/pg/PgChannelsDb.scala index 0317057add..6dc38e4e13 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/db/pg/PgChannelsDb.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/db/pg/PgChannelsDb.scala @@ -19,13 +19,13 @@ package fr.acinq.eclair.db.pg import com.zaxxer.hikari.util.IsolationLevel import fr.acinq.bitcoin.scalacompat.ByteVector32 import fr.acinq.eclair.CltvExpiry -import fr.acinq.eclair.channel.HasCommitments +import fr.acinq.eclair.channel.PersistentChannelData import fr.acinq.eclair.db.ChannelsDb import fr.acinq.eclair.db.DbEventHandler.ChannelEvent import fr.acinq.eclair.db.Monitoring.Metrics.withMetrics import fr.acinq.eclair.db.Monitoring.Tags.DbBackends import fr.acinq.eclair.db.pg.PgUtils.PgLock -import fr.acinq.eclair.wire.internal.channel.ChannelCodecs.stateDataCodec +import fr.acinq.eclair.wire.internal.channel.ChannelCodecs.channelDataCodec import grizzled.slf4j.Logging import scodec.bits.BitVector @@ -89,8 +89,8 @@ class PgChannelsDb(implicit ds: DataSource, lock: PgLock) extends ChannelsDb wit (rs, statement) => { // This forces a re-serialization of the channel data with latest codecs, because as of codecs v3 we don't // store local commitment signatures anymore, and we want to clean up existing data - val state = stateDataCodec.decode(BitVector(rs.getBytes("data"))).require.value - val data = stateDataCodec.encode(state).require.toByteArray + val state = channelDataCodec.decode(BitVector(rs.getBytes("data"))).require.value + val data = channelDataCodec.encode(state).require.toByteArray val json = serialization.writePretty(state) statement.setBytes(1, data) statement.setString(2, json) @@ -140,7 +140,7 @@ class PgChannelsDb(implicit ds: DataSource, lock: PgLock) extends ChannelsDb wit table, s"UPDATE $table SET json=?::JSONB WHERE channel_id=?", (rs, statement) => { - val state = stateDataCodec.decode(BitVector(rs.getBytes("data"))).require.value + val state = channelDataCodec.decode(BitVector(rs.getBytes("data"))).require.value val json = serialization.writePretty(state) statement.setString(1, json) statement.setString(2, state.channelId.toHex) @@ -148,9 +148,9 @@ class PgChannelsDb(implicit ds: DataSource, lock: PgLock) extends ChannelsDb wit )(logger) } - override def addOrUpdateChannel(state: HasCommitments): Unit = withMetrics("channels/add-or-update-channel", DbBackends.Postgres) { + override def addOrUpdateChannel(data: PersistentChannelData): Unit = withMetrics("channels/add-or-update-channel", DbBackends.Postgres) { withLock { pg => - val data = stateDataCodec.encode(state).require.toByteArray + val encoded = channelDataCodec.encode(data).require.toByteArray using(pg.prepareStatement( """ | INSERT INTO local.channels (channel_id, data, json, is_closed) @@ -158,19 +158,19 @@ class PgChannelsDb(implicit ds: DataSource, lock: PgLock) extends ChannelsDb wit | ON CONFLICT (channel_id) | DO UPDATE SET data = EXCLUDED.data, json = EXCLUDED.json ; | """.stripMargin)) { statement => - statement.setString(1, state.channelId.toHex) - statement.setBytes(2, data) - statement.setString(3, serialization.writePretty(state)) + statement.setString(1, data.channelId.toHex) + statement.setBytes(2, encoded) + statement.setString(3, serialization.writePretty(data)) statement.executeUpdate() } } } - override def getChannel(channelId: ByteVector32): Option[HasCommitments] = withMetrics("channels/get-channel", DbBackends.Postgres) { + override def getChannel(channelId: ByteVector32): Option[PersistentChannelData] = withMetrics("channels/get-channel", DbBackends.Postgres) { withLock { pg => using(pg.prepareStatement("SELECT data FROM local.channels WHERE channel_id=? AND is_closed=FALSE")) { statement => statement.setString(1, channelId.toHex) - statement.executeQuery.mapCodec(stateDataCodec).lastOption + statement.executeQuery.mapCodec(channelDataCodec).lastOption } } } @@ -219,11 +219,11 @@ class PgChannelsDb(implicit ds: DataSource, lock: PgLock) extends ChannelsDb wit } } - override def listLocalChannels(): Seq[HasCommitments] = withMetrics("channels/list-local-channels", DbBackends.Postgres) { + override def listLocalChannels(): Seq[PersistentChannelData] = withMetrics("channels/list-local-channels", DbBackends.Postgres) { withLock { pg => using(pg.createStatement) { statement => statement.executeQuery("SELECT data FROM local.channels WHERE is_closed=FALSE") - .mapCodec(stateDataCodec).toSeq + .mapCodec(channelDataCodec).toSeq } } } diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/db/sqlite/SqliteChannelsDb.scala b/eclair-core/src/main/scala/fr/acinq/eclair/db/sqlite/SqliteChannelsDb.scala index ea61a527e7..3cb8df57b3 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/db/sqlite/SqliteChannelsDb.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/db/sqlite/SqliteChannelsDb.scala @@ -17,13 +17,13 @@ package fr.acinq.eclair.db.sqlite import fr.acinq.bitcoin.scalacompat.ByteVector32 -import fr.acinq.eclair.{CltvExpiry, TimestampMilli} -import fr.acinq.eclair.channel.HasCommitments +import fr.acinq.eclair.channel.PersistentChannelData import fr.acinq.eclair.db.ChannelsDb import fr.acinq.eclair.db.DbEventHandler.ChannelEvent import fr.acinq.eclair.db.Monitoring.Metrics.withMetrics import fr.acinq.eclair.db.Monitoring.Tags.DbBackends -import fr.acinq.eclair.wire.internal.channel.ChannelCodecs.stateDataCodec +import fr.acinq.eclair.wire.internal.channel.ChannelCodecs.channelDataCodec +import fr.acinq.eclair.{CltvExpiry, TimestampMilli} import grizzled.slf4j.Logging import scodec.bits.BitVector @@ -70,8 +70,8 @@ class SqliteChannelsDb(val sqlite: Connection) extends ChannelsDb with Logging { (rs, statement) => { // This forces a re-serialization of the channel data with latest codecs, because as of codecs v3 we don't // store local commitment signatures anymore, and we want to clean up existing data - val state = stateDataCodec.decode(BitVector(rs.getBytes("data"))).require.value - val data = stateDataCodec.encode(state).require.toByteArray + val state = channelDataCodec.decode(BitVector(rs.getBytes("data"))).require.value + val data = channelDataCodec.encode(state).require.toByteArray statement.setBytes(1, data) statement.setBytes(2, state.channelId.toArray) } @@ -100,25 +100,25 @@ class SqliteChannelsDb(val sqlite: Connection) extends ChannelsDb with Logging { setVersion(statement, DB_NAME, CURRENT_VERSION) } - override def addOrUpdateChannel(state: HasCommitments): Unit = withMetrics("channels/add-or-update-channel", DbBackends.Sqlite) { - val data = stateDataCodec.encode(state).require.toByteArray + override def addOrUpdateChannel(data: PersistentChannelData): Unit = withMetrics("channels/add-or-update-channel", DbBackends.Sqlite) { + val encoded = channelDataCodec.encode(data).require.toByteArray using(sqlite.prepareStatement("UPDATE local_channels SET data=? WHERE channel_id=?")) { update => - update.setBytes(1, data) - update.setBytes(2, state.channelId.toArray) + update.setBytes(1, encoded) + update.setBytes(2, data.channelId.toArray) if (update.executeUpdate() == 0) { using(sqlite.prepareStatement("INSERT INTO local_channels (channel_id, data, is_closed) VALUES (?, ?, 0)")) { statement => - statement.setBytes(1, state.channelId.toArray) - statement.setBytes(2, data) + statement.setBytes(1, data.channelId.toArray) + statement.setBytes(2, encoded) statement.executeUpdate() } } } } - override def getChannel(channelId: ByteVector32): Option[HasCommitments] = withMetrics("channels/get-channel", DbBackends.Sqlite) { + override def getChannel(channelId: ByteVector32): Option[PersistentChannelData] = withMetrics("channels/get-channel", DbBackends.Sqlite) { using(sqlite.prepareStatement("SELECT data FROM local_channels WHERE channel_id=? AND is_closed=0")) { statement => statement.setBytes(1, channelId.toArray) - statement.executeQuery.mapCodec(stateDataCodec).lastOption + statement.executeQuery.mapCodec(channelDataCodec).lastOption } } @@ -162,10 +162,10 @@ class SqliteChannelsDb(val sqlite: Connection) extends ChannelsDb with Logging { } } - override def listLocalChannels(): Seq[HasCommitments] = withMetrics("channels/list-local-channels", DbBackends.Sqlite) { + override def listLocalChannels(): Seq[PersistentChannelData] = withMetrics("channels/list-local-channels", DbBackends.Sqlite) { using(sqlite.createStatement) { statement => statement.executeQuery("SELECT data FROM local_channels WHERE is_closed=0") - .mapCodec(stateDataCodec).toSeq + .mapCodec(channelDataCodec).toSeq } } diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/io/Peer.scala b/eclair-core/src/main/scala/fr/acinq/eclair/io/Peer.scala index 67136eac53..0c0ef910c7 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/io/Peer.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/io/Peer.scala @@ -455,7 +455,7 @@ object Peer { case object DISCONNECTED extends State case object CONNECTED extends State - case class Init(storedChannels: Set[HasCommitments]) + case class Init(storedChannels: Set[PersistentChannelData]) case class Connect(nodeId: PublicKey, address_opt: Option[NodeAddress], replyTo: ActorRef, isPersistent: Boolean) { def uri: Option[NodeURI] = address_opt.map(NodeURI(nodeId, _)) } diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/io/Switchboard.scala b/eclair-core/src/main/scala/fr/acinq/eclair/io/Switchboard.scala index a3ec6355bd..640f484177 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/io/Switchboard.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/io/Switchboard.scala @@ -128,7 +128,7 @@ class Switchboard(nodeParams: NodeParams, peerFactory: Switchboard.PeerFactory) def createPeer(remoteNodeId: PublicKey): ActorRef = peerFactory.spawn(context, remoteNodeId) - def createOrGetPeer(remoteNodeId: PublicKey, offlineChannels: Set[HasCommitments]): ActorRef = { + def createOrGetPeer(remoteNodeId: PublicKey, offlineChannels: Set[PersistentChannelData]): ActorRef = { getPeer(remoteNodeId) match { case Some(peer) => peer case None => diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/payment/relay/PostRestartHtlcCleaner.scala b/eclair-core/src/main/scala/fr/acinq/eclair/payment/relay/PostRestartHtlcCleaner.scala index 6588c1e3b5..f40b4593b8 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/payment/relay/PostRestartHtlcCleaner.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/payment/relay/PostRestartHtlcCleaner.scala @@ -324,7 +324,7 @@ object PostRestartHtlcCleaner { } /** @return incoming HTLCs that have been *cross-signed* (that potentially have been relayed). */ - private def getIncomingHtlcs(channels: Seq[HasCommitments], paymentsDb: IncomingPaymentsDb, privateKey: PrivateKey)(implicit log: LoggingAdapter): Seq[IncomingHtlc] = { + private def getIncomingHtlcs(channels: Seq[PersistentChannelData], paymentsDb: IncomingPaymentsDb, privateKey: PrivateKey)(implicit log: LoggingAdapter): Seq[IncomingHtlc] = { // We are interested in incoming HTLCs, that have been *cross-signed* (otherwise they wouldn't have been relayed). // They signed it first, so the HTLC will first appear in our commitment tx, and later on in their commitment when // we subsequently sign it. That's why we need to look in *their* commitment with direction=OUT. @@ -356,7 +356,7 @@ object PostRestartHtlcCleaner { .toMap /** @return pending outgoing HTLCs, grouped by their upstream origin. */ - private def getHtlcsRelayedOut(channels: Seq[HasCommitments], htlcsIn: Seq[IncomingHtlc])(implicit log: LoggingAdapter): Map[Origin, Set[(ByteVector32, Long)]] = { + private def getHtlcsRelayedOut(channels: Seq[PersistentChannelData], htlcsIn: Seq[IncomingHtlc])(implicit log: LoggingAdapter): Map[Origin, Set[(ByteVector32, Long)]] = { val htlcsOut = channels .flatMap { c => // Filter out HTLCs that will never reach the blockchain or have already been timed-out on-chain. @@ -398,7 +398,7 @@ object PostRestartHtlcCleaner { * and before it has effectively been removed. Such closed channels will automatically be removed once the channel is * restored. */ - private def listLocalChannels(channelsDb: ChannelsDb): Seq[HasCommitments] = + private def listLocalChannels(channelsDb: ChannelsDb): Seq[PersistentChannelData] = channelsDb.listLocalChannels().filterNot(c => Closing.isClosed(c, None).isDefined) /** diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/wire/internal/channel/ChannelCodecs.scala b/eclair-core/src/main/scala/fr/acinq/eclair/wire/internal/channel/ChannelCodecs.scala index 6a8fb44bfb..d0b116072b 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/wire/internal/channel/ChannelCodecs.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/wire/internal/channel/ChannelCodecs.scala @@ -16,7 +16,7 @@ package fr.acinq.eclair.wire.internal.channel -import fr.acinq.eclair.channel.HasCommitments +import fr.acinq.eclair.channel.PersistentChannelData import fr.acinq.eclair.wire.internal.channel.version0.ChannelCodecs0 import fr.acinq.eclair.wire.internal.channel.version1.ChannelCodecs1 import fr.acinq.eclair.wire.internal.channel.version2.ChannelCodecs2 @@ -65,10 +65,10 @@ object ChannelCodecs extends Logging { * * More info here: https://github.com/scodec/scodec/issues/122 */ - val stateDataCodec: Codec[HasCommitments] = discriminated[HasCommitments].by(byte) - .typecase(3, ChannelCodecs3.stateDataCodec) - .typecase(2, ChannelCodecs2.stateDataCodec.decodeOnly) - .typecase(1, ChannelCodecs1.stateDataCodec.decodeOnly) - .typecase(0, ChannelCodecs0.stateDataCodec.decodeOnly) + val channelDataCodec: Codec[PersistentChannelData] = discriminated[PersistentChannelData].by(byte) + .typecase(3, ChannelCodecs3.channelDataCodec) + .typecase(2, ChannelCodecs2.channelDataCodec.decodeOnly) + .typecase(1, ChannelCodecs1.channelDataCodec.decodeOnly) + .typecase(0, ChannelCodecs0.channelDataCodec.decodeOnly) } diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/wire/internal/channel/version0/ChannelCodecs0.scala b/eclair-core/src/main/scala/fr/acinq/eclair/wire/internal/channel/version0/ChannelCodecs0.scala index 20f6828666..fe817ddf86 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/wire/internal/channel/version0/ChannelCodecs0.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/wire/internal/channel/version0/ChannelCodecs0.scala @@ -454,7 +454,7 @@ private[channel] object ChannelCodecs0 { } // Order matters! - val stateDataCodec: Codec[HasCommitments] = discriminated[HasCommitments].by(uint16) + val channelDataCodec: Codec[PersistentChannelData] = discriminated[PersistentChannelData].by(uint16) .typecase(0x10, Codecs.DATA_NORMAL_Codec) .typecase(0x09, Codecs.DATA_CLOSING_Codec) .typecase(0x08, Codecs.DATA_WAIT_FOR_FUNDING_CONFIRMED_Codec) diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/wire/internal/channel/version1/ChannelCodecs1.scala b/eclair-core/src/main/scala/fr/acinq/eclair/wire/internal/channel/version1/ChannelCodecs1.scala index 98acb81016..857dc5af38 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/wire/internal/channel/version1/ChannelCodecs1.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/wire/internal/channel/version1/ChannelCodecs1.scala @@ -286,7 +286,7 @@ private[channel] object ChannelCodecs1 { } // Order matters! - val stateDataCodec: Codec[HasCommitments] = discriminated[HasCommitments].by(uint16) + val channelDataCodec: Codec[PersistentChannelData] = discriminated[PersistentChannelData].by(uint16) .typecase(0x20, Codecs.DATA_WAIT_FOR_FUNDING_CONFIRMED_Codec) .typecase(0x21, Codecs.DATA_WAIT_FOR_FUNDING_LOCKED_Codec) .typecase(0x22, Codecs.DATA_NORMAL_Codec) diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/wire/internal/channel/version2/ChannelCodecs2.scala b/eclair-core/src/main/scala/fr/acinq/eclair/wire/internal/channel/version2/ChannelCodecs2.scala index 99e59338e5..ff4853a7ee 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/wire/internal/channel/version2/ChannelCodecs2.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/wire/internal/channel/version2/ChannelCodecs2.scala @@ -320,7 +320,7 @@ private[channel] object ChannelCodecs2 { ("remoteChannelReestablish" | channelReestablishCodec)).as[DATA_WAIT_FOR_REMOTE_PUBLISH_FUTURE_COMMITMENT] } - val stateDataCodec: Codec[HasCommitments] = discriminated[HasCommitments].by(uint16) + val channelDataCodec: Codec[PersistentChannelData] = discriminated[PersistentChannelData].by(uint16) .typecase(0x00, Codecs.DATA_WAIT_FOR_FUNDING_CONFIRMED_Codec) .typecase(0x01, Codecs.DATA_WAIT_FOR_FUNDING_LOCKED_Codec) .typecase(0x02, Codecs.DATA_NORMAL_Codec) diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/wire/internal/channel/version3/ChannelCodecs3.scala b/eclair-core/src/main/scala/fr/acinq/eclair/wire/internal/channel/version3/ChannelCodecs3.scala index bfd51eab6a..c7686b6af1 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/wire/internal/channel/version3/ChannelCodecs3.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/wire/internal/channel/version3/ChannelCodecs3.scala @@ -386,7 +386,7 @@ private[channel] object ChannelCodecs3 { } // Order matters! - val stateDataCodec: Codec[HasCommitments] = discriminated[HasCommitments].by(uint16) + val channelDataCodec: Codec[PersistentChannelData] = discriminated[PersistentChannelData].by(uint16) .typecase(0x08, Codecs.DATA_SHUTDOWN_Codec) .typecase(0x07, Codecs.DATA_NORMAL_Codec) .typecase(0x06, Codecs.DATA_WAIT_FOR_REMOTE_PUBLISH_FUTURE_COMMITMENT_Codec) diff --git a/eclair-core/src/test/scala/fr/acinq/eclair/TestDatabases.scala b/eclair-core/src/test/scala/fr/acinq/eclair/TestDatabases.scala index e626c06f7b..7b813fee70 100644 --- a/eclair-core/src/test/scala/fr/acinq/eclair/TestDatabases.scala +++ b/eclair-core/src/test/scala/fr/acinq/eclair/TestDatabases.scala @@ -56,7 +56,7 @@ object TestDatabases { * @param innerDb actual database instance */ class SqliteChannelsDbWithValidation(innerDb: SqliteChannelsDb) extends SqliteChannelsDb(innerDb.sqlite) { - override def addOrUpdateChannel(state: HasCommitments): Unit = { + override def addOrUpdateChannel(data: PersistentChannelData): Unit = { def freeze1(input: Origin): Origin = input match { case h: Origin.LocalHot => Origin.LocalCold(h.id) @@ -68,7 +68,7 @@ object TestDatabases { // payment origins are always "cold" when deserialized, so to compare a "live" channel state against a state that has been // serialized and deserialized we need to turn "hot" payments into cold ones - def freeze3(input: HasCommitments): HasCommitments = input match { + def freeze3(input: PersistentChannelData): PersistentChannelData = input match { case d: DATA_WAIT_FOR_FUNDING_CONFIRMED => d.copy(commitments = freeze2(d.commitments)) case d: DATA_WAIT_FOR_FUNDING_LOCKED => d.copy(commitments = freeze2(d.commitments)) case d: DATA_WAIT_FOR_REMOTE_PUBLISH_FUTURE_COMMITMENT => d.copy(commitments = freeze2(d.commitments)) @@ -78,9 +78,9 @@ object TestDatabases { case d: DATA_SHUTDOWN => d.copy(commitments = freeze2(d.commitments)) } - super.addOrUpdateChannel(state) - val check = super.getChannel(state.channelId) - val frozen = freeze3(state) + super.addOrUpdateChannel(data) + val check = super.getChannel(data.channelId) + val frozen = freeze3(data) require(check.contains(frozen), s"serialization/deserialization check failed, $check != $frozen") } } diff --git a/eclair-core/src/test/scala/fr/acinq/eclair/balance/CheckBalanceSpec.scala b/eclair-core/src/test/scala/fr/acinq/eclair/balance/CheckBalanceSpec.scala index 4eee5c59bd..a7c8305da9 100644 --- a/eclair-core/src/test/scala/fr/acinq/eclair/balance/CheckBalanceSpec.scala +++ b/eclair-core/src/test/scala/fr/acinq/eclair/balance/CheckBalanceSpec.scala @@ -12,7 +12,7 @@ import fr.acinq.eclair.channel.states.ChannelStateTestsBase import fr.acinq.eclair.channel.{CLOSING, CMD_SIGN, DATA_CLOSING, DATA_NORMAL} import fr.acinq.eclair.db.jdbc.JdbcUtils.ExtendedResultSet._ import fr.acinq.eclair.db.pg.PgUtils.using -import fr.acinq.eclair.wire.internal.channel.ChannelCodecs.stateDataCodec +import fr.acinq.eclair.wire.internal.channel.ChannelCodecs.channelDataCodec import fr.acinq.eclair.wire.protocol.{CommitSig, Error, RevokeAndAck} import fr.acinq.eclair.{BlockHeight, MilliSatoshiLong, TestConstants, TestKitBaseClass, ToMilliSatoshiConversion, randomBytes32} import org.scalatest.Outcome @@ -230,7 +230,7 @@ class CheckBalanceSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike with val sqlite = DriverManager.getConnection(s"jdbc:sqlite:$dbFile", sqliteConfig.toProperties) val channels = using(sqlite.createStatement) { statement => statement.executeQuery("SELECT data FROM local_channels WHERE is_closed=0") - .mapCodec(stateDataCodec) + .mapCodec(channelDataCodec) } val knownPreimages: Set[(ByteVector32, Long)] = using(sqlite.prepareStatement("SELECT channel_id, htlc_id FROM pending_relay")) { statement => val rs = statement.executeQuery() diff --git a/eclair-core/src/test/scala/fr/acinq/eclair/channel/RestoreSpec.scala b/eclair-core/src/test/scala/fr/acinq/eclair/channel/RestoreSpec.scala index a749e0ea0b..92f133cada 100644 --- a/eclair-core/src/test/scala/fr/acinq/eclair/channel/RestoreSpec.scala +++ b/eclair-core/src/test/scala/fr/acinq/eclair/channel/RestoreSpec.scala @@ -50,7 +50,7 @@ class RestoreSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike with Chan val sender = TestProbe() // we start by storing the current state - val oldStateData = alice.stateData.asInstanceOf[HasCommitments] + val oldStateData = alice.stateData.asInstanceOf[PersistentChannelData] // then we add an htlc and sign it addHtlc(250000000 msat, alice, bob, alice2bob, bob2alice) sender.send(alice, CMD_SIGN()) diff --git a/eclair-core/src/test/scala/fr/acinq/eclair/channel/states/ChannelStateTestsHelperMethods.scala b/eclair-core/src/test/scala/fr/acinq/eclair/channel/states/ChannelStateTestsHelperMethods.scala index cd98aed03e..31444f0cad 100644 --- a/eclair-core/src/test/scala/fr/acinq/eclair/channel/states/ChannelStateTestsHelperMethods.scala +++ b/eclair-core/src/test/scala/fr/acinq/eclair/channel/states/ChannelStateTestsHelperMethods.scala @@ -273,7 +273,7 @@ trait ChannelStateTestsHelperMethods extends TestKitBase { s ! cmdAdd val htlc = s2r.expectMsgType[UpdateAddHtlc] s2r.forward(r) - awaitCond(r.stateData.asInstanceOf[HasCommitments].commitments.remoteChanges.proposed.contains(htlc)) + awaitCond(r.stateData.asInstanceOf[PersistentChannelData].commitments.remoteChanges.proposed.contains(htlc)) htlc } @@ -281,21 +281,21 @@ trait ChannelStateTestsHelperMethods extends TestKitBase { s ! CMD_FULFILL_HTLC(id, preimage) val fulfill = s2r.expectMsgType[UpdateFulfillHtlc] s2r.forward(r) - awaitCond(r.stateData.asInstanceOf[HasCommitments].commitments.remoteChanges.proposed.contains(fulfill)) + awaitCond(r.stateData.asInstanceOf[PersistentChannelData].commitments.remoteChanges.proposed.contains(fulfill)) } def failHtlc(id: Long, s: TestFSMRef[ChannelState, ChannelData, Channel], r: TestFSMRef[ChannelState, ChannelData, Channel], s2r: TestProbe, r2s: TestProbe): Unit = { s ! CMD_FAIL_HTLC(id, Right(TemporaryNodeFailure)) val fail = s2r.expectMsgType[UpdateFailHtlc] s2r.forward(r) - awaitCond(r.stateData.asInstanceOf[HasCommitments].commitments.remoteChanges.proposed.contains(fail)) + awaitCond(r.stateData.asInstanceOf[PersistentChannelData].commitments.remoteChanges.proposed.contains(fail)) } def crossSign(s: TestFSMRef[ChannelState, ChannelData, Channel], r: TestFSMRef[ChannelState, ChannelData, Channel], s2r: TestProbe, r2s: TestProbe): Unit = { val sender = TestProbe() - val sCommitIndex = s.stateData.asInstanceOf[HasCommitments].commitments.localCommit.index - val rCommitIndex = r.stateData.asInstanceOf[HasCommitments].commitments.localCommit.index - val rHasChanges = Commitments.localHasChanges(r.stateData.asInstanceOf[HasCommitments].commitments) + val sCommitIndex = s.stateData.asInstanceOf[PersistentChannelData].commitments.localCommit.index + val rCommitIndex = r.stateData.asInstanceOf[PersistentChannelData].commitments.localCommit.index + val rHasChanges = Commitments.localHasChanges(r.stateData.asInstanceOf[PersistentChannelData].commitments) s ! CMD_SIGN(Some(sender.ref)) sender.expectMsgType[RES_SUCCESS[CMD_SIGN]] s2r.expectMsgType[CommitSig] @@ -311,15 +311,15 @@ trait ChannelStateTestsHelperMethods extends TestKitBase { s2r.forward(r) r2s.expectMsgType[RevokeAndAck] r2s.forward(s) - awaitCond(s.stateData.asInstanceOf[HasCommitments].commitments.localCommit.index == sCommitIndex + 1) - awaitCond(s.stateData.asInstanceOf[HasCommitments].commitments.remoteCommit.index == sCommitIndex + 2) - awaitCond(r.stateData.asInstanceOf[HasCommitments].commitments.localCommit.index == rCommitIndex + 2) - awaitCond(r.stateData.asInstanceOf[HasCommitments].commitments.remoteCommit.index == rCommitIndex + 1) + awaitCond(s.stateData.asInstanceOf[PersistentChannelData].commitments.localCommit.index == sCommitIndex + 1) + awaitCond(s.stateData.asInstanceOf[PersistentChannelData].commitments.remoteCommit.index == sCommitIndex + 2) + awaitCond(r.stateData.asInstanceOf[PersistentChannelData].commitments.localCommit.index == rCommitIndex + 2) + awaitCond(r.stateData.asInstanceOf[PersistentChannelData].commitments.remoteCommit.index == rCommitIndex + 1) } else { - awaitCond(s.stateData.asInstanceOf[HasCommitments].commitments.localCommit.index == sCommitIndex + 1) - awaitCond(s.stateData.asInstanceOf[HasCommitments].commitments.remoteCommit.index == sCommitIndex + 1) - awaitCond(r.stateData.asInstanceOf[HasCommitments].commitments.localCommit.index == rCommitIndex + 1) - awaitCond(r.stateData.asInstanceOf[HasCommitments].commitments.remoteCommit.index == rCommitIndex + 1) + awaitCond(s.stateData.asInstanceOf[PersistentChannelData].commitments.localCommit.index == sCommitIndex + 1) + awaitCond(s.stateData.asInstanceOf[PersistentChannelData].commitments.remoteCommit.index == sCommitIndex + 1) + awaitCond(r.stateData.asInstanceOf[PersistentChannelData].commitments.localCommit.index == rCommitIndex + 1) + awaitCond(r.stateData.asInstanceOf[PersistentChannelData].commitments.remoteCommit.index == rCommitIndex + 1) } } @@ -335,7 +335,7 @@ trait ChannelStateTestsHelperMethods extends TestKitBase { r2s.forward(s) s2r.expectMsgType[RevokeAndAck] s2r.forward(r) - awaitCond(s.stateData.asInstanceOf[HasCommitments].commitments.localCommit.spec.commitTxFeerate == feerate) + awaitCond(s.stateData.asInstanceOf[PersistentChannelData].commitments.localCommit.spec.commitTxFeerate == feerate) } def mutualClose(s: TestFSMRef[ChannelState, ChannelData, Channel], r: TestFSMRef[ChannelState, ChannelData, Channel], s2r: TestProbe, r2s: TestProbe, s2blockchain: TestProbe, r2blockchain: TestProbe): Unit = { diff --git a/eclair-core/src/test/scala/fr/acinq/eclair/channel/states/e/NormalStateSpec.scala b/eclair-core/src/test/scala/fr/acinq/eclair/channel/states/e/NormalStateSpec.scala index dc2c406abb..a7f5c7b736 100644 --- a/eclair-core/src/test/scala/fr/acinq/eclair/channel/states/e/NormalStateSpec.scala +++ b/eclair-core/src/test/scala/fr/acinq/eclair/channel/states/e/NormalStateSpec.scala @@ -2750,7 +2750,7 @@ class NormalStateSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike with bob2alice.expectMsgType[CommitSig] bob ! CurrentBlockHeight(htlc.cltvExpiry.blockHeight - Bob.nodeParams.channelConf.fulfillSafetyBeforeTimeout.toInt) - val ChannelErrorOccurred(_, _, _, _, LocalError(err), isFatal) = listener.expectMsgType[ChannelErrorOccurred] + val ChannelErrorOccurred(_, _, _, LocalError(err), isFatal) = listener.expectMsgType[ChannelErrorOccurred] assert(isFatal) assert(err.isInstanceOf[HtlcsWillTimeoutUpstream]) @@ -2783,7 +2783,7 @@ class NormalStateSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike with bob2alice.expectNoMessage(500 millis) bob ! CurrentBlockHeight(htlc.cltvExpiry.blockHeight - Bob.nodeParams.channelConf.fulfillSafetyBeforeTimeout.toInt) - val ChannelErrorOccurred(_, _, _, _, LocalError(err), isFatal) = listener.expectMsgType[ChannelErrorOccurred] + val ChannelErrorOccurred(_, _, _, LocalError(err), isFatal) = listener.expectMsgType[ChannelErrorOccurred] assert(isFatal) assert(err.isInstanceOf[HtlcsWillTimeoutUpstream]) @@ -2820,7 +2820,7 @@ class NormalStateSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike with alice2bob.forward(bob) bob ! CurrentBlockHeight(htlc.cltvExpiry.blockHeight - Bob.nodeParams.channelConf.fulfillSafetyBeforeTimeout.toInt) - val ChannelErrorOccurred(_, _, _, _, LocalError(err), isFatal) = listener.expectMsgType[ChannelErrorOccurred] + val ChannelErrorOccurred(_, _, _, LocalError(err), isFatal) = listener.expectMsgType[ChannelErrorOccurred] assert(isFatal) assert(err.isInstanceOf[HtlcsWillTimeoutUpstream]) diff --git a/eclair-core/src/test/scala/fr/acinq/eclair/channel/states/e/OfflineStateSpec.scala b/eclair-core/src/test/scala/fr/acinq/eclair/channel/states/e/OfflineStateSpec.scala index 0a57a6e8ad..c467c5d6ca 100644 --- a/eclair-core/src/test/scala/fr/acinq/eclair/channel/states/e/OfflineStateSpec.scala +++ b/eclair-core/src/test/scala/fr/acinq/eclair/channel/states/e/OfflineStateSpec.scala @@ -540,7 +540,7 @@ class OfflineStateSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike with bob.underlyingActor.nodeParams.db.pendingCommands.addSettlementCommand(initialState.channelId, CMD_FULFILL_HTLC(htlc.id, r, commit = true)) bob ! CurrentBlockHeight(htlc.cltvExpiry.blockHeight - bob.underlyingActor.nodeParams.channelConf.fulfillSafetyBeforeTimeout.toInt) - val ChannelErrorOccurred(_, _, _, _, LocalError(err), isFatal) = listener.expectMsgType[ChannelErrorOccurred] + val ChannelErrorOccurred(_, _, _, LocalError(err), isFatal) = listener.expectMsgType[ChannelErrorOccurred] assert(isFatal) assert(err.isInstanceOf[HtlcsWillTimeoutUpstream]) @@ -787,12 +787,12 @@ class OfflineStateSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike with alice ! INPUT_RECONNECTED(alice2bob.ref, aliceInit, bobInit) bob ! INPUT_RECONNECTED(bob2alice.ref, bobInit, aliceInit) - val aliceCommitments = alice.stateData.asInstanceOf[HasCommitments].commitments + val aliceCommitments = alice.stateData.asInstanceOf[PersistentChannelData].commitments val aliceCurrentPerCommitmentPoint = TestConstants.Alice.channelKeyManager.commitmentPoint( TestConstants.Alice.channelKeyManager.keyPath(aliceCommitments.localParams, aliceCommitments.channelConfig), aliceCommitments.localCommit.index) - val bobCommitments = bob.stateData.asInstanceOf[HasCommitments].commitments + val bobCommitments = bob.stateData.asInstanceOf[PersistentChannelData].commitments val bobCurrentPerCommitmentPoint = TestConstants.Bob.channelKeyManager.commitmentPoint( TestConstants.Bob.channelKeyManager.keyPath(bobCommitments.localParams, bobCommitments.channelConfig), bobCommitments.localCommit.index) diff --git a/eclair-core/src/test/scala/fr/acinq/eclair/channel/states/g/NegotiatingStateSpec.scala b/eclair-core/src/test/scala/fr/acinq/eclair/channel/states/g/NegotiatingStateSpec.scala index f7231d81d5..075e3274c5 100644 --- a/eclair-core/src/test/scala/fr/acinq/eclair/channel/states/g/NegotiatingStateSpec.scala +++ b/eclair-core/src/test/scala/fr/acinq/eclair/channel/states/g/NegotiatingStateSpec.scala @@ -62,11 +62,11 @@ class NegotiatingStateSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike val bobShutdown = bob2alice.expectMsgType[Shutdown] bob2alice.forward(alice, bobShutdown) awaitCond(alice.stateName == NEGOTIATING) - if (alice.stateData.asInstanceOf[HasCommitments].commitments.channelFeatures.hasFeature(Features.UpfrontShutdownScript)) { + if (alice.stateData.asInstanceOf[PersistentChannelData].commitments.channelFeatures.hasFeature(Features.UpfrontShutdownScript)) { assert(aliceShutdown.scriptPubKey == alice.stateData.asInstanceOf[DATA_NEGOTIATING].commitments.localParams.defaultFinalScriptPubKey) } awaitCond(bob.stateName == NEGOTIATING) - if (bob.stateData.asInstanceOf[HasCommitments].commitments.channelFeatures.hasFeature(Features.UpfrontShutdownScript)) { + if (bob.stateData.asInstanceOf[PersistentChannelData].commitments.channelFeatures.hasFeature(Features.UpfrontShutdownScript)) { assert(bobShutdown.scriptPubKey == bob.stateData.asInstanceOf[DATA_NEGOTIATING].commitments.localParams.defaultFinalScriptPubKey) } } @@ -81,11 +81,11 @@ class NegotiatingStateSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike val aliceShutdown = alice2bob.expectMsgType[Shutdown] alice2bob.forward(bob, aliceShutdown) awaitCond(alice.stateName == NEGOTIATING) - if (alice.stateData.asInstanceOf[HasCommitments].commitments.channelFeatures.hasFeature(Features.UpfrontShutdownScript)) { + if (alice.stateData.asInstanceOf[PersistentChannelData].commitments.channelFeatures.hasFeature(Features.UpfrontShutdownScript)) { assert(aliceShutdown.scriptPubKey == alice.stateData.asInstanceOf[DATA_NEGOTIATING].commitments.localParams.defaultFinalScriptPubKey) } awaitCond(bob.stateName == NEGOTIATING) - if (bob.stateData.asInstanceOf[HasCommitments].commitments.channelFeatures.hasFeature(Features.UpfrontShutdownScript)) { + if (bob.stateData.asInstanceOf[PersistentChannelData].commitments.channelFeatures.hasFeature(Features.UpfrontShutdownScript)) { assert(bobShutdown.scriptPubKey == bob.stateData.asInstanceOf[DATA_NEGOTIATING].commitments.localParams.defaultFinalScriptPubKey) } } diff --git a/eclair-core/src/test/scala/fr/acinq/eclair/channel/states/h/ClosingStateSpec.scala b/eclair-core/src/test/scala/fr/acinq/eclair/channel/states/h/ClosingStateSpec.scala index 1ae8baa91b..933cd79311 100644 --- a/eclair-core/src/test/scala/fr/acinq/eclair/channel/states/h/ClosingStateSpec.scala +++ b/eclair-core/src/test/scala/fr/acinq/eclair/channel/states/h/ClosingStateSpec.scala @@ -1613,7 +1613,7 @@ class ClosingStateSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike with import f._ mutualClose(alice, bob, alice2bob, bob2alice, alice2blockchain, bob2blockchain) val initialState = alice.stateData.asInstanceOf[DATA_CLOSING] - val bobCommitments = bob.stateData.asInstanceOf[HasCommitments].commitments + val bobCommitments = bob.stateData.asInstanceOf[PersistentChannelData].commitments val bobCurrentPerCommitmentPoint = TestConstants.Bob.channelKeyManager.commitmentPoint( TestConstants.Bob.channelKeyManager.keyPath(bobCommitments.localParams, bobCommitments.channelConfig), bobCommitments.localCommit.index) diff --git a/eclair-core/src/test/scala/fr/acinq/eclair/db/AuditDbSpec.scala b/eclair-core/src/test/scala/fr/acinq/eclair/db/AuditDbSpec.scala index 8261aa986b..cd57224c02 100644 --- a/eclair-core/src/test/scala/fr/acinq/eclair/db/AuditDbSpec.scala +++ b/eclair-core/src/test/scala/fr/acinq/eclair/db/AuditDbSpec.scala @@ -77,8 +77,8 @@ class AuditDbSpec extends AnyFunSuite { val pp6 = PaymentSent.PartialPayment(UUID.randomUUID(), 42000 msat, 1000 msat, randomBytes32(), None, timestamp = TimestampMilli.now() + 10.minutes) val e6 = PaymentSent(UUID.randomUUID(), randomBytes32(), randomBytes32(), 42000 msat, randomKey().publicKey, pp6 :: Nil) val e7 = ChannelEvent(randomBytes32(), randomKey().publicKey, 456123000 sat, isFunder = true, isPrivate = false, ChannelEvent.EventType.Closed(MutualClose(null))) - val e8 = ChannelErrorOccurred(null, randomBytes32(), randomKey().publicKey, null, LocalError(new RuntimeException("oops")), isFatal = true) - val e9 = ChannelErrorOccurred(null, randomBytes32(), randomKey().publicKey, null, RemoteError(Error(randomBytes32(), "remote oops")), isFatal = true) + val e8 = ChannelErrorOccurred(null, randomBytes32(), randomKey().publicKey, LocalError(new RuntimeException("oops")), isFatal = true) + val e9 = ChannelErrorOccurred(null, randomBytes32(), randomKey().publicKey, RemoteError(Error(randomBytes32(), "remote oops")), isFatal = true) val e10 = TrampolinePaymentRelayed(randomBytes32(), Seq(PaymentRelayed.Part(20000 msat, randomBytes32()), PaymentRelayed.Part(22000 msat, randomBytes32())), Seq(PaymentRelayed.Part(10000 msat, randomBytes32()), PaymentRelayed.Part(12000 msat, randomBytes32()), PaymentRelayed.Part(15000 msat, randomBytes32())), randomKey().publicKey, 30000 msat) val multiPartPaymentHash = randomBytes32() val now = TimestampMilli.now() @@ -208,8 +208,8 @@ class AuditDbSpec extends AnyFunSuite { val pp1 = PaymentSent.PartialPayment(UUID.randomUUID(), 42001 msat, 1001 msat, randomBytes32(), None) val pp2 = PaymentSent.PartialPayment(UUID.randomUUID(), 42002 msat, 1002 msat, randomBytes32(), None) val ps1 = PaymentSent(UUID.randomUUID(), randomBytes32(), randomBytes32(), 84003 msat, PrivateKey(ByteVector32.One).publicKey, pp1 :: pp2 :: Nil) - val e1 = ChannelErrorOccurred(null, randomBytes32(), randomKey().publicKey, null, LocalError(new RuntimeException("oops")), isFatal = true) - val e2 = ChannelErrorOccurred(null, randomBytes32(), randomKey().publicKey, null, RemoteError(Error(randomBytes32(), "remote oops")), isFatal = true) + val e1 = ChannelErrorOccurred(null, randomBytes32(), randomKey().publicKey, LocalError(new RuntimeException("oops")), isFatal = true) + val e2 = ChannelErrorOccurred(null, randomBytes32(), randomKey().publicKey, RemoteError(Error(randomBytes32(), "remote oops")), isFatal = true) migrationCheck( dbs = dbs, @@ -270,8 +270,8 @@ class AuditDbSpec extends AnyFunSuite { test("migrate sqlite audit database v2 -> current") { val dbs = TestSqliteDatabases() - val e1 = ChannelErrorOccurred(null, randomBytes32(), randomKey().publicKey, null, LocalError(new RuntimeException("oops")), isFatal = true) - val e2 = ChannelErrorOccurred(null, randomBytes32(), randomKey().publicKey, null, RemoteError(Error(randomBytes32(), "remote oops")), isFatal = true) + val e1 = ChannelErrorOccurred(null, randomBytes32(), randomKey().publicKey, LocalError(new RuntimeException("oops")), isFatal = true) + val e2 = ChannelErrorOccurred(null, randomBytes32(), randomKey().publicKey, RemoteError(Error(randomBytes32(), "remote oops")), isFatal = true) migrationCheck( dbs = dbs, diff --git a/eclair-core/src/test/scala/fr/acinq/eclair/db/ChannelsDbSpec.scala b/eclair-core/src/test/scala/fr/acinq/eclair/db/ChannelsDbSpec.scala index d8f519eb3a..871adad0d6 100644 --- a/eclair-core/src/test/scala/fr/acinq/eclair/db/ChannelsDbSpec.scala +++ b/eclair-core/src/test/scala/fr/acinq/eclair/db/ChannelsDbSpec.scala @@ -26,7 +26,7 @@ import fr.acinq.eclair.db.pg.PgUtils.{getVersion, setVersion} import fr.acinq.eclair.db.pg.{PgChannelsDb, PgUtils} import fr.acinq.eclair.db.sqlite.SqliteChannelsDb import fr.acinq.eclair.db.sqlite.SqliteUtils.ExtendedResultSet._ -import fr.acinq.eclair.wire.internal.channel.ChannelCodecs.stateDataCodec +import fr.acinq.eclair.wire.internal.channel.ChannelCodecs.channelDataCodec import fr.acinq.eclair.wire.internal.channel.ChannelCodecsSpec import fr.acinq.eclair.{CltvExpiry, ShortChannelId, TestDatabases, randomBytes32} import org.scalatest.funsuite.AnyFunSuite @@ -362,7 +362,7 @@ object ChannelsDbSpec { val testCases: Seq[TestCase] = for (_ <- 0 until 10) yield { val channelId = randomBytes32() - val data = stateDataCodec.encode(ChannelCodecsSpec.normal.modify(_.commitments.channelId).setTo(channelId)).require.bytes + val data = channelDataCodec.encode(ChannelCodecsSpec.normal.modify(_.commitments.channelId).setTo(channelId)).require.bytes TestCase( channelId = channelId, data = data, diff --git a/eclair-core/src/test/scala/fr/acinq/eclair/integration/ChannelIntegrationSpec.scala b/eclair-core/src/test/scala/fr/acinq/eclair/integration/ChannelIntegrationSpec.scala index 33d6641be4..383083091c 100644 --- a/eclair-core/src/test/scala/fr/acinq/eclair/integration/ChannelIntegrationSpec.scala +++ b/eclair-core/src/test/scala/fr/acinq/eclair/integration/ChannelIntegrationSpec.scala @@ -492,7 +492,7 @@ class StandardChannelIntegrationSpec extends ChannelIntegrationSpec { val Some((_, fundeeChannel)) = sender.expectMsgType[Map[ByteVector32, ActorRef]].find(_._1 == tempChannelId) sender.send(fundeeChannel, CMD_GETSTATEDATA(ActorRef.noSender)) - val channelId = sender.expectMsgType[RES_GETSTATEDATA[HasCommitments]].data.channelId + val channelId = sender.expectMsgType[RES_GETSTATEDATA[PersistentChannelData]].data.channelId awaitCond({ funder.register ! Register.Forward(sender.ref, channelId, CMD_GETSTATE(ActorRef.noSender)) sender.expectMsgType[RES_GETSTATE[_]].state == WAIT_FOR_FUNDING_LOCKED diff --git a/eclair-core/src/test/scala/fr/acinq/eclair/io/PeerSpec.scala b/eclair-core/src/test/scala/fr/acinq/eclair/io/PeerSpec.scala index 1fa21cf749..8f998f0a34 100644 --- a/eclair-core/src/test/scala/fr/acinq/eclair/io/PeerSpec.scala +++ b/eclair-core/src/test/scala/fr/acinq/eclair/io/PeerSpec.scala @@ -86,7 +86,7 @@ class PeerSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike with Paralle withFixture(test.toNoArgTest(FixtureParam(aliceParams, remoteNodeId, peer, peerConnection, channel, switchboard))) } - def connect(remoteNodeId: PublicKey, peer: TestFSMRef[Peer.State, Peer.Data, Peer], peerConnection: TestProbe, switchboard: TestProbe, channels: Set[HasCommitments] = Set.empty, remoteInit: protocol.Init = protocol.Init(Bob.nodeParams.features.initFeatures())): Unit = { + def connect(remoteNodeId: PublicKey, peer: TestFSMRef[Peer.State, Peer.Data, Peer], peerConnection: TestProbe, switchboard: TestProbe, channels: Set[PersistentChannelData] = Set.empty, remoteInit: protocol.Init = protocol.Init(Bob.nodeParams.features.initFeatures())): Unit = { // let's simulate a connection switchboard.send(peer, Peer.Init(channels)) val localInit = protocol.Init(peer.underlyingActor.nodeParams.features.initFeatures()) diff --git a/eclair-core/src/test/scala/fr/acinq/eclair/json/JsonSerializersSpec.scala b/eclair-core/src/test/scala/fr/acinq/eclair/json/JsonSerializersSpec.scala index c88ffd2a43..6cdb9554cf 100644 --- a/eclair-core/src/test/scala/fr/acinq/eclair/json/JsonSerializersSpec.scala +++ b/eclair-core/src/test/scala/fr/acinq/eclair/json/JsonSerializersSpec.scala @@ -276,11 +276,11 @@ class JsonSerializersSpec extends AnyFunSuite with Matchers { val dataNegotiating = hex"0100240000000703af0ed6052cf28d670665549bc86f4b721c9fdb309d40c58f5811f63966e005d0000928544434bbbda1da0790cf138ef4b3881f5cec34b933ab77ffd57a7e12992bf780000001000000000000044c0000000008f0d1800000000000002710000000000000000000900064ff1600140cbd801be794f9854b38981ee859e3a000ad104c0000186b0200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000229a82039dc0e0b1d25905e44fdf6f8e89755a5e219685840d0bc1d28d3308f9628a358500000000000003e8ffffffffffffffff0000000000004e2000000000000003e80090001e0234ea57c6a0d7308e0479811f0315df88650da7a8af626fb6ceb9a6b3e1bf068e032f5bf3637d4efa39b50a7bad5e3f6d32663a1cc207a166155f00f8b9a9f621cc026b8899cafac94bcfee408aecfec60e86a30082b0ea587d8a7ab6b2b309fc66110210996c2725e4129dad191f6c6d9ba8c35ab58df4d340051d7025d366423aa15703bf59f021a7431277a31a53b2101bd3ff5730adefeae596020e58c9099728b7f000000003229a820000000000000000000000000009c4000000002faf0800000000000bebc2002424d4fd09fbcbde0363fda5d43c8bc68cea396aa1edd3d48d118ec27bb30fd1d5000000002b40420f0000000000220020552fd9e112e447f57c95b896d384461ee713c8108894ced2ea1272e0d354aab74752210234ea57c6a0d7308e0479811f0315df88650da7a8af626fb6ceb9a6b3e1bf068e2103d45fea036aa6817a71387c3976790beeb4705739d4cf0271007043854dde877552aefd01bc0200000000010124d4fd09fbcbde0363fda5d43c8bc68cea396aa1edd3d48d118ec27bb30fd1d50000000000c089a180044a010000000000002200207ba66732d8b8e8863cbdcad193c4602b54df24f9af202a977e3a6315e85072704a01000000000000220020f25aee697436b14ebdc0bdab0b3a0c339c98e49cd6a8b84fbfb84c7c5557aad1400d030000000000220020a659aeaecad3be965ed5a498adac881967d2d3ed2a773019da1b26337c7d0d1372270c000000000022002095c2df1035ebb714a728a166d88332e1569b3da5c035037df1bc07e227b7e1ec040047304402205837856dc4bc8f4a679015460580c38a29899986f6cca09afe3525097dcef36702201b2abd6fdbfa890e247cbe6a096bb01f3d47901a552f7f5e5c6ecb6c80a07d1701483045022100abfa35999608ea0c993418f7d432c7f9710b993f4eb45e17fbb95e10c6899e190220542593d102382a92a11eac65bef87a75742ee4447abebb38fc47c4d27d74f9a2014752210234ea57c6a0d7308e0479811f0315df88650da7a8af626fb6ceb9a6b3e1bf068e2103d45fea036aa6817a71387c3976790beeb4705739d4cf0271007043854dde877552ae68075c20000000000000000000000000000009c4000000000bebc200000000002faf080054b02aad4844030f2e1c3c61f95b34df8d14c0fdbddbe5d56090667016ca8979033d0000a1e29b94b3517a04106dc7bb74f4f091a2ee419d889ecf8434bcfdf127000000000000000000000000000000000000000000000000000000000000ff03228da9a93e02211af77afa576b94f57d747099099f5352298d8b3c4dbc7215c62424d4fd09fbcbde0363fda5d43c8bc68cea396aa1edd3d48d118ec27bb30fd1d5000000002b40420f0000000000220020552fd9e112e447f57c95b896d384461ee713c8108894ced2ea1272e0d354aab74752210234ea57c6a0d7308e0479811f0315df88650da7a8af626fb6ceb9a6b3e1bf068e2103d45fea036aa6817a71387c3976790beeb4705739d4cf0271007043854dde877552ae00000024d4fd09fbcbde0363fda5d43c8bc68cea396aa1edd3d48d118ec27bb30fd1d53824d4fd09fbcbde0363fda5d43c8bc68cea396aa1edd3d48d118ec27bb30fd1d5001600140cbd801be794f9854b38981ee859e3a000ad104c3824d4fd09fbcbde0363fda5d43c8bc68cea396aa1edd3d48d118ec27bb30fd1d50016001458043e6e40996eb9d3c77752a81398115ec43d5900010002db71020000000124d4fd09fbcbde0363fda5d43c8bc68cea396aa1edd3d48d118ec27bb30fd1d50000000000ffffffff02400d03000000000016001458043e6e40996eb9d3c77752a81398115ec43d59ac1a0c00000000001600140cbd801be794f9854b38981ee859e3a000ad104c000000006824d4fd09fbcbde0363fda5d43c8bc68cea396aa1edd3d48d118ec27bb30fd1d50000000000001a54fa574848f29f143c52f2717510e2a8831afaf7752217ce3452c7e88d24eb14905191e04229fc6433aef69bc33f9f2f6eb3c841fee628f7c583b9efe5a149aa47db71020000000124d4fd09fbcbde0363fda5d43c8bc68cea396aa1edd3d48d118ec27bb30fd1d50000000000ffffffff02400d03000000000016001458043e6e40996eb9d3c77752a81398115ec43d59f81d0c00000000001600140cbd801be794f9854b38981ee859e3a000ad104c000000006824d4fd09fbcbde0363fda5d43c8bc68cea396aa1edd3d48d118ec27bb30fd1d50000000000001708fc4039310f093081478d723e70b6bb1f17aa925472ccef2f79057aafce602726039f88ed9a0eb0841c61c39a5c224516288a81a53256693588f5af97e9e76c88fffd014e0200000000010124d4fd09fbcbde0363fda5d43c8bc68cea396aa1edd3d48d118ec27bb30fd1d50000000000ffffffff02400d03000000000016001458043e6e40996eb9d3c77752a81398115ec43d5942210c00000000001600140cbd801be794f9854b38981ee859e3a000ad104c0400483045022100ced76c39d6c63a52374b17103eba46ac6d21b5f5e427d48ffcd5e505a26477b90220588f30b94c0938632bcee8cfe9bc185325b2edde88c85fb4d226eda215abf26b01473044022042741816de3767e7b54fc1cdf94b6f0072203daf76c01ba5abb120801965413b02205237d5f3978b2332aa14ce65501fa784f51ea4e97030d44536f52f188f768074014752210234ea57c6a0d7308e0479811f0315df88650da7a8af626fb6ceb9a6b3e1bf068e2103d45fea036aa6817a71387c3976790beeb4705739d4cf0271007043854dde877552ae00000000" val dataClosingLocal = hex"0100250000000103af0ed6052cf28d670665549bc86f4b721c9fdb309d40c58f5811f63966e005d0000948d8efaf118cae9f142433a624b41a9ef7e09327fa45083ebd7694e1a61c429980000001000000000000044c0000000008f0d1800000000000002710000000000000000000900064ff16001401396601573e7aef81f91a89fc4b4b56feb7a35e0000186b0200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000028a82039dc0e0b1d25905e44fdf6f8e89755a5e219685840d0bc1d28d3308f9628a358500000000000003e8ffffffffffffffff0000000000004e2000000000000003e80090001e03174f3de90105ae02d88ccc1a7ed4bf0d116f27ef6010f1ec308273c1010ae3dc02fc17b2289973a29fd374ee24671d5d9643465a11bd725bac1d640b56493bd8f702b5460ae3379bc8a92d2aa2488f3e55a73d8909695e677beddd61a94d3655490f0357a1a37c3ae33b2a94bca0b6ae541036c22feeca86860c7c5501153ccfffd585028fb43c64d53c5d891bb0af3b7ed41acf3ebb0de59599b3e7836a8401645cb6e000000003028a82000000000000000007000500fd05aa0a007eacf337b3a80941f2defd530cf824f13cd263ba2ca194e7170072ce28e8000000000000000400000000017d784077c3e8caa53f1a775a5e89b1a54488aff835593d5e2b7355179136bbdd10a86c00061b1000020b7604aeb7cb080b12de62f75a292bed3134b4a3de764bd032fb049e2c2a1d3942cc11b9b12619d42cda3c7eb63da952644a3f355bdf772d77f1fc2a0b36bf116cdacfcda3b77974536cc3f3d0f8209dba69408073cbe0f039eba220fcf3b0b96d5875bb71acdc999fd9feeab68a0b63629efe0dc91e92dcf93b3c49285c981746a68ead7a96a9c1ce21284a2796b0051e6b7cf36a264d545063c054454b87cc3f9ddad5350382585de18cdc4e65e02484695f541b8fc082c87ea4a56aabc84fd1b7c1cd40e3517ae811f9ff921fba672e0191c88a2681ef8ea1300eeb6c1d8fccdb5ab05bf80b2a5c3ed5c018752cc841305edae02149389bc5e58ea5a59a1c59755c7ab5f35e3740c9f6218d227370363a7e386b214f5b2e771ea8b94a2a5e640d8a715d57756665f4a659f4ef6488f9ceab5e22d523ee52da368701d799fcb3459a31e6fb03de91ffd9b608656b172945015da3e5000f7f6c3dc0b4e102ba5f101bab5c2ceab8021d071bf89cf9d65d2439fe9a9dea4291eccb43a431904313655391ace4b82bf5da6270eb5bc12a60a69e7cf96b75a699db5a374713558eff7101bb2d8471e0c4ad0e202fd10aa46098bd5565c1d410e695fdd799c866090f1a7aa002305388acb68c8d82d588c1a66df5fb12653686bc4cf487a3484c0c23578a428de3df57539ed11227f2648bc36261c7f3f4f13e18d238dc856b8dd8f07de9fb73663d3a0026a03d9ee9f807e2a03c9546d2537a1f30a1f06767622d8bacdf4ab3b0f245a7b4f482baa60080fce3e7e15d2e086c670d6ec11d907e3da593977c8c25d620ed40cf82dd503c25f1a5f3e8a5ddb65ae7117600794844252e1448d17849028bd5df960a5fddf56e48cf082cfbc5c29666bca6af335c06f8240912a311e6c07946eeea9ef57e46b3e48b95c82cbee3830bf2b55d5e0223b9480fe072729a8af4c6c8c2f86038cb8a2e02405ce5f834c87b241fcb9963f008c273c64bc1f7289cc3a0c5eea7ea1a6dc7bc6228a97978a2ddd7dc49303c5beb15b36c8044f656716cad0a62d1e8c381db46f007be7f8096f72d3a8f08d338d9f2bbc43c0244215df229824a9ad34b655d840b38c5061462d54358be1c184b51d3a805beeea78047f544b15cc333d591f3d8cb60cbdd78e58ed47d21739762957ed6365fea14d7ba8368371fe4333be4f5ae289ff444c9f377a072a3a4173bd2680c6d6074743908d9c4f09aa30d064c7866a7a34303fce53deba6a597a24c211d209815bbff97736ba9fc79e390b36b2343d2590c8fd6db3e54206580eb7a53b9de09a42cfaa2cffb00ea90dbd07f1d357e69ca96fbba4efefc4e07b1a1a174a9a8a5568c0ec9a9487add3890a20391eebd69a56c4dd1a7c7112766b05d29fcfdd0f60d8c3f7287ec070201b4d0200e3ebbf47a97c230a7d2f05b25bec59cfd125f6cc15529f13fc624ebfd387327119434b66e61a8446e9fd9e14f4e0a42cee83f4600b195a06f4f0e55d67239c55256db69c3eb5218f9d214e0d9ca0992dee76630b55a96136a251a84711096475028e326782112f2afd64c3795f438ea623754cb0ea5e6a0d4e1ded7ee633f1eb8bf71b791646c8953e54a07242a178c02baf8fc68e7c1d3e6982b265802f50353b7f1eb0d8f33c9aed1b18432ecd04d10f951473a0e7d7e3e88a3cfca46ad1b11c5abca59bab0c8e880519753b9f4a9ab4f7a756d58a389dc3bdb25940a71a03899125b08efd7ec85b3cf0c1577014a81bf63b2144617cf259383a41af2d50a7ebb7d45a8968e3e3edfb1f4a45368ba380d172f82e641eb16949e192a3c2a37117df8e22fb7a4e7ed425f9951b392bc59184db81899ed2270844446a29aaed5cb3839c392d51636a24b737a3100417a849104c08606b4644a785080b67a92dfe888cd987100fd05aa0a007eacf337b3a80941f2defd530cf824f13cd263ba2ca194e7170072ce28e800000000000000070000000001312d0077c3e8caa53f1a775a5e89b1a54488aff835593d5e2b7355179136bbdd10a86c00061b1100030159105c3e04b59668b1516a793628be01d018e0de5972a7e6094a8b29761bd07a1654dc17ab21c8f940806cd4ccfd904db9594a8170f310b1e2d95e0e8b0baab7f8484c2c66a91b7f4274ec9e5cc3651ef2ee3a0177281548905a3c7d03c4ddf2bf8b736a940d69f2a5e6beaea33d92ce189a96803654a52b0d3da0cbdbbe0725e64dc4a6633f33318de0f6ca50b9f2a79ac68fdfe3a6f6c01a5215dc3bdfb56a780dc17968c5afd3270c50d4f7e1f540364e184d460e8b8479719788023ed029ad1439d0a0c85570b7a3f50ff70a82bd9ff9c04d6d8154046a30a3606ce25c2fbda28c863109cfaa95b7fe4f96622c715422ed1a8e99ce5bdecadb7c39798822115215e3914409d5de1e2c95a6c375c530b27fd0263d02167eb28628b945280a668f88c607bd74e3aac0ac704dfda9e796a76e6a856aee502b41c6f3932b6a89425484d580b6abc232cb12530b38b5c20cbbdcb0357210c3ad09a3ad7a56353dbbd6087f7cbccbae1f656ad06d370e4ec5a7906c9841a1f36f24ba6eab5c70b5d66bc8aecb60d9feb4576ef33b23456332483f01fcd0e01477789448ddc20fa207f496db56203fdaf53f6d64d97153d8e8c8c89c821f526f4b376e929d7598cf368b826313eb0ac5e435097b3f4acef26cfb30e63ab70622ff1ed04f9a1c02074bdb2d302d932cffbba4f833ab95912272ec87d8c05a8c5f1b2b101fb78a75cf9d0ab6e751163f27018f08c2fae76c7a6a417cf5cae2cdbd867115d9c1f162e83c3fc4f52202d3471212c3ae6eb39f882aa322609958dfbc8ca3f3a2eb051ef1b43d452b54c2352e8c9d184cbbd46ea936161067893164a72a34f6e2fd63c94353e524c9db699d15cef86f970bcf6a92dc367152f9740e84b2c292dbb338e4f21e6a47171b5a5cec0f4026906b528ad2c115866fb9e807faa200b600637abd774148f7637789946a82ec5c8e35692470c0c0f12a6a39a0c5dddf73635f2dbbb82d9ea56d8313a25cfd879ee024ee5144817b1f96945f34632cf0a5a3dd3ebcb8b42bb6c4b1c3d2a7fc6f817c97ec6282a3981a8d9e3d7070c178f7df847fcec8013b0a0d07a4f8c13c829209172022e0d724caf5a01219575f1d5a26f50f53d72ef8b596ae2263d2c2eeb822166178d56eba9ee9a9c60adb4fe3a7be89044d34288c7bd59cbf6e88e01f971b687200fccdc68d5a21f8430a8e5654a17f05773b2254eb301a5624c4aadbd3db8641cfe866ff72424a891f5e0487a48c204870c932ed9895427ce9a3d0a183fc40b7bbea3617b321f35cbba2c2180908e9bea2e07e1e5d8d5de9846994b78a313b8828eca935f4bdf9ca861326cca20776c6a4df35eeee257899467973941e6e8c567054480a7d8077e6e61ab480562ad53ad8127874a7fa4f747ccb2601cfa6e8c43e89f678dd38e4df80adef7bf07149edd32bf0e9775f3478870da6af26709a5bebbac77018050a07f1a8ffe4539c2df9de1dfe18c9bf0aa640178b0912bd9631acebdc2f2f993039b6cfa414d5cfcd0c363a178443e954db312efcd4463ee7cfe0d8a1eabe74d47692653f996cdd9b93c9fad41c5b16aa91a7bd5b267578a537e45d2af048ee0ce09ea41c72020d61509e5e91575022e7d5956b8e680f229909642366d5a16a17f021f41ca3d13df75ac3d3c8c772c2ba042680ba81466f8d05c07e19b1cde5a4d27ba6b820a63fffc5a42234e18109f128cb1e3524d621e38855b5c11cfbe7edf25dc3cd470308971b655b3381f946531d89ed23ad24f6a3cacd022fb9e5eb1d5a188a5d0936d0dfe3c7c424dba5f8892b2adda87a171d73bb5c5b8f809812689794ee3a5a7dc7d80f9c84bdad2fb7f89b2a45dc25836a42c8757eaddabcab7f82e1e51502cdcd3c4745009c55fd70b1c8f1a748e71e2b96b312f71f21cb00fd05aa0a007eacf337b3a80941f2defd530cf824f13cd263ba2ca194e7170072ce28e80000000000000006000000000010c87c77c3e8caa53f1a775a5e89b1a54488aff835593d5e2b7355179136bbdd10a86c00061b100002a9a1e8cbe48ae54ff2f32eb81ac70966e623abd77532a8cef6c3dab174da1e2879020c2238504e525d2d3fae9adb39044e8e6d0c394ae9e6ff1f01ae21e354d0bd1a5970e77015dbb6a635157b6465c32aee891c26ff8942ccfd24b612e4df241c55fc34dc1a5a613d431b813e14d0ad78023314f93c38f2bba6a6ea6e642d59a547f97b306ae0d072944c62cdec15933ffd85dafd9cabf278d9b8121db56915075baa049ac0d47df8a32b6c54a9935fbc1284fe8af288d3dd72870c8faf77e34a20970bf44b47bda06f2b8bfc931252456760ba1fa58669a3ec443737b429095db43f5bdf8e5d7f2d2f9c7318cfe012213ad35d54751539605337143de28756a146779a41308dbf94be4c9290422cb79ba768c340bc91012488afc3b388fbc253bdb9a35b1f4e39307c89f9ec3bb58e5da660013a741c1ab6c0cb22a3c94db0bf6d207599a527f18831530179880ef00950886378abcb99d2d1502b874669fb8f0a596ce3909e314057d7d1f668ca80e23c46f86127a71a729021623038d23cba281ed4967ea654470d4fdb31b297def0d22f5897f58d28af0cd86287fa51722af2682fe259987f56a9fe74af94138bb520ed12bd86453cc44f31f00e337647997b56c8bf40e3e9233e42b4c4ffe2ccc438417c754e04c95a2e7f357eb238020a0b235b8757a40996b6dab0e09e526f891f1773153151d99f3f65e62f0db6d4d94fb18293ea2f13e8c900d575cc0800969ef1e6903e6958c02dac84a8e863bcb8226bd3c6bab1038b628661333449d801b8b739bb08e09daf59c969691306e9e09c68508c5a558708a9b138fb841906a1967ea6290198be18ea3941a72a95b1b55e38403bda57d391cfdb86db844a0d9b4762a550cb1d7010de80fd6507d1e2dc7830ccd49784f8e80a3c87d9301339572b0347db9336bb7b1ede0fd1e187ca94aba942fe2b5c230f7dd1d3d0376aa882136b112883999227e2be17e9d681fb813acb70807b47e99bac127ca67c2d9619049783f8a9089d3fea4275585533683308ab94f3f02f577fb840ffae279813439fcb30eb5874329c48160768c2ca6b5d6368775989b96a056f22f7dddfbcd1b22a7fb74bb2d1b36f3e94914b82709a9351e1be88364a17a36b2a92ef61bb0520fefb802393b9e9effd6d54741ab9c6dbf28911bc45b334d9c2a6d76d94ecc2a19a3115d0f2b5e5ddb1f29fc9db0b3a21651afc2f93d321189621d8b59ab07e8d4e348f4bdbdb25b91d19b313850afddf92300c7fcebd9b266792745a24a505c56a3f98428ec70b65b0396a46836cabe49024d382eb1c8227e2df4da21385960f3d3801fb63d73ae69a4fcb6aca7018e874e8bf44f73c5e845ce81b2c643862c0344e3f4e50f4e6cb51b53a6c90ea545bc897dd73e2d2b3250711ed2a666413ae85b22e848735e8a6306e3b80f3677c8f40f85bf2f457f7764343288530a9c58b160de657df482af5eb0f291a50071d207cf46969643c113a6b15354b0b590885fbf4a7136939463ef66e013cb794ac6ab0fa887352817827ffc420bd8d1ee0b6a04d6819eadc1d96517c2edd8fe028101cd9842e407a44a8eb6bbda3fc5c54997fa43aaf340ed8ab6f75e3b588dd906ebd9deba889711b3895bd7df494f042e68cd78d7e75c237bd22b90e49e5571e169487508dfea22bfe2c83f21ec1e91f7d9331e5ac4ba6c52c1183afb1e083f3d0c42af6cf41e82e9151b5717b934ba6e4f52757d27a7c8139c523f977cb9c7f29e4a19cf41a1288c60a9ee10f58189351a51925422276e2da9ce3a4ca6944b767601e686745e88b7902e0e110dd66189dec74e3abbc76a4045d5051a6b76c91b2b20fc2ab1ca7d5d63f25d2c83f5d8ab31034e3ca42c4af1ed6017f5b10c2f44a52d78bf858aa7c148b6f07156ee365cd463d3c00fd05aa0a007eacf337b3a80941f2defd530cf824f13cd263ba2ca194e7170072ce28e800000000000000030000000001c9c38077c3e8caa53f1a775a5e89b1a54488aff835593d5e2b7355179136bbdd10a86c00061b1000031a12d4e5b7253515c5822879f6f1738224e451910cacebbb545aa637e2a0f631a151e02f206b6397055534bd6a0b7c7990d269d153d3886fc7e51fd4e09c5357a96694911e9912135e3f9ccec1058be709a743ee44f07feebb0fc6a3078bec155a1b9f67afaac6914debcc890fd86150d790f8de1b7168d4501064dacfd16c19f61a8c13c7658df92d6e5ad79b1b251a96db66bfc498e8e4114f98b9b36bc41663c9d2d15a280fdae479c14e52e148b0f86abbe4f9ef78570e193585b5aa30e53d54352eba5ad54d238f0d756b54aca9889fb21c57b6c639a6713a4f655d5dde92391185a9d8c929bca42c3bc9ba5f65b059dcbab02e89cf2e95fe1b1fb291aa1c2aeb8b57ab24f92414fc296a37b683a1d47155acb5210ffb6a170642e0f1cf7a4704861099b23c0294f367f28bf6fb6f839ba3e958ba6954ef630f90d014b687e63decc26c395601a885583ee0f1a86de5d60069664e2b93a7e936579e934a084b3e34850a1c26dc5fe7a8479278e6000f5025552b0d43ec186cd01a4d6ae748ba9289d39046c3568982aac9593a3496d3eec561b538a9b0d9ed91a4560f504174bb70725fc1c9bc354afe11d1e8aab3389774d619fdff96ea096c8283c2555e9d3169c8dd543bc74eb9f3dd4f17105563922aa18243f7135429b7a71368b44975e07443fb6f5eae089b88dc2d729d87e303104b8a7172902cdb8500ce9cd2086f7a7f6ce683942caae21ed05596c46d8f87f98eadb034c472a3f6b9d7a83d41fa70b44beb4288973cee486adc191a9aad1d1b7cebac6225aec67eed51c347fa5c145e183454b2a514a5044808eea8a9b28b24e39b115e2faa75f04d370285684857129e14e6726bb23aa0ff9323e9687578446868705f3137289c49357ff4acb134f6f3f7dc7efe6b6a332cd2fbbef0579493c4368b70815ff13abc1e3cb08c3931d8b7c99bb8b5e89fccda77a6d51fee07754332500517b75bd26bc66c81cf9f0e8a34e01c700b86590fa1cc7682a6d20c10d325d735dabc43db87ae2700e4966d8be90e408aca19ba1327ab209d4a574095e37285880c31cd631aabafa6b6c31b6db80b989ec57141ab35a5d7e32445f153da3832b223831bcaa8d1cedf6cf9d8e2dc121fd1b8a744481690be8668d6185113853ad1e86fbfe5a1b216208d3300532b0c80bc751d805260f1e6b014fe8f0b904a54560baa1b9f9d81479024b9d722fa577d9708eeb5b84c5005766f2e2c622689e1d750dc16ddd74450fedec590cb49014d4cba6dff6d2aa2c15b71067c8c02128e587f6a09556ee2e8e6b1b6bb8380ea6e79f43fb6e427fa66f0b616b84261b18f07d3607eaf4b932f38fd7267c742c503862458a1d1f01b239e94f39bcce1864564ce2f021fd43673964e77d3616bf8405b4c770996fa48d312458b29be5c05a6941ce5b3b2ff4ff32ad784ea47a664fbc2bec22fb6faecf928539773cd5c0972d9e6a10762a66190c3b5cc9b77d3546ec02d355aeec68ca9af34b2f8c44071b6d9b608f17e24ec3ac185cd9fab9b9bfdfb7873e748796af1b87820707752798534334b0e79bf108d60ef61a2c3cbdffc663b54f2ef407ae43749d31681e3da13ab3beb1f4ac2053cc7286bd7a3192ca412d1692ddcb1fc33131c19bc312d72b1616b91110fc15a8f33b2429eb0fd07bb034405bb879e54cf2f4331c2fbafc69cca8c2ff5a762c7f139edbe123735e63490a17f309ec895077731e5f6d6a53e513f1a3c15eaf72db4605d65eaf5cdc830155f5b9bf4e96a3644dd0ae9ab1f09778fdcd763668507d1c49663dc4a64def5f24577d2b1b34113f6a2a92999bcaf649536e431b8c2c30491cb54fe84b7e087c7fdd1e9b92dfaa31651138e7602602a45d331528ebd79b450ea237b195e80a04a2261a00fdd918cd0b0116f9d00fd05aa0a007eacf337b3a80941f2defd530cf824f13cd263ba2ca194e7170072ce28e800000000000000050000000001c9c38077c3e8caa53f1a775a5e89b1a54488aff835593d5e2b7355179136bbdd10a86c00061b100003d4b11a6510316810f0248ea0530220e3255171fd5fce2eee5d0bff33d694904b77c108bd2c322ebc2c3231e1f78618ab9ba83f81fcbbc7278f4d0cf17edb4342ccf40ba133606f6597f474b0dde594a6f8af078aadcfc940d5fcccd32793a1266190f06e55aec9b95b9f2e552ee8d5e4a662a7cdddb20599b14e3105699f2618395ca9d80ca232f5a96e48e27a09b24b3c28b38b42bf63464dbfc0d233c635d1379784581f5ff2f2fa2c6dff4cf8c12454745c695ea394d0fc477f4907e82e636e347306ee70730f61aa75ddbb10cf023b28a5e1f7dfed48470bf4b3180e343ea7f578a0d8f33505aa36b3875226b668376db40b3171f5a2eef326b0a416fd27cd7c7936e71cc9822421d9e317db5fa31de68f4be412666c3ef4c699acbadf94d2bfd1f32ad1f962da04965d20d783047a415f5f6a59117422dc26c5f05a5ef0180081e9b7771277ae8520647e833c2dc80149baea35700c35aadce8c4c81ef6e3fc3ec55e3fe3b9f846710fd648668ca3ba05f6b7cf5eddc9b5a7e73f2ac4d1f53864765cf70f55128ec53692bf26656da9468ea93b7030063a2021ad57cf3ab1df019c21118f6f9cec64def026910242fc4809d2224210460d63d02f2d6475b371b97907cc3c1e72f56ce8285cc08fd4e37f439f39b63667c045f4b5dc5f982cdc8b32fa0392ce38dccfa6a79f5bcaccd2bdaae666404947fd8b6d8ad7e16ae1307d7b24cc15d712814d1311bdf2155ee28da446ddd2bd0e782c225a8a379073314ec486aa2a9dc54c4edc2e2dea278f39ee23b0d7c2f5df7a20ffe5d77541d1c42a94a17e977763f15dd889c939104b691553ec8c99d5c87a9513553a7384e3a45fac0193b77fd8b7a2c5bf291a6954c767addeca4c91a04946688491c56818bb9de51d2e2dfc2c0b2e8f3e929ba04d9b3f457935f8c797dd770cd6558b6238ba0706a500bd9aaa17565a8a8b8abb41e4717f312d9b449de7dcd5317e1f6ba71b428f5e96857fc9acaef6298d4e994746a45534715af1326c79836f0f3a7ae3aaa41c90f172ec8544d13086237420207fddbae7d349a2871a62f465a6c57bb54e623c36067f41f33282a8548e5047d3d2da4c83483811ee3559bd7479216631281aeee1152f1fb876beb57b51c9cbf002ce9e6c81129a119120e24789958bb1de20448f01692ea4b955099b808af3c4dc7ad6652a9eff075f91fd3bbf54ec7d450c8000005894542b810974b36f6a66125e047dc491aa376b70aef9fd65379c0668937a86e0c12772520a151df018c031b931b2e0c0a25419f10080fa9010ddee60b4861692ed00bef79ab5cae1a4d5baf62552a111845c3969538bed014baac2169b2c6e847b3123a7aff9761736ba9e2f5f4d0f94852c921599615f91bbbdeb230ddf834305c9c70490307c300952b8e61e5255b31cd09f2ca7cdbb4c4e76798a78c0a8709d86c7dfd5dc008af596308a36e0d28c4ba60d68151858e740ccbcc068b0acb3fb81bea92e4e979ac39057ccb19c8603658efc62f6222621cf956b377b7ff0fea770908f04600c2720b03371a62ef941159fcc015248ba326f31d1bc82e4d94c186d4f6c39e1f55600221a2cdf85b560b78dc5fb3e74069021e9062e2e7c6173716ca70dc843cf02070253d31ddb9c4b569df4fe243b78a8300788104b575d641108510bafea96a25bbea6b8f6474fa1886de9d525a4fbdb480afc4ed96482ff2aa8e64142c285b11c87ffef811b5026b3a2587a91aff83c6825c4d0634ccc7aab85e795c11491f3e0883568c23e67efcd4c26a5db3ca0b5c3bbded3c6e355738319c1a087d8da87db4da52d4c5214d272cd1631b2843cbd6b015e52eb51a8bb759d529ae6ab7b397aa8963f2074c9278fa8499de47dc9152bb8726de26f5bbf24e9ca7e329353ca2da6363b4e00002710000000000598cd44000000002faf0800240a007eacf337b3a80941f2defd530cf824f13cd263ba2ca194e7170072ce28e8000000002b40420f0000000000220020e2eb1e4df160f9e11d4d06a6075034b47e9d3e1c3d21d0feab64905d2e6ab17b47522103174f3de90105ae02d88ccc1a7ed4bf0d116f27ef6010f1ec308273c1010ae3dc2103548b338f50bdae124711cadef7a82ce832bff61826f13b031677793abb8c674c52aefd0205020000000001010a007eacf337b3a80941f2defd530cf824f13cd263ba2ca194e7170072ce28e80000000000a1c4a78006204e0000000000002200204c81bcdcc2c4f01d3c045348a155c9249ddba4d48c16ccf33c1d8b6e34614180a8610000000000002200204c81bcdcc2c4f01d3c045348a155c9249ddba4d48c16ccf33c1d8b6e3461418030750000000000002200204c81bcdcc2c4f01d3c045348a155c9249ddba4d48c16ccf33c1d8b6e3461418030750000000000002200204c81bcdcc2c4f01d3c045348a155c9249ddba4d48c16ccf33c1d8b6e34614180a437010000000000220020680a82e78074810847ca530cd74fabdbd2e34beaf0fdd2bc832ddfcd2669876c00350c0000000000160014e1fdef3169db3728018a906129e3913dd841ab0f04004730440220639ddfeb4cfd418c28418208226f5f6be762b65bb242968695ac1574d1fae8e702207bd3b3f60f12f171a37e50b7126c709a4cb87e417efdfe520707962d393bd28c01473044022058407ee97260aa8020eea7036f348ec4959fbd8a820e8628244705138803e00e02207d53e7fec4e01bbc04a0495e8c31210c0c6c2542e38d6c9ae677b78bd568cedb0147522103174f3de90105ae02d88ccc1a7ed4bf0d116f27ef6010f1ec308273c1010ae3dc2103548b338f50bdae124711cadef7a82ce832bff61826f13b031677793abb8c674c52ae340169200004000324efa7874aa335cd976b8209145d670a6dba17471f6a4f47dacaa432dd972d801c000000002b204e0000000000002200204c81bcdcc2c4f01d3c045348a155c9249ddba4d48c16ccf33c1d8b6e346141808576a9144a2fe35d15fdacd3b3cba332b5879b6acfb2e79f8763ac67210375099d4e25580f8d2c59718d7319e9d26c7119f9476ca3a623fb638843d3c8617c820120876475527c210375f5c7f3e5f1da49febb149cb9dc97098402628f84b79b586d5d516c17e6327852ae67a914950b69c651378982bec084b296e6dd23a33c41b588ac68685e0200000001efa7874aa335cd976b8209145d670a6dba17471f6a4f47dacaa432dd972d801c000000000000000000013a34000000000000220020680a82e78074810847ca530cd74fabdbd2e34beaf0fdd2bc832ddfcd2669876c111b06004093d252d2f22cecee6c2b604a1190120db574f0ba33b49ac826229b95071230bd7a4baa7a1704813804ba9b7d0e2aef3932a7d7d096862c1636736ad3296a46f5401f096356d49cb9c0d1dad9a01530aa892aa75cdcb626f42ef09b734f39d0a2650d6274377598b29f3f3eae1281a8b61d5cb9853b478cc973b8035af5d60c26a0000324efa7874aa335cd976b8209145d670a6dba17471f6a4f47dacaa432dd972d801c010000002ba8610000000000002200204c81bcdcc2c4f01d3c045348a155c9249ddba4d48c16ccf33c1d8b6e346141808576a9144a2fe35d15fdacd3b3cba332b5879b6acfb2e79f8763ac67210375099d4e25580f8d2c59718d7319e9d26c7119f9476ca3a623fb638843d3c8617c820120876475527c210375f5c7f3e5f1da49febb149cb9dc97098402628f84b79b586d5d516c17e6327852ae67a914950b69c651378982bec084b296e6dd23a33c41b588ac68685e0200000001efa7874aa335cd976b8209145d670a6dba17471f6a4f47dacaa432dd972d801c01000000000000000001c247000000000000220020680a82e78074810847ca530cd74fabdbd2e34beaf0fdd2bc832ddfcd2669876c101b060040774ca3fbbee6dc29db89dbb2bdb977afdf31727548aa6060e9e23a79090bf658474a5aa2de53dae36371ec535e13e4291c9fbd1942e7cc812ff4ca4c9d84483c4088605547607e6c8b1b24a671ed340700ad396a8bf613fa9e4646c0b11c2aeff708e4448ba70fe48903e3034ace605d8651091fcd6f80fddb57d2e2b09da6765d000324efa7874aa335cd976b8209145d670a6dba17471f6a4f47dacaa432dd972d801c020000002b30750000000000002200204c81bcdcc2c4f01d3c045348a155c9249ddba4d48c16ccf33c1d8b6e346141808576a9144a2fe35d15fdacd3b3cba332b5879b6acfb2e79f8763ac67210375099d4e25580f8d2c59718d7319e9d26c7119f9476ca3a623fb638843d3c8617c820120876475527c210375f5c7f3e5f1da49febb149cb9dc97098402628f84b79b586d5d516c17e6327852ae67a914950b69c651378982bec084b296e6dd23a33c41b588ac68685e0200000001efa7874aa335cd976b8209145d670a6dba17471f6a4f47dacaa432dd972d801c020000000000000000014a5b000000000000220020680a82e78074810847ca530cd74fabdbd2e34beaf0fdd2bc832ddfcd2669876c101b0600404ec5ef779e7b0db022d9da0986bee62eeb0372337f3974e0bfa8ecbddec7a3ed47930ce5ca6796d3cde21dbf9e0678f4d0af5d84889c24e2b960786d141b900a402c736579e487f2ceedb15546a438818e9a13d3b9f9232d4ff418855f9112795e2bce08fb52f8737268b616158eeb06e36abdc83942396fb407d3e603ed1edd7b000324efa7874aa335cd976b8209145d670a6dba17471f6a4f47dacaa432dd972d801c030000002b30750000000000002200204c81bcdcc2c4f01d3c045348a155c9249ddba4d48c16ccf33c1d8b6e346141808576a9144a2fe35d15fdacd3b3cba332b5879b6acfb2e79f8763ac67210375099d4e25580f8d2c59718d7319e9d26c7119f9476ca3a623fb638843d3c8617c820120876475527c210375f5c7f3e5f1da49febb149cb9dc97098402628f84b79b586d5d516c17e6327852ae67a914950b69c651378982bec084b296e6dd23a33c41b588ac68685e0200000001efa7874aa335cd976b8209145d670a6dba17471f6a4f47dacaa432dd972d801c030000000000000000014a5b000000000000220020680a82e78074810847ca530cd74fabdbd2e34beaf0fdd2bc832ddfcd2669876c101b060040ff0a3853c07d426ac93a8b772017a41f324558851ec69bcd65ed1cd81490e0f11c3c01574fe196df6311cf21fbb78abd7d40659479ea080c7ccb3c5fd53027df404f63e06d948b7890c8a3fb1ae568e88de8cd4ef3364c092bcdeb006c40558b082a5fc572f9f02f5d2a0870101ff7d900da184fb19b5cd410ba0779bc55533c4a00000000000000070005fffd05aa0a007eacf337b3a80941f2defd530cf824f13cd263ba2ca194e7170072ce28e800000000000000030000000001c9c38077c3e8caa53f1a775a5e89b1a54488aff835593d5e2b7355179136bbdd10a86c00061b1000031a12d4e5b7253515c5822879f6f1738224e451910cacebbb545aa637e2a0f631a151e02f206b6397055534bd6a0b7c7990d269d153d3886fc7e51fd4e09c5357a96694911e9912135e3f9ccec1058be709a743ee44f07feebb0fc6a3078bec155a1b9f67afaac6914debcc890fd86150d790f8de1b7168d4501064dacfd16c19f61a8c13c7658df92d6e5ad79b1b251a96db66bfc498e8e4114f98b9b36bc41663c9d2d15a280fdae479c14e52e148b0f86abbe4f9ef78570e193585b5aa30e53d54352eba5ad54d238f0d756b54aca9889fb21c57b6c639a6713a4f655d5dde92391185a9d8c929bca42c3bc9ba5f65b059dcbab02e89cf2e95fe1b1fb291aa1c2aeb8b57ab24f92414fc296a37b683a1d47155acb5210ffb6a170642e0f1cf7a4704861099b23c0294f367f28bf6fb6f839ba3e958ba6954ef630f90d014b687e63decc26c395601a885583ee0f1a86de5d60069664e2b93a7e936579e934a084b3e34850a1c26dc5fe7a8479278e6000f5025552b0d43ec186cd01a4d6ae748ba9289d39046c3568982aac9593a3496d3eec561b538a9b0d9ed91a4560f504174bb70725fc1c9bc354afe11d1e8aab3389774d619fdff96ea096c8283c2555e9d3169c8dd543bc74eb9f3dd4f17105563922aa18243f7135429b7a71368b44975e07443fb6f5eae089b88dc2d729d87e303104b8a7172902cdb8500ce9cd2086f7a7f6ce683942caae21ed05596c46d8f87f98eadb034c472a3f6b9d7a83d41fa70b44beb4288973cee486adc191a9aad1d1b7cebac6225aec67eed51c347fa5c145e183454b2a514a5044808eea8a9b28b24e39b115e2faa75f04d370285684857129e14e6726bb23aa0ff9323e9687578446868705f3137289c49357ff4acb134f6f3f7dc7efe6b6a332cd2fbbef0579493c4368b70815ff13abc1e3cb08c3931d8b7c99bb8b5e89fccda77a6d51fee07754332500517b75bd26bc66c81cf9f0e8a34e01c700b86590fa1cc7682a6d20c10d325d735dabc43db87ae2700e4966d8be90e408aca19ba1327ab209d4a574095e37285880c31cd631aabafa6b6c31b6db80b989ec57141ab35a5d7e32445f153da3832b223831bcaa8d1cedf6cf9d8e2dc121fd1b8a744481690be8668d6185113853ad1e86fbfe5a1b216208d3300532b0c80bc751d805260f1e6b014fe8f0b904a54560baa1b9f9d81479024b9d722fa577d9708eeb5b84c5005766f2e2c622689e1d750dc16ddd74450fedec590cb49014d4cba6dff6d2aa2c15b71067c8c02128e587f6a09556ee2e8e6b1b6bb8380ea6e79f43fb6e427fa66f0b616b84261b18f07d3607eaf4b932f38fd7267c742c503862458a1d1f01b239e94f39bcce1864564ce2f021fd43673964e77d3616bf8405b4c770996fa48d312458b29be5c05a6941ce5b3b2ff4ff32ad784ea47a664fbc2bec22fb6faecf928539773cd5c0972d9e6a10762a66190c3b5cc9b77d3546ec02d355aeec68ca9af34b2f8c44071b6d9b608f17e24ec3ac185cd9fab9b9bfdfb7873e748796af1b87820707752798534334b0e79bf108d60ef61a2c3cbdffc663b54f2ef407ae43749d31681e3da13ab3beb1f4ac2053cc7286bd7a3192ca412d1692ddcb1fc33131c19bc312d72b1616b91110fc15a8f33b2429eb0fd07bb034405bb879e54cf2f4331c2fbafc69cca8c2ff5a762c7f139edbe123735e63490a17f309ec895077731e5f6d6a53e513f1a3c15eaf72db4605d65eaf5cdc830155f5b9bf4e96a3644dd0ae9ab1f09778fdcd763668507d1c49663dc4a64def5f24577d2b1b34113f6a2a92999bcaf649536e431b8c2c30491cb54fe84b7e087c7fdd1e9b92dfaa31651138e7602602a45d331528ebd79b450ea237b195e80a04a2261a00fdd918cd0b0116f9dfffd05aa0a007eacf337b3a80941f2defd530cf824f13cd263ba2ca194e7170072ce28e800000000000000050000000001c9c38077c3e8caa53f1a775a5e89b1a54488aff835593d5e2b7355179136bbdd10a86c00061b100003d4b11a6510316810f0248ea0530220e3255171fd5fce2eee5d0bff33d694904b77c108bd2c322ebc2c3231e1f78618ab9ba83f81fcbbc7278f4d0cf17edb4342ccf40ba133606f6597f474b0dde594a6f8af078aadcfc940d5fcccd32793a1266190f06e55aec9b95b9f2e552ee8d5e4a662a7cdddb20599b14e3105699f2618395ca9d80ca232f5a96e48e27a09b24b3c28b38b42bf63464dbfc0d233c635d1379784581f5ff2f2fa2c6dff4cf8c12454745c695ea394d0fc477f4907e82e636e347306ee70730f61aa75ddbb10cf023b28a5e1f7dfed48470bf4b3180e343ea7f578a0d8f33505aa36b3875226b668376db40b3171f5a2eef326b0a416fd27cd7c7936e71cc9822421d9e317db5fa31de68f4be412666c3ef4c699acbadf94d2bfd1f32ad1f962da04965d20d783047a415f5f6a59117422dc26c5f05a5ef0180081e9b7771277ae8520647e833c2dc80149baea35700c35aadce8c4c81ef6e3fc3ec55e3fe3b9f846710fd648668ca3ba05f6b7cf5eddc9b5a7e73f2ac4d1f53864765cf70f55128ec53692bf26656da9468ea93b7030063a2021ad57cf3ab1df019c21118f6f9cec64def026910242fc4809d2224210460d63d02f2d6475b371b97907cc3c1e72f56ce8285cc08fd4e37f439f39b63667c045f4b5dc5f982cdc8b32fa0392ce38dccfa6a79f5bcaccd2bdaae666404947fd8b6d8ad7e16ae1307d7b24cc15d712814d1311bdf2155ee28da446ddd2bd0e782c225a8a379073314ec486aa2a9dc54c4edc2e2dea278f39ee23b0d7c2f5df7a20ffe5d77541d1c42a94a17e977763f15dd889c939104b691553ec8c99d5c87a9513553a7384e3a45fac0193b77fd8b7a2c5bf291a6954c767addeca4c91a04946688491c56818bb9de51d2e2dfc2c0b2e8f3e929ba04d9b3f457935f8c797dd770cd6558b6238ba0706a500bd9aaa17565a8a8b8abb41e4717f312d9b449de7dcd5317e1f6ba71b428f5e96857fc9acaef6298d4e994746a45534715af1326c79836f0f3a7ae3aaa41c90f172ec8544d13086237420207fddbae7d349a2871a62f465a6c57bb54e623c36067f41f33282a8548e5047d3d2da4c83483811ee3559bd7479216631281aeee1152f1fb876beb57b51c9cbf002ce9e6c81129a119120e24789958bb1de20448f01692ea4b955099b808af3c4dc7ad6652a9eff075f91fd3bbf54ec7d450c8000005894542b810974b36f6a66125e047dc491aa376b70aef9fd65379c0668937a86e0c12772520a151df018c031b931b2e0c0a25419f10080fa9010ddee60b4861692ed00bef79ab5cae1a4d5baf62552a111845c3969538bed014baac2169b2c6e847b3123a7aff9761736ba9e2f5f4d0f94852c921599615f91bbbdeb230ddf834305c9c70490307c300952b8e61e5255b31cd09f2ca7cdbb4c4e76798a78c0a8709d86c7dfd5dc008af596308a36e0d28c4ba60d68151858e740ccbcc068b0acb3fb81bea92e4e979ac39057ccb19c8603658efc62f6222621cf956b377b7ff0fea770908f04600c2720b03371a62ef941159fcc015248ba326f31d1bc82e4d94c186d4f6c39e1f55600221a2cdf85b560b78dc5fb3e74069021e9062e2e7c6173716ca70dc843cf02070253d31ddb9c4b569df4fe243b78a8300788104b575d641108510bafea96a25bbea6b8f6474fa1886de9d525a4fbdb480afc4ed96482ff2aa8e64142c285b11c87ffef811b5026b3a2587a91aff83c6825c4d0634ccc7aab85e795c11491f3e0883568c23e67efcd4c26a5db3ca0b5c3bbded3c6e355738319c1a087d8da87db4da52d4c5214d272cd1631b2843cbd6b015e52eb51a8bb759d529ae6ab7b397aa8963f2074c9278fa8499de47dc9152bb8726de26f5bbf24e9ca7e329353ca2da6363b4efffd05aa0a007eacf337b3a80941f2defd530cf824f13cd263ba2ca194e7170072ce28e8000000000000000400000000017d784077c3e8caa53f1a775a5e89b1a54488aff835593d5e2b7355179136bbdd10a86c00061b1000020b7604aeb7cb080b12de62f75a292bed3134b4a3de764bd032fb049e2c2a1d3942cc11b9b12619d42cda3c7eb63da952644a3f355bdf772d77f1fc2a0b36bf116cdacfcda3b77974536cc3f3d0f8209dba69408073cbe0f039eba220fcf3b0b96d5875bb71acdc999fd9feeab68a0b63629efe0dc91e92dcf93b3c49285c981746a68ead7a96a9c1ce21284a2796b0051e6b7cf36a264d545063c054454b87cc3f9ddad5350382585de18cdc4e65e02484695f541b8fc082c87ea4a56aabc84fd1b7c1cd40e3517ae811f9ff921fba672e0191c88a2681ef8ea1300eeb6c1d8fccdb5ab05bf80b2a5c3ed5c018752cc841305edae02149389bc5e58ea5a59a1c59755c7ab5f35e3740c9f6218d227370363a7e386b214f5b2e771ea8b94a2a5e640d8a715d57756665f4a659f4ef6488f9ceab5e22d523ee52da368701d799fcb3459a31e6fb03de91ffd9b608656b172945015da3e5000f7f6c3dc0b4e102ba5f101bab5c2ceab8021d071bf89cf9d65d2439fe9a9dea4291eccb43a431904313655391ace4b82bf5da6270eb5bc12a60a69e7cf96b75a699db5a374713558eff7101bb2d8471e0c4ad0e202fd10aa46098bd5565c1d410e695fdd799c866090f1a7aa002305388acb68c8d82d588c1a66df5fb12653686bc4cf487a3484c0c23578a428de3df57539ed11227f2648bc36261c7f3f4f13e18d238dc856b8dd8f07de9fb73663d3a0026a03d9ee9f807e2a03c9546d2537a1f30a1f06767622d8bacdf4ab3b0f245a7b4f482baa60080fce3e7e15d2e086c670d6ec11d907e3da593977c8c25d620ed40cf82dd503c25f1a5f3e8a5ddb65ae7117600794844252e1448d17849028bd5df960a5fddf56e48cf082cfbc5c29666bca6af335c06f8240912a311e6c07946eeea9ef57e46b3e48b95c82cbee3830bf2b55d5e0223b9480fe072729a8af4c6c8c2f86038cb8a2e02405ce5f834c87b241fcb9963f008c273c64bc1f7289cc3a0c5eea7ea1a6dc7bc6228a97978a2ddd7dc49303c5beb15b36c8044f656716cad0a62d1e8c381db46f007be7f8096f72d3a8f08d338d9f2bbc43c0244215df229824a9ad34b655d840b38c5061462d54358be1c184b51d3a805beeea78047f544b15cc333d591f3d8cb60cbdd78e58ed47d21739762957ed6365fea14d7ba8368371fe4333be4f5ae289ff444c9f377a072a3a4173bd2680c6d6074743908d9c4f09aa30d064c7866a7a34303fce53deba6a597a24c211d209815bbff97736ba9fc79e390b36b2343d2590c8fd6db3e54206580eb7a53b9de09a42cfaa2cffb00ea90dbd07f1d357e69ca96fbba4efefc4e07b1a1a174a9a8a5568c0ec9a9487add3890a20391eebd69a56c4dd1a7c7112766b05d29fcfdd0f60d8c3f7287ec070201b4d0200e3ebbf47a97c230a7d2f05b25bec59cfd125f6cc15529f13fc624ebfd387327119434b66e61a8446e9fd9e14f4e0a42cee83f4600b195a06f4f0e55d67239c55256db69c3eb5218f9d214e0d9ca0992dee76630b55a96136a251a84711096475028e326782112f2afd64c3795f438ea623754cb0ea5e6a0d4e1ded7ee633f1eb8bf71b791646c8953e54a07242a178c02baf8fc68e7c1d3e6982b265802f50353b7f1eb0d8f33c9aed1b18432ecd04d10f951473a0e7d7e3e88a3cfca46ad1b11c5abca59bab0c8e880519753b9f4a9ab4f7a756d58a389dc3bdb25940a71a03899125b08efd7ec85b3cf0c1577014a81bf63b2144617cf259383a41af2d50a7ebb7d45a8968e3e3edfb1f4a45368ba380d172f82e641eb16949e192a3c2a37117df8e22fb7a4e7ed425f9951b392bc59184db81899ed2270844446a29aaed5cb3839c392d51636a24b737a3100417a849104c08606b4644a785080b67a92dfe888cd9871fffd05aa0a007eacf337b3a80941f2defd530cf824f13cd263ba2ca194e7170072ce28e80000000000000006000000000010c87c77c3e8caa53f1a775a5e89b1a54488aff835593d5e2b7355179136bbdd10a86c00061b100002a9a1e8cbe48ae54ff2f32eb81ac70966e623abd77532a8cef6c3dab174da1e2879020c2238504e525d2d3fae9adb39044e8e6d0c394ae9e6ff1f01ae21e354d0bd1a5970e77015dbb6a635157b6465c32aee891c26ff8942ccfd24b612e4df241c55fc34dc1a5a613d431b813e14d0ad78023314f93c38f2bba6a6ea6e642d59a547f97b306ae0d072944c62cdec15933ffd85dafd9cabf278d9b8121db56915075baa049ac0d47df8a32b6c54a9935fbc1284fe8af288d3dd72870c8faf77e34a20970bf44b47bda06f2b8bfc931252456760ba1fa58669a3ec443737b429095db43f5bdf8e5d7f2d2f9c7318cfe012213ad35d54751539605337143de28756a146779a41308dbf94be4c9290422cb79ba768c340bc91012488afc3b388fbc253bdb9a35b1f4e39307c89f9ec3bb58e5da660013a741c1ab6c0cb22a3c94db0bf6d207599a527f18831530179880ef00950886378abcb99d2d1502b874669fb8f0a596ce3909e314057d7d1f668ca80e23c46f86127a71a729021623038d23cba281ed4967ea654470d4fdb31b297def0d22f5897f58d28af0cd86287fa51722af2682fe259987f56a9fe74af94138bb520ed12bd86453cc44f31f00e337647997b56c8bf40e3e9233e42b4c4ffe2ccc438417c754e04c95a2e7f357eb238020a0b235b8757a40996b6dab0e09e526f891f1773153151d99f3f65e62f0db6d4d94fb18293ea2f13e8c900d575cc0800969ef1e6903e6958c02dac84a8e863bcb8226bd3c6bab1038b628661333449d801b8b739bb08e09daf59c969691306e9e09c68508c5a558708a9b138fb841906a1967ea6290198be18ea3941a72a95b1b55e38403bda57d391cfdb86db844a0d9b4762a550cb1d7010de80fd6507d1e2dc7830ccd49784f8e80a3c87d9301339572b0347db9336bb7b1ede0fd1e187ca94aba942fe2b5c230f7dd1d3d0376aa882136b112883999227e2be17e9d681fb813acb70807b47e99bac127ca67c2d9619049783f8a9089d3fea4275585533683308ab94f3f02f577fb840ffae279813439fcb30eb5874329c48160768c2ca6b5d6368775989b96a056f22f7dddfbcd1b22a7fb74bb2d1b36f3e94914b82709a9351e1be88364a17a36b2a92ef61bb0520fefb802393b9e9effd6d54741ab9c6dbf28911bc45b334d9c2a6d76d94ecc2a19a3115d0f2b5e5ddb1f29fc9db0b3a21651afc2f93d321189621d8b59ab07e8d4e348f4bdbdb25b91d19b313850afddf92300c7fcebd9b266792745a24a505c56a3f98428ec70b65b0396a46836cabe49024d382eb1c8227e2df4da21385960f3d3801fb63d73ae69a4fcb6aca7018e874e8bf44f73c5e845ce81b2c643862c0344e3f4e50f4e6cb51b53a6c90ea545bc897dd73e2d2b3250711ed2a666413ae85b22e848735e8a6306e3b80f3677c8f40f85bf2f457f7764343288530a9c58b160de657df482af5eb0f291a50071d207cf46969643c113a6b15354b0b590885fbf4a7136939463ef66e013cb794ac6ab0fa887352817827ffc420bd8d1ee0b6a04d6819eadc1d96517c2edd8fe028101cd9842e407a44a8eb6bbda3fc5c54997fa43aaf340ed8ab6f75e3b588dd906ebd9deba889711b3895bd7df494f042e68cd78d7e75c237bd22b90e49e5571e169487508dfea22bfe2c83f21ec1e91f7d9331e5ac4ba6c52c1183afb1e083f3d0c42af6cf41e82e9151b5717b934ba6e4f52757d27a7c8139c523f977cb9c7f29e4a19cf41a1288c60a9ee10f58189351a51925422276e2da9ce3a4ca6944b767601e686745e88b7902e0e110dd66189dec74e3abbc76a4045d5051a6b76c91b2b20fc2ab1ca7d5d63f25d2c83f5d8ab31034e3ca42c4af1ed6017f5b10c2f44a52d78bf858aa7c148b6f07156ee365cd463d3cfffd05aa0a007eacf337b3a80941f2defd530cf824f13cd263ba2ca194e7170072ce28e800000000000000070000000001312d0077c3e8caa53f1a775a5e89b1a54488aff835593d5e2b7355179136bbdd10a86c00061b1100030159105c3e04b59668b1516a793628be01d018e0de5972a7e6094a8b29761bd07a1654dc17ab21c8f940806cd4ccfd904db9594a8170f310b1e2d95e0e8b0baab7f8484c2c66a91b7f4274ec9e5cc3651ef2ee3a0177281548905a3c7d03c4ddf2bf8b736a940d69f2a5e6beaea33d92ce189a96803654a52b0d3da0cbdbbe0725e64dc4a6633f33318de0f6ca50b9f2a79ac68fdfe3a6f6c01a5215dc3bdfb56a780dc17968c5afd3270c50d4f7e1f540364e184d460e8b8479719788023ed029ad1439d0a0c85570b7a3f50ff70a82bd9ff9c04d6d8154046a30a3606ce25c2fbda28c863109cfaa95b7fe4f96622c715422ed1a8e99ce5bdecadb7c39798822115215e3914409d5de1e2c95a6c375c530b27fd0263d02167eb28628b945280a668f88c607bd74e3aac0ac704dfda9e796a76e6a856aee502b41c6f3932b6a89425484d580b6abc232cb12530b38b5c20cbbdcb0357210c3ad09a3ad7a56353dbbd6087f7cbccbae1f656ad06d370e4ec5a7906c9841a1f36f24ba6eab5c70b5d66bc8aecb60d9feb4576ef33b23456332483f01fcd0e01477789448ddc20fa207f496db56203fdaf53f6d64d97153d8e8c8c89c821f526f4b376e929d7598cf368b826313eb0ac5e435097b3f4acef26cfb30e63ab70622ff1ed04f9a1c02074bdb2d302d932cffbba4f833ab95912272ec87d8c05a8c5f1b2b101fb78a75cf9d0ab6e751163f27018f08c2fae76c7a6a417cf5cae2cdbd867115d9c1f162e83c3fc4f52202d3471212c3ae6eb39f882aa322609958dfbc8ca3f3a2eb051ef1b43d452b54c2352e8c9d184cbbd46ea936161067893164a72a34f6e2fd63c94353e524c9db699d15cef86f970bcf6a92dc367152f9740e84b2c292dbb338e4f21e6a47171b5a5cec0f4026906b528ad2c115866fb9e807faa200b600637abd774148f7637789946a82ec5c8e35692470c0c0f12a6a39a0c5dddf73635f2dbbb82d9ea56d8313a25cfd879ee024ee5144817b1f96945f34632cf0a5a3dd3ebcb8b42bb6c4b1c3d2a7fc6f817c97ec6282a3981a8d9e3d7070c178f7df847fcec8013b0a0d07a4f8c13c829209172022e0d724caf5a01219575f1d5a26f50f53d72ef8b596ae2263d2c2eeb822166178d56eba9ee9a9c60adb4fe3a7be89044d34288c7bd59cbf6e88e01f971b687200fccdc68d5a21f8430a8e5654a17f05773b2254eb301a5624c4aadbd3db8641cfe866ff72424a891f5e0487a48c204870c932ed9895427ce9a3d0a183fc40b7bbea3617b321f35cbba2c2180908e9bea2e07e1e5d8d5de9846994b78a313b8828eca935f4bdf9ca861326cca20776c6a4df35eeee257899467973941e6e8c567054480a7d8077e6e61ab480562ad53ad8127874a7fa4f747ccb2601cfa6e8c43e89f678dd38e4df80adef7bf07149edd32bf0e9775f3478870da6af26709a5bebbac77018050a07f1a8ffe4539c2df9de1dfe18c9bf0aa640178b0912bd9631acebdc2f2f993039b6cfa414d5cfcd0c363a178443e954db312efcd4463ee7cfe0d8a1eabe74d47692653f996cdd9b93c9fad41c5b16aa91a7bd5b267578a537e45d2af048ee0ce09ea41c72020d61509e5e91575022e7d5956b8e680f229909642366d5a16a17f021f41ca3d13df75ac3d3c8c772c2ba042680ba81466f8d05c07e19b1cde5a4d27ba6b820a63fffc5a42234e18109f128cb1e3524d621e38855b5c11cfbe7edf25dc3cd470308971b655b3381f946531d89ed23ad24f6a3cacd022fb9e5eb1d5a188a5d0936d0dfe3c7c424dba5f8892b2adda87a171d73bb5c5b8f809812689794ee3a5a7dc7d80f9c84bdad2fb7f89b2a45dc25836a42c8757eaddabcab7f82e1e51502cdcd3c4745009c55fd70b1c8f1a748e71e2b96b312f71f21cb00002710000000002faf0800000000000598cd446da1a38c05425e396afcb5fbb37ea2a9db15c56121e2fae11ec9f06da63917610371ece811f4d34713b42d65c38a775487c71c193a52df6ac46d6a013164681dd200000000000000000000000000000000000000080000000000000000000500000000000000050003d6ec06b2431d4e1f9c36a610af90d6c40000000000000006000317def351ac5745148ba3275aacb2b68f000000000000000700035d913d0e286346e1a50fe900f618b18600000000000000030003c35487d4d1e24e38bb4f923885d19b44000000000000000400030c7e6ecdbccf41baab2f7d95ca9e5e9bff03d32570a2783f1792d20fbe141f337d5dded9509c875e13288fe140400f36560e240a007eacf337b3a80941f2defd530cf824f13cd263ba2ca194e7170072ce28e8000000002b40420f0000000000220020e2eb1e4df160f9e11d4d06a6075034b47e9d3e1c3d21d0feab64905d2e6ab17b47522103174f3de90105ae02d88ccc1a7ed4bf0d116f27ef6010f1ec308273c1010ae3dc2103548b338f50bdae124711cadef7a82ce832bff61826f13b031677793abb8c674c52ae0003003e0000fffffffffffc008030b0e83d8813791baf507a3c85c55d81cf80a50fd9f08504260743bb8033212800fc0003ffffffffffe80101460f774080d0e1bad18203f9af025451bfb4b8de611116890dd1fa45dd0f8e9802000007ffffffffffc80104c31735de0c70dc61744d1123646e49d871b662ae090c568a3ba7666fe370ce0c0003ffffffffffe40a007eacf337b3a80941f2defd530cf824f13cd263ba2ca194e7170072ce28e8000000000000061a8000000000fffd0205020000000001010a007eacf337b3a80941f2defd530cf824f13cd263ba2ca194e7170072ce28e80000000000a1c4a78006204e0000000000002200204c81bcdcc2c4f01d3c045348a155c9249ddba4d48c16ccf33c1d8b6e34614180a8610000000000002200204c81bcdcc2c4f01d3c045348a155c9249ddba4d48c16ccf33c1d8b6e3461418030750000000000002200204c81bcdcc2c4f01d3c045348a155c9249ddba4d48c16ccf33c1d8b6e3461418030750000000000002200204c81bcdcc2c4f01d3c045348a155c9249ddba4d48c16ccf33c1d8b6e34614180a437010000000000220020680a82e78074810847ca530cd74fabdbd2e34beaf0fdd2bc832ddfcd2669876c00350c0000000000160014e1fdef3169db3728018a906129e3913dd841ab0f04004730440220639ddfeb4cfd418c28418208226f5f6be762b65bb242968695ac1574d1fae8e702207bd3b3f60f12f171a37e50b7126c709a4cb87e417efdfe520707962d393bd28c01473044022058407ee97260aa8020eea7036f348ec4959fbd8a820e8628244705138803e00e02207d53e7fec4e01bbc04a0495e8c31210c0c6c2542e38d6c9ae677b78bd568cedb0147522103174f3de90105ae02d88ccc1a7ed4bf0d116f27ef6010f1ec308273c1010ae3dc2103548b338f50bdae124711cadef7a82ce832bff61826f13b031677793abb8c674c52ae34016920ffed02000000000101efa7874aa335cd976b8209145d670a6dba17471f6a4f47dacaa432dd972d801c04000000009000000001c62401000000000016001401396601573e7aef81f91a89fc4b4b56feb7a35e03483045022100c787b74c895285a11e04a680a50cef980d74a1ea53998bc2abaa2f7e13b6131b02204e0a8216f2efe89880feac989f9b0cfbf6aea1a61444d453d5547060aa65cc5901004d632103d6a391d54b9683da5c4c1ab1720739757422861b7ca98da226118061b40c412e67029000b2752102f2b77c73154588dfa6301b6c69062c0a713467996542a836f7a2ce6a239ba68868ac0000000000000004fd017a02000000000101efa7874aa335cd976b8209145d670a6dba17471f6a4f47dacaa432dd972d801c000000000000000000013a34000000000000220020680a82e78074810847ca530cd74fabdbd2e34beaf0fdd2bc832ddfcd2669876c050047304402201f096356d49cb9c0d1dad9a01530aa892aa75cdcb626f42ef09b734f39d0a26502200d6274377598b29f3f3eae1281a8b61d5cb9853b478cc973b8035af5d60c26a00148304502210093d252d2f22cecee6c2b604a1190120db574f0ba33b49ac826229b95071230bd02207a4baa7a1704813804ba9b7d0e2aef3932a7d7d096862c1636736ad3296a46f501008576a9144a2fe35d15fdacd3b3cba332b5879b6acfb2e79f8763ac67210375099d4e25580f8d2c59718d7319e9d26c7119f9476ca3a623fb638843d3c8617c820120876475527c210375f5c7f3e5f1da49febb149cb9dc97098402628f84b79b586d5d516c17e6327852ae67a914950b69c651378982bec084b296e6dd23a33c41b588ac6868111b0600fd017a02000000000101efa7874aa335cd976b8209145d670a6dba17471f6a4f47dacaa432dd972d801c01000000000000000001c247000000000000220020680a82e78074810847ca530cd74fabdbd2e34beaf0fdd2bc832ddfcd2669876c050048304502210088605547607e6c8b1b24a671ed340700ad396a8bf613fa9e4646c0b11c2aeff7022008e4448ba70fe48903e3034ace605d8651091fcd6f80fddb57d2e2b09da6765d014730440220774ca3fbbee6dc29db89dbb2bdb977afdf31727548aa6060e9e23a79090bf6580220474a5aa2de53dae36371ec535e13e4291c9fbd1942e7cc812ff4ca4c9d84483c01008576a9144a2fe35d15fdacd3b3cba332b5879b6acfb2e79f8763ac67210375099d4e25580f8d2c59718d7319e9d26c7119f9476ca3a623fb638843d3c8617c820120876475527c210375f5c7f3e5f1da49febb149cb9dc97098402628f84b79b586d5d516c17e6327852ae67a914950b69c651378982bec084b296e6dd23a33c41b588ac6868101b0600fd017902000000000101efa7874aa335cd976b8209145d670a6dba17471f6a4f47dacaa432dd972d801c020000000000000000014a5b000000000000220020680a82e78074810847ca530cd74fabdbd2e34beaf0fdd2bc832ddfcd2669876c050047304402202c736579e487f2ceedb15546a438818e9a13d3b9f9232d4ff418855f9112795e02202bce08fb52f8737268b616158eeb06e36abdc83942396fb407d3e603ed1edd7b0147304402204ec5ef779e7b0db022d9da0986bee62eeb0372337f3974e0bfa8ecbddec7a3ed022047930ce5ca6796d3cde21dbf9e0678f4d0af5d84889c24e2b960786d141b900a01008576a9144a2fe35d15fdacd3b3cba332b5879b6acfb2e79f8763ac67210375099d4e25580f8d2c59718d7319e9d26c7119f9476ca3a623fb638843d3c8617c820120876475527c210375f5c7f3e5f1da49febb149cb9dc97098402628f84b79b586d5d516c17e6327852ae67a914950b69c651378982bec084b296e6dd23a33c41b588ac6868101b0600fd017a02000000000101efa7874aa335cd976b8209145d670a6dba17471f6a4f47dacaa432dd972d801c030000000000000000014a5b000000000000220020680a82e78074810847ca530cd74fabdbd2e34beaf0fdd2bc832ddfcd2669876c050047304402204f63e06d948b7890c8a3fb1ae568e88de8cd4ef3364c092bcdeb006c40558b0802202a5fc572f9f02f5d2a0870101ff7d900da184fb19b5cd410ba0779bc55533c4a01483045022100ff0a3853c07d426ac93a8b772017a41f324558851ec69bcd65ed1cd81490e0f102201c3c01574fe196df6311cf21fbb78abd7d40659479ea080c7ccb3c5fd53027df01008576a9144a2fe35d15fdacd3b3cba332b5879b6acfb2e79f8763ac67210375099d4e25580f8d2c59718d7319e9d26c7119f9476ca3a623fb638843d3c8617c820120876475527c210375f5c7f3e5f1da49febb149cb9dc97098402628f84b79b586d5d516c17e6327852ae67a914950b69c651378982bec084b296e6dd23a33c41b588ac6868101b06000004ec02000000000101ea542e3a509a29b8d2afac84f21bc8f4e100df901b35c9fc19a331c588683519000000000090000000015c2100000000000016001401396601573e7aef81f91a89fc4b4b56feb7a35e034730440220359f29d38879b19665015a2b85bd60e4e3949292f75d2294d5a545aa392dd1fd022036aa2b42bdedd9deca319eece3e8a5670fe89e78231e1025b9fc1079a931398d01004d632103d6a391d54b9683da5c4c1ab1720739757422861b7ca98da226118061b40c412e67029000b2752102f2b77c73154588dfa6301b6c69062c0a713467996542a836f7a2ce6a239ba68868ac00000000ed02000000000101374c80d9d5213e7bf0ea94c3a8085866a4d533590d89f68e829162d03d431a2600000000009000000001e43400000000000016001401396601573e7aef81f91a89fc4b4b56feb7a35e03483045022100d486e826ecfddcc474b719cb69e641efe97b4795b8ea4bb9729237788a3d35ed022051b097591bfc53dc855303672e17ad8488de9f2bcca670995060f331a7dfe55e01004d632103d6a391d54b9683da5c4c1ab1720739757422861b7ca98da226118061b40c412e67029000b2752102f2b77c73154588dfa6301b6c69062c0a713467996542a836f7a2ce6a239ba68868ac00000000ed02000000000101a436af3ff69624fd11b543c0b8d451190bcb7891a7259832cb64445571dc3003000000000090000000016c4800000000000016001401396601573e7aef81f91a89fc4b4b56feb7a35e03483045022100c203f2093d4b182ba5b78a471f806acf13c4d44f7191068abaf2b7a6742f427e02200fabe2a24e947f467a48fca7bba3ed68387ce46c32533366d99a52cefb0e3ad801004d632103d6a391d54b9683da5c4c1ab1720739757422861b7ca98da226118061b40c412e67029000b2752102f2b77c73154588dfa6301b6c69062c0a713467996542a836f7a2ce6a239ba68868ac00000000ec020000000001013798507505fc7de865bccaad655dc03b3899bba86e139dfbc543a2a2f9b4b842000000000090000000016c4800000000000016001401396601573e7aef81f91a89fc4b4b56feb7a35e034730440220724b0e5a340e80de26f3908ae510a34c93b5632dbd539c1a155856cad5375ac402203de9139fbaadd86a11168c612b75f974a6143e68c564de77c8b350f2978ff2f901004d632103d6a391d54b9683da5c4c1ab1720739757422861b7ca98da226118061b40c412e67029000b2752102f2b77c73154588dfa6301b6c69062c0a713467996542a836f7a2ce6a239ba68868ac0000000000000000000000" - assert(JsonSerializers.serialization.write(ChannelCodecs.stateDataCodec.decode(dataNormal.bits).require.value)(JsonSerializers.formats).contains(""""type":"DATA_NORMAL"""")) - assert(JsonSerializers.serialization.write(ChannelCodecs.stateDataCodec.decode(dataWaitForFundingConfirmed.bits).require.value)(JsonSerializers.formats).contains(""""type":"DATA_WAIT_FOR_FUNDING_CONFIRMED"""")) - assert(JsonSerializers.serialization.write(ChannelCodecs.stateDataCodec.decode(dataShutdown.bits).require.value)(JsonSerializers.formats).contains(""""type":"DATA_SHUTDOWN"""")) - assert(JsonSerializers.serialization.write(ChannelCodecs.stateDataCodec.decode(dataNegotiating.bits).require.value)(JsonSerializers.formats).contains(""""type":"DATA_NEGOTIATING"""")) - assert(JsonSerializers.serialization.write(ChannelCodecs.stateDataCodec.decode(dataClosingLocal.bits).require.value)(JsonSerializers.formats).contains(""""type":"DATA_CLOSING"""")) + assert(JsonSerializers.serialization.write(ChannelCodecs.channelDataCodec.decode(dataNormal.bits).require.value)(JsonSerializers.formats).contains(""""type":"DATA_NORMAL"""")) + assert(JsonSerializers.serialization.write(ChannelCodecs.channelDataCodec.decode(dataWaitForFundingConfirmed.bits).require.value)(JsonSerializers.formats).contains(""""type":"DATA_WAIT_FOR_FUNDING_CONFIRMED"""")) + assert(JsonSerializers.serialization.write(ChannelCodecs.channelDataCodec.decode(dataShutdown.bits).require.value)(JsonSerializers.formats).contains(""""type":"DATA_SHUTDOWN"""")) + assert(JsonSerializers.serialization.write(ChannelCodecs.channelDataCodec.decode(dataNegotiating.bits).require.value)(JsonSerializers.formats).contains(""""type":"DATA_NEGOTIATING"""")) + assert(JsonSerializers.serialization.write(ChannelCodecs.channelDataCodec.decode(dataClosingLocal.bits).require.value)(JsonSerializers.formats).contains(""""type":"DATA_CLOSING"""")) } diff --git a/eclair-core/src/test/scala/fr/acinq/eclair/wire/internal/channel/ChannelCodecsSpec.scala b/eclair-core/src/test/scala/fr/acinq/eclair/wire/internal/channel/ChannelCodecsSpec.scala index 06b1749447..5e2259cbf2 100644 --- a/eclair-core/src/test/scala/fr/acinq/eclair/wire/internal/channel/ChannelCodecsSpec.scala +++ b/eclair-core/src/test/scala/fr/acinq/eclair/wire/internal/channel/ChannelCodecsSpec.scala @@ -48,7 +48,7 @@ class ChannelCodecsSpec extends AnyFunSuite { test("nonreg for der/bin64 signatures") { val bin = ByteVector.fromValidHex(Source.fromInputStream(getClass.getResourceAsStream("/normal_data_htlcs.bin")).mkString) - val c = ChannelCodecs.stateDataCodec.decode(bin.toBitVector).require.value + val c = ChannelCodecs.channelDataCodec.decode(bin.toBitVector).require.value val ref = Seq( hex"304502210097fcda40b22916b5d61badedf6126658c2b5927d5002cc2c3e5f88a78ba5f45b02204a74bcf8827d894cab153fc051f39d8e2aeb660162a6a05797f7140587a6133301", @@ -86,15 +86,15 @@ class ChannelCodecsSpec extends AnyFunSuite { // currently version=0 and discriminator type=1 assert(bin_old.startsWith(hex"000001")) // let's decode the old data (this will use the old codec that provides default values for new fields) - val data_new = stateDataCodec.decode(bin_old.toBitVector).require.value + val data_new = channelDataCodec.decode(bin_old.toBitVector).require.value assert(data_new.asInstanceOf[DATA_WAIT_FOR_FUNDING_CONFIRMED].fundingTx === None) assert(TimestampSecond.now().toLong - data_new.asInstanceOf[DATA_WAIT_FOR_FUNDING_CONFIRMED].waitingSince.toLong < 3600) // we just set this to current time // and re-encode it with the new codec - val bin_new = ByteVector(stateDataCodec.encode(data_new).require.toByteVector.toArray) + val bin_new = ByteVector(channelDataCodec.encode(data_new).require.toByteVector.toArray) // data should now be encoded under the new format assert(bin_new.startsWith(hex"030000")) // now let's decode it again - val data_new2 = stateDataCodec.decode(bin_new.toBitVector).require.value + val data_new2 = channelDataCodec.decode(bin_new.toBitVector).require.value // data should match perfectly assert(data_new === data_new2) } @@ -120,13 +120,13 @@ class ChannelCodecsSpec extends AnyFunSuite { // check that this data has been encoded with the old 0x03 codec assert(oldbin.startsWith(hex"000003")) // we decode with compat codec - val oldnormal = stateDataCodec.decode(oldbin.bits).require.value + val oldnormal = channelDataCodec.decode(oldbin.bits).require.value // and we encode with new codec - val newbin = stateDataCodec.encode(oldnormal).require.bytes + val newbin = channelDataCodec.encode(oldnormal).require.bytes // make sure that encoding used the new codec assert(newbin.startsWith(hex"030007")) // make sure that round-trip yields the same data - val newnormal = stateDataCodec.decode(newbin.bits).require.value + val newnormal = channelDataCodec.decode(newbin.bits).require.value assert(newnormal === oldnormal) } } @@ -144,11 +144,11 @@ class ChannelCodecsSpec extends AnyFunSuite { refs.foreach { case (oldbin, refjson) => // we decode with compat codec - val oldnormal = stateDataCodec.decode(oldbin.bits).require.value + val oldnormal = channelDataCodec.decode(oldbin.bits).require.value // we then encode with new codec - val newbin = stateDataCodec.encode(oldnormal).require.bytes + val newbin = channelDataCodec.encode(oldnormal).require.bytes // and we decode with the new codec - val newnormal = stateDataCodec.decode(newbin.bits).require.value + val newnormal = channelDataCodec.decode(newbin.bits).require.value // finally we check that the actual data is the same as before (we just remove the new json field) val oldjson = Serialization.write(oldnormal)(JsonSerializers.formats) val newjson = Serialization.write(newnormal)(JsonSerializers.formats) @@ -171,41 +171,41 @@ class ChannelCodecsSpec extends AnyFunSuite { // check that this data has been encoded with the old codec assert(oldBin.startsWith(hex"0100")) // we decode with the new codec - val decoded1 = stateDataCodec.decode(oldBin.bits).require.value + val decoded1 = channelDataCodec.decode(oldBin.bits).require.value // and we encode with the new codec - val newBin = stateDataCodec.encode(decoded1).require.bytes + val newBin = channelDataCodec.encode(decoded1).require.bytes // make sure that encoding used the new codec assert(newBin.startsWith(hex"0300")) // make sure that round-trip yields the same data - val decoded2 = stateDataCodec.decode(newBin.bits).require.value + val decoded2 = channelDataCodec.decode(newBin.bits).require.value assert(decoded1 === decoded2) }) - val negotiating = stateDataCodec.decode(dataNegotiating.bits).require.value.asInstanceOf[DATA_NEGOTIATING] + val negotiating = channelDataCodec.decode(dataNegotiating.bits).require.value.asInstanceOf[DATA_NEGOTIATING] assert(negotiating.bestUnpublishedClosingTx_opt.nonEmpty) negotiating.bestUnpublishedClosingTx_opt.foreach(tx => assert(tx.toLocalOutput === None)) assert(negotiating.closingTxProposed.flatten.nonEmpty) negotiating.closingTxProposed.flatten.foreach(tx => assert(tx.unsignedTx.toLocalOutput === None)) - val normal = stateDataCodec.decode(dataNormal.bits).require.value.asInstanceOf[DATA_NORMAL] + val normal = channelDataCodec.decode(dataNormal.bits).require.value.asInstanceOf[DATA_NORMAL] assert(normal.commitments.localCommit.htlcTxsAndRemoteSigs.nonEmpty) normal.commitments.localCommit.htlcTxsAndRemoteSigs.foreach(tx => assert(tx.htlcTx.htlcId === 0)) - val closingLocal = stateDataCodec.decode(dataClosingLocal.bits).require.value.asInstanceOf[DATA_CLOSING] + val closingLocal = channelDataCodec.decode(dataClosingLocal.bits).require.value.asInstanceOf[DATA_CLOSING] assert(closingLocal.localCommitPublished.nonEmpty) assert(closingLocal.localCommitPublished.get.commitTx.txOut.size === 6) assert(closingLocal.localCommitPublished.get.htlcTxs.size === 4) assert(closingLocal.localCommitPublished.get.claimHtlcDelayedTxs.size === 4) assert(closingLocal.localCommitPublished.get.irrevocablySpent.isEmpty) - val closingRemote = stateDataCodec.decode(dataClosingRemote.bits).require.value.asInstanceOf[DATA_CLOSING] + val closingRemote = channelDataCodec.decode(dataClosingRemote.bits).require.value.asInstanceOf[DATA_CLOSING] assert(closingRemote.remoteCommitPublished.nonEmpty) assert(closingRemote.remoteCommitPublished.get.commitTx.txOut.size === 7) assert(closingRemote.remoteCommitPublished.get.commitTx.txOut.count(_.amount === AnchorOutputsCommitmentFormat.anchorAmount) === 2) assert(closingRemote.remoteCommitPublished.get.claimHtlcTxs.size === 3) assert(closingRemote.remoteCommitPublished.get.irrevocablySpent.isEmpty) - val closingRevoked = stateDataCodec.decode(dataClosingRevoked.bits).require.value.asInstanceOf[DATA_CLOSING] + val closingRevoked = channelDataCodec.decode(dataClosingRevoked.bits).require.value.asInstanceOf[DATA_CLOSING] assert(closingRevoked.revokedCommitPublished.size === 1) assert(closingRevoked.revokedCommitPublished.head.commitTx.txOut.size === 6) assert(closingRevoked.revokedCommitPublished.head.htlcPenaltyTxs.size === 4) @@ -231,11 +231,11 @@ class ChannelCodecsSpec extends AnyFunSuite { oldbins.foreach { oldbin => // we decode with compat codec - val oldnormal = stateDataCodec.decode(oldbin.bits).require.value + val oldnormal = channelDataCodec.decode(oldbin.bits).require.value // and we encode with new codec - val newbin = stateDataCodec.encode(oldnormal).require.bytes + val newbin = channelDataCodec.encode(oldnormal).require.bytes // make sure that round-trip yields the same data - val newnormal = stateDataCodec.decode(newbin.bits).require.value + val newnormal = channelDataCodec.decode(newbin.bits).require.value assert(newnormal === oldnormal) // make sure that we have stripped sigs from the transactions assert(newnormal.commitments.localCommit.commitTxAndRemoteSig.commitTx.tx.txIn.forall(_.witness.stack.isEmpty)) diff --git a/eclair-core/src/test/scala/fr/acinq/eclair/wire/internal/channel/version2/ChannelCodecs2Spec.scala b/eclair-core/src/test/scala/fr/acinq/eclair/wire/internal/channel/version2/ChannelCodecs2Spec.scala index 13100f6299..9072ec4de7 100644 --- a/eclair-core/src/test/scala/fr/acinq/eclair/wire/internal/channel/version2/ChannelCodecs2Spec.scala +++ b/eclair-core/src/test/scala/fr/acinq/eclair/wire/internal/channel/version2/ChannelCodecs2Spec.scala @@ -3,7 +3,7 @@ package fr.acinq.eclair.wire.internal.channel.version2 import fr.acinq.bitcoin.scalacompat.{ByteVector64, OutPoint, Transaction} import fr.acinq.eclair.channel.{ChannelConfig, ChannelFeatures, HtlcTxAndRemoteSig} import fr.acinq.eclair.wire.internal.channel.version2.ChannelCodecs2.Codecs._ -import fr.acinq.eclair.wire.internal.channel.version2.ChannelCodecs2.stateDataCodec +import fr.acinq.eclair.wire.internal.channel.version2.ChannelCodecs2.channelDataCodec import fr.acinq.eclair.{FeatureSupport, Features, randomBytes32} import org.scalatest.funsuite.AnyFunSuite import scodec.bits.HexStringSyntax @@ -24,7 +24,7 @@ class ChannelCodecs2Spec extends AnyFunSuite { } test("remove signatures from commitment txs") { - val commitments = stateDataCodec.decode(dataNormal.bits).require.value.commitments + val commitments = channelDataCodec.decode(dataNormal.bits).require.value.commitments commitments.localCommit.commitTxAndRemoteSig.commitTx.tx.txIn.foreach(txIn => assert(txIn.witness.isNull)) assert(commitments.localCommit.htlcTxsAndRemoteSigs.nonEmpty) commitments.localCommit.htlcTxsAndRemoteSigs.foreach { @@ -37,32 +37,32 @@ class ChannelCodecs2Spec extends AnyFunSuite { test("split channel version into channel config and channel features") { { // Standard channel - val commitments = stateDataCodec.decode(dataNormal.bits).require.value.commitments + val commitments = channelDataCodec.decode(dataNormal.bits).require.value.commitments assert(commitments.channelConfig === ChannelConfig.standard) assert(commitments.channelFeatures === ChannelFeatures()) } { val staticRemoteKeyChannel = hex"000200000003039dc0e0b1d25905e44fdf6f8e89755a5e219685840d0bc1d28d3308f9628a358500092eaee758da6a5beab04167c5b889732a98ec556cf92689da41744b10159ace488000000000000000000003e8ffffffffffffffff0000000000004e2000000000000003e80090001e001600140a46fc26a4ef7b50aaf16759d2f0ca8b014fd0a6028feba10d0eafd0fad8fe20e6d9206e6bd30242826de05c63f459a00aced24b120000000302698203af0ed6052cf28d670665549bc86f4b721c9fdb309d40c58f5811f63966e005d0000000000000044c000000001dcd6500000000000000271000000000000000000090006402a87d8f1844a3809284885b41cfc9713a561780b2b784a7a027851f68aaa838730328e2fd423323abcd86b15335ff44679068acd4db71b8052f63a2a7f0b47432bd028feba10d0eafd0fad8fe20e6d9206e6bd30242826de05c63f459a00aced24b12025ee0984b83efe2369c23c3754e89d19905f8094a86486de3b241cf8735208292031163dfd4eee879b9a333290cf10e52eb010d1da45bd44efee6fab16d1035120c0000186b02000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000269820000000000000000010001fffd05aab125c87884677613fe191e097b3806667482e0ff7668c64bca637300fe02307200000000000000000000000002faf080a2fbf30338f78b739d2b0a0a806506d6877408a995791901c43f6ef98d8a7a2e00061b10000223bb38126f1131ad95b37e0b30adf0ae315f66f8cf7460afccba393fa848d036073b6577f39b0e54043691e2eec74f46b86584ffab7aa01d15e6a7ff5ff9d7c60d095c7952a19e263c267f94fbe0208fdd212b304fa8d3df1379017d184fbcce7ffd5175997774c9de7ef2f3733c7056a22888c9f302e4a9bac35f581d4f571a7ef29e6cf3b1d8a7cc05cd155a047ae498a18fccb6589338242d91e00493a86b2b78810de20644f0f065399894854bd7347927a0ce8f9c1102c9c7227ffba4b71c4325f301933397aa8f54a28d3844c71021d19b72795141af019c9a0abae3e2cc29033b7f8be8465ac8406d4c1d61d0bc3c87dee2faac4d649fc166917c81a1e237c91d5c8091f696a72241c67047cfcec893bb41e97753b3d362695bc31f776cd4a744bf09f2e428dc189fa4838f34d130d5fd4fc3d79bc7546d30d543ca99818a8c39f6c17e74ff45976c95fd6de261d68e2c5fc585d28fa9ae5abb1db475f24d16d9cb0562a589c6dec07f3b81a37b4c7f2c4642df1fabf5d7343e038706e786d2cea71f76663f57a88751287db3f8e9a7a896990374daf72eb776ee67c9ec61c1a10f164688ecbc88caa086e24daa79808899e3c3f6870ed326f5253fc038147774fa8795351f44cbadc53b67743822b89f27f0c03b2b0f4e4c774598db681cadde0e4e28f1f4edbbc8ec68649fe05e3c8cdbc46b07011c9b81b9cb3ad92ec08ddf8209a501ce064ee0bd9befce196c0c559cffcb3b0c447922ad50fbceb288037ec36abb17d93deebd40e83d8c197248b14ee12dcfe72e46f0826ef1e6e94700ad6428df77b54eb8ca767af1fd84507adc52beef32f48e3968c24d990d04cd8b35c87e270a04e2e8fc9d0ab6a6398c2168986321cc0dc297f8e0e4887226db20958e934bc35151de72d896511e3b850d548402a0e1f32fb01d5050a8ff9d7ba6818600a2dafa1c4b3ca11c0d091796190c05a1edc8146d7ef534d67bb39f76f37279dff6be5e053b7315c3f3406e9240c6b618b18545fccb46d668c007a1b640634c663bbd27c5d00a48f5c3702bac6202b55cce4212920be059ecf708db85f07c0fcc0f480fcd06aef1128fc491b2b384d89ce15120c81bd65c225d679f8cd38fb1b0ddb7d8edd3455506fa3406578f43ba4caab00593b6623b7b69c863409f0350b8b8783b9ee2ada9b9f410ab309527b7f67758f543261f52695da19e597f9457483d188e8a2bd7248a6ee5f2d01cccacd2561239959f0ce80cbb83503891a8b4e3ab88d3a02de5f8c784c0700e8bef68445615f25dd3d5baea34bc8e694a7282b054f99fa2b150af00ec62c2fd2227a23e0c0a36090b5986271f964e969cc9313ef42c3b7a9ff9e608342c73da023019e983ee6b6f630e12a02ae79802bfbee10ba20199895d7f1302d2c3b8d7ba6ad08cbb27265f9bb709bf6225a81bdabf7fc5fe9ee4794b00181038051cae0a52c08d8a7750ee46c99b7dd6cd452c52a347f12873dc697786b89ddd13e2d584aa3244cdbdb7809bc7a42728d756485070ff84aaba81b1506a7b20d2acfef11df724ee78e8b0f92376676d1e01aed7ad8d84919b8296684dafc152680b0f964db5a1b7ee4093f453fe24750c6857252e4befef3df2d648e32cc20c1ef48fd5865c242951cd359f92985680f0d626602f164b6285971a194a4baf4eb1d9a3e88841269b3e84a96e6784407f869bca5db2bb2d31e784c35e210dcaf5d3441edea9a4a348e3ead6c9b920e1ff8f1c76c41d564827cd3db006e741a8dbb5db9bdbe13033faac7e6b676bc1cf88677d10676ddca3e187caeeac52b69212503f7acca29a49c699d68f0d982c4c41806c8d9bbbc4e7d2d77a1a0655c73cfcd21b93d95e70d2bad6c306dc172b67120335bd2d03878b3d9e5967c54dd567d307c15e305b5200002710000000000bebc200000000002cb4178024b125c87884677613fe191e097b3806667482e0ff7668c64bca637300fe023072000000002b40420f000000000022002090750411c84891017ca3ab8e6212a198dbf957143d6753f7b48264c7faf45cf44752210257f2ca56049071462716385481d04d3c7c859d7e9b3f31c019b126aa0eeed1e82102a87d8f1844a3809284885b41cfc9713a561780b2b784a7a027851f68aaa8387352aefd018602000000000101b125c87884677613fe191e097b3806667482e0ff7668c64bca637300fe023072000000000036a2ab800350c300000000000022002042ee833f99ec58f28a3ffc13033c29d4e02f72f6169e0e8e039ad9323e912e30400d030000000000220020981c45edf62e238461337b25d5fd7de72a305e7f4c7755a693f877b1a564831cb04e0b0000000000160014761879f7b274ce995f87150a02e75cc0c037e8e30400483045022100dc11d7761cdf7c708ea2aaaed409a4d24697bb07948704e77b7cbe911d0268fd02204a81721e85bb1ff6cb34741ed5c5ee89c4ea8f5bb1515792625d32043682c14301483045022100af2d760500664483ea81ccaa3bc925c5587cd3cd4358ee27110f62929903c49602201ce1a97498227eaef1ab5c04da2eb9ea8114abe6af1bd35494d9cbb0e64da3e7014752210257f2ca56049071462716385481d04d3c7c859d7e9b3f31c019b126aa0eeed1e82102a87d8f1844a3809284885b41cfc9713a561780b2b784a7a027851f68aaa8387352aead678920000101241bfa1a637efc49b76b41be6ec36c47c546f69b1646a11e8420957a1dbf731487000000002b50c300000000000022002042ee833f99ec58f28a3ffc13033c29d4e02f72f6169e0e8e039ad9323e912e308b76a91420fe4794a7f993489c0477c442fed3be2c9294678763ac67210230714b6385889be70b5299603fbc508a01517a3b754d03e33e5bcf125104adc57c8201208763a914e5a9c4cf993e5053ca47ddd2a194a3c522c1fdc588527c2103bff704aae937cd0b98704a4791140cab835c5bd2406897104602c881352869ae52ae677503101b06b175ac68685e02000000011bfa1a637efc49b76b41be6ec36c47c546f69b1646a11e8420957a1dbf73148700000000000000000001daa7000000000000220020981c45edf62e238461337b25d5fd7de72a305e7f4c7755a693f877b1a564831c00000000a2fbf30338f78b739d2b0a0a806506d6877408a995791901c43f6ef98d8a7a2e000000000000000040c5c678fda30c1e23bbb68093b1d9a34169304ff3d36bfef74157f129df8d01e31ddcd8dd04f3ac9521ac13b7fed5d7997ce0c72c942054711d924ea197c7ab7640cd0045f41ffd38fa637cfc09679c628b29a8273223db1150e262d5159cf5d7852542c4ad7334f67d08ca835cd5b16b1df96544c454dff121856685471d2255300000000000000001000100fd05aab125c87884677613fe191e097b3806667482e0ff7668c64bca637300fe02307200000000000000000000000002faf080a2fbf30338f78b739d2b0a0a806506d6877408a995791901c43f6ef98d8a7a2e00061b10000223bb38126f1131ad95b37e0b30adf0ae315f66f8cf7460afccba393fa848d036073b6577f39b0e54043691e2eec74f46b86584ffab7aa01d15e6a7ff5ff9d7c60d095c7952a19e263c267f94fbe0208fdd212b304fa8d3df1379017d184fbcce7ffd5175997774c9de7ef2f3733c7056a22888c9f302e4a9bac35f581d4f571a7ef29e6cf3b1d8a7cc05cd155a047ae498a18fccb6589338242d91e00493a86b2b78810de20644f0f065399894854bd7347927a0ce8f9c1102c9c7227ffba4b71c4325f301933397aa8f54a28d3844c71021d19b72795141af019c9a0abae3e2cc29033b7f8be8465ac8406d4c1d61d0bc3c87dee2faac4d649fc166917c81a1e237c91d5c8091f696a72241c67047cfcec893bb41e97753b3d362695bc31f776cd4a744bf09f2e428dc189fa4838f34d130d5fd4fc3d79bc7546d30d543ca99818a8c39f6c17e74ff45976c95fd6de261d68e2c5fc585d28fa9ae5abb1db475f24d16d9cb0562a589c6dec07f3b81a37b4c7f2c4642df1fabf5d7343e038706e786d2cea71f76663f57a88751287db3f8e9a7a896990374daf72eb776ee67c9ec61c1a10f164688ecbc88caa086e24daa79808899e3c3f6870ed326f5253fc038147774fa8795351f44cbadc53b67743822b89f27f0c03b2b0f4e4c774598db681cadde0e4e28f1f4edbbc8ec68649fe05e3c8cdbc46b07011c9b81b9cb3ad92ec08ddf8209a501ce064ee0bd9befce196c0c559cffcb3b0c447922ad50fbceb288037ec36abb17d93deebd40e83d8c197248b14ee12dcfe72e46f0826ef1e6e94700ad6428df77b54eb8ca767af1fd84507adc52beef32f48e3968c24d990d04cd8b35c87e270a04e2e8fc9d0ab6a6398c2168986321cc0dc297f8e0e4887226db20958e934bc35151de72d896511e3b850d548402a0e1f32fb01d5050a8ff9d7ba6818600a2dafa1c4b3ca11c0d091796190c05a1edc8146d7ef534d67bb39f76f37279dff6be5e053b7315c3f3406e9240c6b618b18545fccb46d668c007a1b640634c663bbd27c5d00a48f5c3702bac6202b55cce4212920be059ecf708db85f07c0fcc0f480fcd06aef1128fc491b2b384d89ce15120c81bd65c225d679f8cd38fb1b0ddb7d8edd3455506fa3406578f43ba4caab00593b6623b7b69c863409f0350b8b8783b9ee2ada9b9f410ab309527b7f67758f543261f52695da19e597f9457483d188e8a2bd7248a6ee5f2d01cccacd2561239959f0ce80cbb83503891a8b4e3ab88d3a02de5f8c784c0700e8bef68445615f25dd3d5baea34bc8e694a7282b054f99fa2b150af00ec62c2fd2227a23e0c0a36090b5986271f964e969cc9313ef42c3b7a9ff9e608342c73da023019e983ee6b6f630e12a02ae79802bfbee10ba20199895d7f1302d2c3b8d7ba6ad08cbb27265f9bb709bf6225a81bdabf7fc5fe9ee4794b00181038051cae0a52c08d8a7750ee46c99b7dd6cd452c52a347f12873dc697786b89ddd13e2d584aa3244cdbdb7809bc7a42728d756485070ff84aaba81b1506a7b20d2acfef11df724ee78e8b0f92376676d1e01aed7ad8d84919b8296684dafc152680b0f964db5a1b7ee4093f453fe24750c6857252e4befef3df2d648e32cc20c1ef48fd5865c242951cd359f92985680f0d626602f164b6285971a194a4baf4eb1d9a3e88841269b3e84a96e6784407f869bca5db2bb2d31e784c35e210dcaf5d3441edea9a4a348e3ead6c9b920e1ff8f1c76c41d564827cd3db006e741a8dbb5db9bdbe13033faac7e6b676bc1cf88677d10676ddca3e187caeeac52b69212503f7acca29a49c699d68f0d982c4c41806c8d9bbbc4e7d2d77a1a0655c73cfcd21b93d95e70d2bad6c306dc172b67120335bd2d03878b3d9e5967c54dd567d307c15e305b5200002710000000002cb41780000000000bebc200b5c42b5c67eb6043b2776c0e9a8bd91d8ffdf7280b81dce825558ad5258746fb030d9b4186ad4f32aae9ca90701dc66e8df3f7b73e1f9590c0f6cd690aae8ad097000000000000000000000000000000000000000000000000000000010000ff0250b3cac5267f9448efcb8c2a89944f8bb4e4e7f1a3ae72d4961dfe187105b3f324b125c87884677613fe191e097b3806667482e0ff7668c64bca637300fe023072000000002b40420f000000000022002090750411c84891017ca3ab8e6212a198dbf957143d6753f7b48264c7faf45cf44752210257f2ca56049071462716385481d04d3c7c859d7e9b3f31c019b126aa0eeed1e82102a87d8f1844a3809284885b41cfc9713a561780b2b784a7a027851f68aaa8387352ae000100400000ffffffffffff0020b0e394cbe4d79e47a73926b89d17d8835e8f042d7adb244a84b6c30496c6355f80007fffffffffff80b125c87884677613fe191e097b3806667482e0ff7668c64bca637300fe023072061a8000002a00000000888bc37730827b0ccb54f13689babb8d211a6cbbec55113caad14a97f6bfce7d85313c9cefa398d15213abf841e3c9a8b88f62fa3fc742a6c746619d3e76aa71fb06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f061a8000002a000060e32b8d010000900000000000000000000854d00000000a000000003b9aca000000" - val commitments = stateDataCodec.decode(staticRemoteKeyChannel.bits).require.value.commitments + val commitments = channelDataCodec.decode(staticRemoteKeyChannel.bits).require.value.commitments assert(commitments.channelConfig === ChannelConfig.standard) assert(commitments.channelFeatures === ChannelFeatures(Features.StaticRemoteKey)) } { val anchorOutputsChannel = hex"00020000000703af0ed6052cf28d670665549bc86f4b721c9fdb309d40c58f5811f63966e005d000094b82816a3f15ab3e324ddf6f0f5a116cef8c3200a353240db684337d2dcaa81e80000001000000000000044c000000001dcd65000000000000002710000000000000000000900064ff160014f09f6f93de60c6af417ed31d52c2c883b6113f260000186b0200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000225982039dc0e0b1d25905e44fdf6f8e89755a5e219685840d0bc1d28d3308f9628a358500000000000003e8ffffffffffffffff0000000000004e2000000000000003e80090001e02e9cd12509fbc345c10e2b2e10427ae43eabbf0788bda8118b34344e5576d5d5002eb112dd8d61a02bf3434d5417e1020ed2d951e75bd1e14615d473dd5f1991b4402ca8b6891d6a53aea035259fa0d57a1e672d3cc59a2c696a96247d3557ee726cd030f2aa0ca0ae0e00d6da847d897cf7288ae286dd12037f06250937dc7b37fe0b5028d59e68c5799980a98b120acb891dabfd091e80c6596b0c2a7de57a298d48512000000032259820000000000000000000000000009c4000000002faf0800000000000bebc2002432e16e6e875d1f02a9512943ba2eb9309f4715390b52e4965dd6e39a2989ae63000000002b40420f00000000002200204de81ee2e9850dabdb9c364a12cc2dd75dd20c21d4ca0a809a2e6af3caeeaf9647522102e9cd12509fbc345c10e2b2e10427ae43eabbf0788bda8118b34344e5576d5d502103683425bf640d5e4338553ca6f6afea948ff2bf378eed1b3e9497a3f18f477d5352aefd01bc0200000000010132e16e6e875d1f02a9512943ba2eb9309f4715390b52e4965dd6e39a2989ae63000000000089273f80044a010000000000002200202102815a0b14d50a2a8c028cd47413e743f02ad5460151bd4ae5930639cbbd484a010000000000002200204e81bd6470c45c349068c2b0ad544934b718ef49c1615f2a0b0cd8766400b562400d0300000000002200208eadab92c95168438acfb73f2d3d92f56d6fc30d3f79fc4527f4e77df88b8add72270c0000000000220020895c0fef7efb7aa0e4805381434363b30386d31f6cb621abb0ca4a52b269fbc304004830450221009f09a584b1af9ba86f1618aad1ca9817324f97c3d3789b2490c3b9435c7bf1dd02205e4dcca3d7937f6b80a0ed39084e4ea9e9c531b80698ebd0c116fd9319a0db1201473044022001e4104ec25ba9bc43bf3f623d6e98f371434442b134255667ddeedd9cd9cd1b02201f057d2c15ee4e5d62a73f1db262846ca7ad35deaed2496abdb5b16cd91c5cb80147522102e9cd12509fbc345c10e2b2e10427ae43eabbf0788bda8118b34344e5576d5d502103683425bf640d5e4338553ca6f6afea948ff2bf378eed1b3e9497a3f18f477d5352ae25899520000000000000000000000000000009c4000000000bebc200000000002faf0800acdb0bf90ed7350d429c2d70fce66300ac9b27d8dbb3bceb5bd2cc8bd443938f03f54d00601f1b95e82836540d760ab6b38bc6fc1701df5d5e3b410f1936212d54000000000000000000000000000000000000000000000000000000000000ff03658b1e02efd8464688f87a052518691ff4d818a7c36addf4c6520ae07b7e20912432e16e6e875d1f02a9512943ba2eb9309f4715390b52e4965dd6e39a2989ae63000000002b40420f00000000002200204de81ee2e9850dabdb9c364a12cc2dd75dd20c21d4ca0a809a2e6af3caeeaf9647522102e9cd12509fbc345c10e2b2e10427ae43eabbf0788bda8118b34344e5576d5d502103683425bf640d5e4338553ca6f6afea948ff2bf378eed1b3e9497a3f18f477d5352ae00000032e16e6e875d1f02a9512943ba2eb9309f4715390b52e4965dd6e39a2989ae63061a8000002a000000008833a9275befbedbf928e743a71c9476f46528baf6e832ad25478c2607e4108dea67657c51db7344032627c855518179dc7a94b59f306faf9a3b4eef7684d5d73106226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f061a8000002a000060e32a590101009000000000000003e8000854d00000000a000000003b9aca000000" - val commitments = stateDataCodec.decode(anchorOutputsChannel.bits).require.value.commitments + val commitments = channelDataCodec.decode(anchorOutputsChannel.bits).require.value.commitments assert(commitments.channelConfig === ChannelConfig.standard) assert(commitments.channelFeatures === ChannelFeatures(Features.StaticRemoteKey, Features.AnchorOutputs)) } { val wumboChannel = hex"00000000000103af0ed6052cf28d670665549bc86f4b721c9fdb309d40c58f5811f63966e005d00009b3b6da18b7e5e43405415a43e61abd77edf4d300c131af17a955950837d7db4980000001000000000000044c000000001dcd65000000000000002710000000000000000000900064ff1600142946bdbb3141be9a40ed8133ef159ee0022176e90000186b02000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a4982039dc0e0b1d25905e44fdf6f8e89755a5e219685840d0bc1d28d3308f9628a358500000000000003e8ffffffffffffffff0000000000004e2000000000000003e80090001e03a6be2613a9ff761a769b077abb43d76c5f06944fc32010891156179bf8b81607025c24f0c3572631ea09dade913ccbb1cd8a55585fc152cc2165bf4f43af702c8b0306c241c667eefee031639052c4a35c4ae076ab56b49f76f7e12f63dfb7bb32a503fdbff1ca92c99c09a9c0eac3cfe1ca35deb658d5fdb815fe7a240df25da5e20f02c47d9e4e1fb501c81933cfc4d3ba7f0e8203003cda2683569f1f67aac2b6e20d000000030a4982000000000000000000000000002710000000745e66c600000000000bebc2002464fc06b43e94d9ce0a5a0e1ef13f63ba78e56d920e7d606d0c6e7a631c48c32c000000002b0065cd1d00000000220020d1b88cc50b09abce945ce6703f30dae3d71ec626be2201925db9379a3e8b981047522103044d393b0da6bcd92030f3131d0780b0d6fa017a0ff45b7fed708903c2950ced2103a6be2613a9ff761a769b077abb43d76c5f06944fc32010891156179bf8b8160752aefd01590200000000010164fc06b43e94d9ce0a5a0e1ef13f63ba78e56d920e7d606d0c6e7a631c48c32c000000000018e2678002400d030000000000160014cf3c9d08ec27d3ffefbf7e2640d3773e11a60ceb783bca1d00000000220020153e514ade07f347db9ed32cf6b2096d066d48e0cf8c504590cd1155de68be2204004730440220056ac83d5b2eb9eb9714e85294d080a9b64f73916d8206b15533613b4303ed3d022044da40ba433e27ddb8743c75acc0f6b050c346bc9d241ab3a1b65051820ce06a0147304402207683c10f33682e2389e5f02dd34090bbe4d786633d49e1777d5ec2ab71a7924902206d99dceb74ff809237ae8e06c118b38047e2d4a49f9956c538bedca47cb4b1da0147522103044d393b0da6bcd92030f3131d0780b0d6fa017a0ff45b7fed708903c2950ced2103a6be2613a9ff761a769b077abb43d76c5f06944fc32010891156179bf8b8160752aef5c4602000000000000000000000000000002710000000000bebc200000000745e66c6000bdebd6cf39db4c2ce1a675281b0a714e525525149032ba048d75c89e5a9b355021a87b53e12e4b36287635cdf887991a732c2fd56b12f5377d755b8b890795db6000000000000000000000000000000000000000000000000000000000000ff032c5f941f78a00105b995fba7f3c340afe53e287a60361135386ae1448d6f3d632464fc06b43e94d9ce0a5a0e1ef13f63ba78e56d920e7d606d0c6e7a631c48c32c000000002b0065cd1d00000000220020d1b88cc50b09abce945ce6703f30dae3d71ec626be2201925db9379a3e8b981047522103044d393b0da6bcd92030f3131d0780b0d6fa017a0ff45b7fed708903c2950ced2103a6be2613a9ff761a769b077abb43d76c5f06944fc32010891156179bf8b8160752ae00000064fc06b43e94d9ce0a5a0e1ef13f63ba78e56d920e7d606d0c6e7a631c48c32cff5e020000000101010101010101010101010101010101010101010101010101010101010101012a00000000ffffffff010065cd1d00000000220020d1b88cc50b09abce945ce6703f30dae3d71ec626be2201925db9379a3e8b9810000000000000000060e32bf9000082000000000000000000000000000000000000000000000000000000000000000064fc06b43e94d9ce0a5a0e1ef13f63ba78e56d920e7d606d0c6e7a631c48c32c0000f4957823b0a6b76697d7c545bcca66abec8522a0f6350a722e45f3f2830f7f824c84efed8daffa04bb0822ce1a08fb2de77dd20c23a91cced7a3966808956644" - val commitments = stateDataCodec.decode(wumboChannel.bits).require.value.commitments + val commitments = channelDataCodec.decode(wumboChannel.bits).require.value.commitments assert(commitments.channelConfig === ChannelConfig.standard) assert(commitments.channelFeatures === ChannelFeatures(Features.Wumbo)) } } test("ensure remote shutdown script is not set") { - val commitments = stateDataCodec.decode(dataNormal.bits).require.value.commitments + val commitments = channelDataCodec.decode(dataNormal.bits).require.value.commitments assert(commitments.remoteParams.shutdownScript === None) } diff --git a/eclair-core/src/test/scala/fr/acinq/eclair/wire/internal/channel/version3/ChannelCodecs3Spec.scala b/eclair-core/src/test/scala/fr/acinq/eclair/wire/internal/channel/version3/ChannelCodecs3Spec.scala index 832ebe667a..36ab4756aa 100644 --- a/eclair-core/src/test/scala/fr/acinq/eclair/wire/internal/channel/version3/ChannelCodecs3Spec.scala +++ b/eclair-core/src/test/scala/fr/acinq/eclair/wire/internal/channel/version3/ChannelCodecs3Spec.scala @@ -22,7 +22,7 @@ import fr.acinq.eclair.channel._ import fr.acinq.eclair.transactions.Transactions._ import fr.acinq.eclair.wire.internal.channel.ChannelCodecsSpec.normal import fr.acinq.eclair.wire.internal.channel.version3.ChannelCodecs3.Codecs._ -import fr.acinq.eclair.wire.internal.channel.version3.ChannelCodecs3.stateDataCodec +import fr.acinq.eclair.wire.internal.channel.version3.ChannelCodecs3.channelDataCodec import fr.acinq.eclair.{BlockHeight, CltvExpiryDelta, Features, MilliSatoshi, UInt64, randomKey} import org.scalatest.funsuite.AnyFunSuite import scodec.bits.{ByteVector, HexStringSyntax} @@ -105,23 +105,23 @@ class ChannelCodecs3Spec extends AnyFunSuite { test("backward compatibility DATA_NORMAL_COMPAT_02_Codec") { val oldBin = hex"00022aed498450b3eb2f6aafedd40640b54efc60ae681da9e6a35299b8b6a6125a7301010003af0ed6052cf28d670665549bc86f4b721c9fdb309d40c58f5811f63966e005d00009d2b17f27b3938b2b50ec713df1b1ae5fd3d23010c9e2e22385f13a168c6acf2c80000001000000000000044c000000001dcd65000000000000002710000000000000000000900064ff1600149d706d0fa71a0b6aa0f3fa400bee18102b45c8170000186b0200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000024982039dc0e0b1d25905e44fdf6f8e89755a5e219685840d0bc1d28d3308f9628a358500000000000003e8ffffffffffffffff0000000000004e2000000000000003e80090001e03fb08866066d5f6f539314220fc31a8e7fdf6ccd12ccde150acc59bac5bb971e003f399d17a9e2fb13a52373d1631807c3161250b2774642fffa629858ad0831f68020b4ecc52820a93f6da40a60d7859307edc737347054d82592959ed1cd0b02e9c03db348203bfd939779bfdd825bc807e904225c3348fa5e3bb57d38ac4b9f40f850284c0df55fbfc2212cbd18cf8ab0eb5283b4b883350ff07e81988e01ae2bb71e20000000302498200000000000000000000000000002710000000002faf0800000000000bebc200242aed498450b3eb2f6aafedd40640b54efc60ae681da9e6a35299b8b6a6125a73000000002b40420f00000000002200203305e10ec90f004675285e9b0371a663ead7abe6caba8c6d5739ace6c9eab4534752210390d6a42ff78a21b41560f75359f0f8a9edaaf0ddcf1a6609130f0d5f234463662103fb08866066d5f6f539314220fc31a8e7fdf6ccd12ccde150acc59bac5bb971e052ae7d02000000012aed498450b3eb2f6aafedd40640b54efc60ae681da9e6a35299b8b6a6125a7300000000000a1e418002400d0300000000001600146862a069e7038573a81f5627ae7d0c6ee5cd0acfb8180c0000000000220020a5f137a8049afcac9f0451b0f31677a81b5443f1c04c1910b37b0d2b8aa4ca0084a4eb2096e400507ac49b57910c914cff8338b8bc57884983541ee1b6919ece7431f4030b09a5fcd87b35682dea0d8faa394e47cc31af897cdf3e6ff502b086cfac37c700000000000000000000000000002710000000000bebc200000000002faf080028131acadf245e7d95d3d7a7f1ac0c0411ead7957ab00d310696b0b5d7d14ac8020597a38e090850030f255fb2781a53713faf7ba81c44de931a63a78efd9908ef000000000000000000000000000000000000000000000000000000000000ff035878c87f6ed100476648193e10a1462bfb55cea3ec5a8f4fbd0fe7304979094b242aed498450b3eb2f6aafedd40640b54efc60ae681da9e6a35299b8b6a6125a73000000002b40420f00000000002200203305e10ec90f004675285e9b0371a663ead7abe6caba8c6d5739ace6c9eab4534752210390d6a42ff78a21b41560f75359f0f8a9edaaf0ddcf1a6609130f0d5f234463662103fb08866066d5f6f539314220fc31a8e7fdf6ccd12ccde150acc59bac5bb971e052ae000000061a8000002a0000000088ec7ae2af533c270809b48f9a0b5a9650df9961a2177e04d7e9929ab319fcd0d150e3ded703b8b4a3f5faff0f2fedf22a6729760deefdea4feed868e4e3cdcf1b06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f061a8000002a000061163fb60101009000000000000003e8000858b800000014000000003b9aca000000" - val decoded1 = stateDataCodec.decode(oldBin.bits).require.value + val decoded1 = channelDataCodec.decode(oldBin.bits).require.value assert(decoded1.asInstanceOf[DATA_NORMAL].closingFeerates === None) - val newBin = stateDataCodec.encode(decoded1).require.bytes + val newBin = channelDataCodec.encode(decoded1).require.bytes // make sure that encoding used the new codec assert(newBin.startsWith(hex"0007")) - val decoded2 = stateDataCodec.decode(newBin.bits).require.value + val decoded2 = channelDataCodec.decode(newBin.bits).require.value assert(decoded1 === decoded2) } test("backward compatibility DATA_SHUTDOWN_COMPAT_03_Codec") { val oldBin = hex"0003342b8fd35a1f3384c6db37723ecc766b672f61b4b0f2e7d5d81cf1e451b584d301010003af0ed6052cf28d670665549bc86f4b721c9fdb309d40c58f5811f63966e005d00009f2408e50889ac3f6c19a007e25752bf143ab0d920cedb9f1c7b7b6b2270c1fe080000001000000000000044c000000001dcd65000000000000002710000000000000000000900064ff160014d0cd80743458194e5f86d9a74592765442fd15bb0000186b0200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000024982039dc0e0b1d25905e44fdf6f8e89755a5e219685840d0bc1d28d3308f9628a358500000000000003e8ffffffffffffffff0000000000004e2000000000000003e80090001e03d1a9a2a574585f60abaaa33826488f9eb8d53ca76693bfa69b42ee2bc8ebe9c50223dc803cceb3edff5deacc9965002cc366b719331e776abf76ee680e4afbf46a0315880bf27110fa57f5b75607bc32a098c209fe8a5a2a30120b2a246fd3fcd62e025dc435be4cb790e5ab12705fb3c0b717ddd9f4d0234fdb557358ecefc6a4e97a0238e3723a9d60dac60c2673ec836e2a909ba9fc888fcbd1cd2ad57ff0b10c5c360000000302498200000000000000000001000200fd05aa342b8fd35a1f3384c6db37723ecc766b672f61b4b0f2e7d5d81cf1e451b584d300000000000000000000000011e1a300d91ec390338376481ff3aea604bf2106cf380d78e946e6a4fc0ad72dc0dec51b00061b100002909a15094ba406ca280bce032eab4d25eae4a9e8b51ff65574b6de2033a292cb1bc6ef576207f4b585273048502efad58af480f08dabcbff1a9642eb3b08811eb4417ac14bf6e5e3883d55ba3b7fdaf27e5ebac16ce63d183b2521867f6cedcf55692f1490da9bc655e38281a26150c44d56e02013faf1cdb2457bec4830e67c10ff0d731798d9e383cc3ce9ba21bddd8971e1d206c54c22317d75411b73abb08c9af348cca2aa2f17232b008aaef4bedb98c426041d3698924d089b59c639396ba38d2ba6d59ea2b0ee8ec9f548deced719e9aae73854d8b6c10c78890999ae09b912a8ae98d3513119bfa0ffdd3037cf5690122020f2c0d01b282ad0cbe345bd31cf7e55d8e78c61abfa62f97d2a095e2256c6569d3e6b5652b365d935d16451f2cf7df04e99e675d9eb649b583fc5d810dae3860001e667b9b78733b3ed6ca5058e6806ca4eb493c5c9a53b0ad78b9ea2091d6e94130afb1d79ce8e274a93d748af9d4ee7ae5b1c06cf1f65507bc79db22c30ae6df93a16c279e4beaf50a0e4e87449e9c830fe9b3877b7332b0632743d4e6267ffa404a35d74d79c5d724bdc9aaaa0423a157fb269b916b0022fd52bb0b2702e6abcc7d9d39d7f69a09a9814b3110cc72574fed031bbc0fd5a03fcee1181076369e76c183b2833385a38dd10773fe3228cb18aa731674a574d310a76052cf89c80077aa89380fcfdeda00508f79261c1e1886240de3bbc343eb84ea7879de24f7dbd0b1527201131bcaf5621e49c69ceec36280f9db6d27161c1676c9b11597d4bd8f10032a964fc1d1afcea594237f3408b184b16eba952778252bc6debc30e6e595c7ebbc2af0c00456ca771d024a56d9f074ca5a7f78f1ef107aa42c2a6426f8dbb2ea8962e2128cfc15161512d2e923e2879635c8ba80bc17f92d09abfae4e08a7f34decc1acd4aa4cc08181017bf248321558a8c4d1a45b92b96274dd9f336eb45d8af6d13147be3a250c17106ec6729e0cffc1af5255352296477dea870426aa82e7af3cc07156b65f8d98b482985618b69b99ee3871240db751923dbeddea6e36f5c3f0599300973fe064ccf4f15cadb7372aaab5b300674f5bf28ce905ab411f5605fba7075ed4a6b08dca3ed5867dc32e491c64e7f09ff4095081e0731cbfc53fa42c33e79bd1a26d8e9f8c5b546b07bd1b300f1f357919e955bded1f987401f4da1a453282b6978ff3bfd13b280f6253dd968cb4e7741a15faf7b4c70dbd9eab6461ca3d3a576410213bc4e144a63685488afeeb7857af4ef83e73c88b17798616a9ccbd603d61ec8f4dbbdd5fea5ca748cf40c38fec50d4eebf1e5b57fd32500baa892da24349598c3125162b2ea0ea049ea9aacdfa848f41fdf7f9eb983776bac58ddf762d131196ab18774349a5eca2fc5b51b60d7aceae1321c1decd462f9c7dbbd820399f71a3c3ccbb30a29f76cd8e94243e400c4dc6e6d32b6f94155a21eb89b6b4c0fd1660bd98509d11b3a45fb257ae1e3c5ebae7bae038200c0f7f2d4ee744c3f2d9007d6fb282b0254ccd71eae5b4c4996b52edb2f2f4120356096c81e42168ee43d98bd630b0af01c270db3fb680cd931d388e1c1260126707548ed1f27006a64db7885ac7500ce020f6349a1abf59fb3ca4bc5bdcbd19b7a0cfe82aeea62f0373d5c16002cd9adcb3ef5e0c862e2fda972530b399b0f6365f4edbc36a32bd1766763104aca34450f278418211d62ff3fff2d0de7f516028011e5681ee892288835a3ec6d0d353f8bc7168086a0eed30d5e81d8a51f7debbb2290dc1a1745e0fc2c08778d11ccb78dc7c98a8b4a4b28fd8decda3a2063ad73c23c112d609b6903613c5ad8e178c90fed2ebd10b176b17c9c2dfc630ef744ac289b437ad229b77a393c6b05c10f36ba2f80482ed6e26b3d9c34d2200fd05aa342b8fd35a1f3384c6db37723ecc766b672f61b4b0f2e7d5d81cf1e451b584d30000000000000001000000000bebc20092ebfcedc573c52ba840ff42bb322419ed390dc845c2fe80636b6b82cf41210000061b100002f211b0d97e6c7f7fb800dbb8d1c7536ad7ef284c40a85fc7316b771bb525c91f7e1d4bba90df0cf0d12c19906e4ae0a1b83954632b59f5f499dedaeba19d75c3bc244ccb57089abeaf29c7d73d67ae822aea2ed4d85d27dc65042589e8172aa3b66d928d7e35f027d96bf23e656701bdf13651e25bed745fef014fdec3faaba4795638299975d3cdc8d2c5b19e2e411e6e4f7b3cede7e269c8902306d25b1027e99736489fde667f4eaf5726349851986ff15a9e967385e080079a14c0a9c3001bbce5da720dcf739e67801cfe2a565b24f5515f8d8889a6d2dc0b51fae4facb72904ba8c1949550332cd8b9095655da72a9815537a80efd204d497af47fd18ef0f6d0639424eb81dab0e34f228aed9406d23773874b4c41d9a21dcaf632419e459baaca5f338f0f9718c89fb72108788d32aeb07e2eb343c45891958779e75fe0039eddaf7e5c4aa8ac2aee9928c68dc529d415780d8e14adcecc91b142b238e7657ef1dc6b6e9843bb5fbe8d04564307e515d88b34105b90b3fa9ed91025297a373507cba86160ba5b7b569948c95fd483b28b8970bebd5e17fcad76c6ed64615cc2d7297994483d94c010a210ad3602b7f359d7d1391b97968f9eaa70de83ea1168fdb05190a6e9fc7c984213da3e2a6672d09704d8e29e2aa9349c9ae44eca3dc0522c769887cbaa0926c5bad64eaf7c22399f7abcc01505d921cce15f4613406956715fe3030ab5c74506d1acc30649b596931316a8e210a368d758d7c1f406f5888499f8317a9ba629dfe85453b4413107796bde15636e6f628078863c0009db7d97cfadc2bfdcdfed237debac33dc525f25865663bc7a812099102fe9c65c8a37b179337141c8d76f365824b0db54b0b18d6c88b21406a1e35061fb4f5ef8a280f9c2ac2ada9eea8cb365d346c5e9eaa56728584aa71c4296a1c11d76f03351a91a030ae6df1da008a5d0f92207b8ca22f335b5a347707ef2500119597d5b92c559f477d8405f1d0dfd790c99ca5a7b4aeac232224ea8461ed07636931e65fee7b063d0ef49f471c04e2fd45b2fff3fb6923314e26045259640335c417ed14a0799553dda3eff5065ec5606303c42309221881c7dea17227da4003a6e396e308ca77da3b4b743a1c2771252c2fa8caad98c9985f9157dbcdd355d3a70b2edeca9682e4bba3e7da24fdd472017b89103e61ab9a4bcc9ab75bd28f7fad29327bf710b3b4759bb76983b003a0907794ad73194d14a70769ce6731b0ae21d565b53780275b6ac42c650d47f570331c7ac57fc75390d3b232eece8277a7c8453b5f28206ff1026879981f2ac83a0d4760554401e671a110de6c03cc104927c55de7254311680af4fb5d36b2199e1348f6fa50877d6cb163dd5f70381f2418f20d145d8ed5df2714cdcda59a4362b0c544ee1af01ac41bc15729951b1e53f3a135fe9011d3e938b08c50d53da259e2ab19b97a47b96d6b7fd559704ac9d1d8a223cbb88c9f77fa563c0c66524c260f0ff54471acae87e71c0507b14edf02bd42993966eea6b2f5d36db12b7fec7a63b80a13651822867db1f046081ad2cf3676b88fa2ef700b8c865a7dedcdee739795853584b74c3f59868daf79e81bf70afed8ea1ce689d67090a32dfe351fd0bdaf60b3903d7ff7c149134a95b2ddf1d63e0f89dfe0b710accf2ca3c37647973532338c59d32e562d7c55573277c1fab09d57a452f4214131178683533fbfe7726276903aacd579d36c6679187b1d22dda32fc5302b91244840a54c258e4d416deb0d20f96b214c335608db6b725175d8517f35f9d6b466c751a1253b20051863a02f2e0c073830cb7de27c96c4ccb196e079edc817ebdf70972b917b6a07c6a431567b99c6072b102e5103a22908683f60bb4fb72538ae3a3768de85f9fc682e67c6aea0e000027100000000011e1a300000000000bebc20024342b8fd35a1f3384c6db37723ecc766b672f61b4b0f2e7d5d81cf1e451b584d3000000002b40420f000000000022002091a342be9a9171a40f83766fbf34a0be03b79675dd20c14e13d91651f7f8273e47522103a1bd05e59ffa63f010cee2ff6848730c6f718da57aef6a5df381683d409a815e2103d1a9a2a574585f60abaaa33826488f9eb8d53ca76693bfa69b42ee2bc8ebe9c552aed30200000001342b8fd35a1f3384c6db37723ecc766b672f61b4b0f2e7d5d81cf1e451b584d300000000007d30f88004400d030000000000160014dab249c7d3b8d826d45244f609bb90f72e691daa400d030000000000220020d24765dcd888e08581c2add26ddfaa6f3ef06b56578373c59915bcc25aa0c6ee286a04000000000022002054d7877901aedaf54d84b20a4233107c2fdab9ff637106d44097e69a813d394ee093040000000000220020039e4d3b414381fb8fda640b122e604b20aa6f64e87607dd9354cdc636cb483d1b17b4207914784cfd82df8f93f15defff862cede27811ce4c59df98e86fd57e5b5105921e842a02a47ee6ddb313b37bc0b6706fe3011e2dd2d82066c85ab11a8d7b4e47000202241ad33e0af0717b31e19b50fd6b0469a42807eec1a080ad29cd56d04a4de54313010000002b400d030000000000220020d24765dcd888e08581c2add26ddfaa6f3ef06b56578373c59915bcc25aa0c6ee8576a91474e49ec772064db47a555b032479b20992beeefe8763ac672102cd66c9b36fdd627754f492f15bc2387f44fd70bc4c9ccdb08df37e25250a5b197c820120876475527c2103d80a13db0dffe34a9b1ff383306a52aed0a40a99ce1c34b113ca7467327f608452ae67a9142a784c1850f79298eab62c5c7709a5d468f5522788ac68685e02000000011ad33e0af0717b31e19b50fd6b0469a42807eec1a080ad29cd56d04a4de54313010000000000000000015af302000000000022002054d7877901aedaf54d84b20a4233107c2fdab9ff637106d44097e69a813d394e101b06000000000000000001f8c46e9fa497a4f9f4fdf422840d264f67178defb43320b83c1d9825a6c152995775652ba3689025f4841f165acbd16732ad88629429b3811d71c7b03adf254402241ad33e0af0717b31e19b50fd6b0469a42807eec1a080ad29cd56d04a4de54313030000002be093040000000000220020039e4d3b414381fb8fda640b122e604b20aa6f64e87607dd9354cdc636cb483d8576a91474e49ec772064db47a555b032479b20992beeefe8763ac672102cd66c9b36fdd627754f492f15bc2387f44fd70bc4c9ccdb08df37e25250a5b197c820120876475527c2103d80a13db0dffe34a9b1ff383306a52aed0a40a99ce1c34b113ca7467327f608452ae67a91448d436723875e511f3a4fc540ca63c91637e926388ac68685e02000000011ad33e0af0717b31e19b50fd6b0469a42807eec1a080ad29cd56d04a4de5431303000000000000000001fa7904000000000022002054d7877901aedaf54d84b20a4233107c2fdab9ff637106d44097e69a813d394e101b06000000000000000000ce718c1999b28ddd1207bcdd6789541ec2f405f775efb096bd896bb237b7f5c17543684f99cb53efeade77bc386997e7b5361418c510ed442700cee38c36f18900000000000000010002fffd05aa342b8fd35a1f3384c6db37723ecc766b672f61b4b0f2e7d5d81cf1e451b584d300000000000000000000000011e1a300d91ec390338376481ff3aea604bf2106cf380d78e946e6a4fc0ad72dc0dec51b00061b100002909a15094ba406ca280bce032eab4d25eae4a9e8b51ff65574b6de2033a292cb1bc6ef576207f4b585273048502efad58af480f08dabcbff1a9642eb3b08811eb4417ac14bf6e5e3883d55ba3b7fdaf27e5ebac16ce63d183b2521867f6cedcf55692f1490da9bc655e38281a26150c44d56e02013faf1cdb2457bec4830e67c10ff0d731798d9e383cc3ce9ba21bddd8971e1d206c54c22317d75411b73abb08c9af348cca2aa2f17232b008aaef4bedb98c426041d3698924d089b59c639396ba38d2ba6d59ea2b0ee8ec9f548deced719e9aae73854d8b6c10c78890999ae09b912a8ae98d3513119bfa0ffdd3037cf5690122020f2c0d01b282ad0cbe345bd31cf7e55d8e78c61abfa62f97d2a095e2256c6569d3e6b5652b365d935d16451f2cf7df04e99e675d9eb649b583fc5d810dae3860001e667b9b78733b3ed6ca5058e6806ca4eb493c5c9a53b0ad78b9ea2091d6e94130afb1d79ce8e274a93d748af9d4ee7ae5b1c06cf1f65507bc79db22c30ae6df93a16c279e4beaf50a0e4e87449e9c830fe9b3877b7332b0632743d4e6267ffa404a35d74d79c5d724bdc9aaaa0423a157fb269b916b0022fd52bb0b2702e6abcc7d9d39d7f69a09a9814b3110cc72574fed031bbc0fd5a03fcee1181076369e76c183b2833385a38dd10773fe3228cb18aa731674a574d310a76052cf89c80077aa89380fcfdeda00508f79261c1e1886240de3bbc343eb84ea7879de24f7dbd0b1527201131bcaf5621e49c69ceec36280f9db6d27161c1676c9b11597d4bd8f10032a964fc1d1afcea594237f3408b184b16eba952778252bc6debc30e6e595c7ebbc2af0c00456ca771d024a56d9f074ca5a7f78f1ef107aa42c2a6426f8dbb2ea8962e2128cfc15161512d2e923e2879635c8ba80bc17f92d09abfae4e08a7f34decc1acd4aa4cc08181017bf248321558a8c4d1a45b92b96274dd9f336eb45d8af6d13147be3a250c17106ec6729e0cffc1af5255352296477dea870426aa82e7af3cc07156b65f8d98b482985618b69b99ee3871240db751923dbeddea6e36f5c3f0599300973fe064ccf4f15cadb7372aaab5b300674f5bf28ce905ab411f5605fba7075ed4a6b08dca3ed5867dc32e491c64e7f09ff4095081e0731cbfc53fa42c33e79bd1a26d8e9f8c5b546b07bd1b300f1f357919e955bded1f987401f4da1a453282b6978ff3bfd13b280f6253dd968cb4e7741a15faf7b4c70dbd9eab6461ca3d3a576410213bc4e144a63685488afeeb7857af4ef83e73c88b17798616a9ccbd603d61ec8f4dbbdd5fea5ca748cf40c38fec50d4eebf1e5b57fd32500baa892da24349598c3125162b2ea0ea049ea9aacdfa848f41fdf7f9eb983776bac58ddf762d131196ab18774349a5eca2fc5b51b60d7aceae1321c1decd462f9c7dbbd820399f71a3c3ccbb30a29f76cd8e94243e400c4dc6e6d32b6f94155a21eb89b6b4c0fd1660bd98509d11b3a45fb257ae1e3c5ebae7bae038200c0f7f2d4ee744c3f2d9007d6fb282b0254ccd71eae5b4c4996b52edb2f2f4120356096c81e42168ee43d98bd630b0af01c270db3fb680cd931d388e1c1260126707548ed1f27006a64db7885ac7500ce020f6349a1abf59fb3ca4bc5bdcbd19b7a0cfe82aeea62f0373d5c16002cd9adcb3ef5e0c862e2fda972530b399b0f6365f4edbc36a32bd1766763104aca34450f278418211d62ff3fff2d0de7f516028011e5681ee892288835a3ec6d0d353f8bc7168086a0eed30d5e81d8a51f7debbb2290dc1a1745e0fc2c08778d11ccb78dc7c98a8b4a4b28fd8decda3a2063ad73c23c112d609b6903613c5ad8e178c90fed2ebd10b176b17c9c2dfc630ef744ac289b437ad229b77a393c6b05c10f36ba2f80482ed6e26b3d9c34d22fffd05aa342b8fd35a1f3384c6db37723ecc766b672f61b4b0f2e7d5d81cf1e451b584d30000000000000001000000000bebc20092ebfcedc573c52ba840ff42bb322419ed390dc845c2fe80636b6b82cf41210000061b100002f211b0d97e6c7f7fb800dbb8d1c7536ad7ef284c40a85fc7316b771bb525c91f7e1d4bba90df0cf0d12c19906e4ae0a1b83954632b59f5f499dedaeba19d75c3bc244ccb57089abeaf29c7d73d67ae822aea2ed4d85d27dc65042589e8172aa3b66d928d7e35f027d96bf23e656701bdf13651e25bed745fef014fdec3faaba4795638299975d3cdc8d2c5b19e2e411e6e4f7b3cede7e269c8902306d25b1027e99736489fde667f4eaf5726349851986ff15a9e967385e080079a14c0a9c3001bbce5da720dcf739e67801cfe2a565b24f5515f8d8889a6d2dc0b51fae4facb72904ba8c1949550332cd8b9095655da72a9815537a80efd204d497af47fd18ef0f6d0639424eb81dab0e34f228aed9406d23773874b4c41d9a21dcaf632419e459baaca5f338f0f9718c89fb72108788d32aeb07e2eb343c45891958779e75fe0039eddaf7e5c4aa8ac2aee9928c68dc529d415780d8e14adcecc91b142b238e7657ef1dc6b6e9843bb5fbe8d04564307e515d88b34105b90b3fa9ed91025297a373507cba86160ba5b7b569948c95fd483b28b8970bebd5e17fcad76c6ed64615cc2d7297994483d94c010a210ad3602b7f359d7d1391b97968f9eaa70de83ea1168fdb05190a6e9fc7c984213da3e2a6672d09704d8e29e2aa9349c9ae44eca3dc0522c769887cbaa0926c5bad64eaf7c22399f7abcc01505d921cce15f4613406956715fe3030ab5c74506d1acc30649b596931316a8e210a368d758d7c1f406f5888499f8317a9ba629dfe85453b4413107796bde15636e6f628078863c0009db7d97cfadc2bfdcdfed237debac33dc525f25865663bc7a812099102fe9c65c8a37b179337141c8d76f365824b0db54b0b18d6c88b21406a1e35061fb4f5ef8a280f9c2ac2ada9eea8cb365d346c5e9eaa56728584aa71c4296a1c11d76f03351a91a030ae6df1da008a5d0f92207b8ca22f335b5a347707ef2500119597d5b92c559f477d8405f1d0dfd790c99ca5a7b4aeac232224ea8461ed07636931e65fee7b063d0ef49f471c04e2fd45b2fff3fb6923314e26045259640335c417ed14a0799553dda3eff5065ec5606303c42309221881c7dea17227da4003a6e396e308ca77da3b4b743a1c2771252c2fa8caad98c9985f9157dbcdd355d3a70b2edeca9682e4bba3e7da24fdd472017b89103e61ab9a4bcc9ab75bd28f7fad29327bf710b3b4759bb76983b003a0907794ad73194d14a70769ce6731b0ae21d565b53780275b6ac42c650d47f570331c7ac57fc75390d3b232eece8277a7c8453b5f28206ff1026879981f2ac83a0d4760554401e671a110de6c03cc104927c55de7254311680af4fb5d36b2199e1348f6fa50877d6cb163dd5f70381f2418f20d145d8ed5df2714cdcda59a4362b0c544ee1af01ac41bc15729951b1e53f3a135fe9011d3e938b08c50d53da259e2ab19b97a47b96d6b7fd559704ac9d1d8a223cbb88c9f77fa563c0c66524c260f0ff54471acae87e71c0507b14edf02bd42993966eea6b2f5d36db12b7fec7a63b80a13651822867db1f046081ad2cf3676b88fa2ef700b8c865a7dedcdee739795853584b74c3f59868daf79e81bf70afed8ea1ce689d67090a32dfe351fd0bdaf60b3903d7ff7c149134a95b2ddf1d63e0f89dfe0b710accf2ca3c37647973532338c59d32e562d7c55573277c1fab09d57a452f4214131178683533fbfe7726276903aacd579d36c6679187b1d22dda32fc5302b91244840a54c258e4d416deb0d20f96b214c335608db6b725175d8517f35f9d6b466c751a1253b20051863a02f2e0c073830cb7de27c96c4ccb196e079edc817ebdf70972b917b6a07c6a431567b99c6072b102e5103a22908683f60bb4fb72538ae3a3768de85f9fc682e67c6aea0e00002710000000000bebc2000000000011e1a300306acd0b21100f755a6d193a819042fde1b4c3839598e730905dfa7e6ef699220240a9cccdb58d887b42ccadeee5704030acd52bd9c7759ba01f47f0995531ca360000000000000000000000000000000000000002000000000000000000020000000000000000000334c7b350311d40b3b422e07f3b7759b400000000000000010003e3dd409b342046e7b410cc380c9a09c2ff03cdeeaf422678a9eac407da8f811a402718083016f88d5404f5508054fe25acb824342b8fd35a1f3384c6db37723ecc766b672f61b4b0f2e7d5d81cf1e451b584d3000000002b40420f000000000022002091a342be9a9171a40f83766fbf34a0be03b79675dd20c14e13d91651f7f8273e47522103a1bd05e59ffa63f010cee2ff6848730c6f718da57aef6a5df381683d409a815e2103d1a9a2a574585f60abaaa33826488f9eb8d53ca76693bfa69b42ee2bc8ebe9c552ae000100400000ffffffffffff00204cec06f1f1496c01cd4840cddff19b47c24b7daa478bcaea862c6d11fcc9fff180007fffffffffff8038342b8fd35a1f3384c6db37723ecc766b672f61b4b0f2e7d5d81cf1e451b584d300160014d0cd80743458194e5f86d9a74592765442fd15bb38342b8fd35a1f3384c6db37723ecc766b672f61b4b0f2e7d5d81cf1e451b584d30016001483366b494906052362a88e967304296937926cd1" - val decoded1 = stateDataCodec.decode(oldBin.bits).require.value + val decoded1 = channelDataCodec.decode(oldBin.bits).require.value assert(decoded1.asInstanceOf[DATA_SHUTDOWN].closingFeerates === None) - val newBin = stateDataCodec.encode(decoded1).require.bytes + val newBin = channelDataCodec.encode(decoded1).require.bytes // make sure that encoding used the new codec assert(newBin.startsWith(hex"0008")) - val decoded2 = stateDataCodec.decode(newBin.bits).require.value + val decoded2 = channelDataCodec.decode(newBin.bits).require.value assert(decoded1 === decoded2) } From c7b1fa634cf25c0d6e632da9eb38589db72e754f Mon Sep 17 00:00:00 2001 From: t-bast Date: Thu, 7 Apr 2022 14:22:45 +0200 Subject: [PATCH 3/6] A few fixes in Channel.scala --- .../fr/acinq/eclair/channel/fsm/Channel.scala | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/channel/fsm/Channel.scala b/eclair-core/src/main/scala/fr/acinq/eclair/channel/fsm/Channel.scala index 0d930e556a..8fc6d36db4 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/channel/fsm/Channel.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/channel/fsm/Channel.scala @@ -331,14 +331,6 @@ class Channel(val nodeParams: NodeParams, val wallet: OnChainChannelFunder, val watchFundingTx(data.commitments) goto(OFFLINE) using data } - - case Event(c: CloseCommand, d) => - channelOpenReplyToUser(Right(ChannelOpenResponse.ChannelClosed(d.channelId))) - handleFastClose(c, d.channelId) - - case Event(TickChannelOpenTimeout, _) => - channelOpenReplyToUser(Left(LocalError(new RuntimeException("open channel cancelled, took too long")))) - goto(CLOSED) }) /* @@ -1420,6 +1412,8 @@ class Channel(val nodeParams: NodeParams, val wallet: OnChainChannelFunder, val case Event(c: CMD_ADD_HTLC, d: DATA_NORMAL) => handleAddDisconnected(c, d) + case Event(c: CMD_UPDATE_RELAY_FEE, d: DATA_NORMAL) => handleUpdateRelayFeeDisconnected(c, d) + case Event(channelReestablish: ChannelReestablish, d: DATA_SHUTDOWN) => Syncing.checkSync(keyManager, d, channelReestablish) match { case syncFailure: SyncResult.Failure => @@ -1501,14 +1495,10 @@ class Channel(val nodeParams: NodeParams, val wallet: OnChainChannelFunder, val when(ERR_INFORMATION_LEAK)(errorStateHandler) - when(ERR_FUNDING_LOST)(errorStateHandler) - whenUnhandled { case Event(INPUT_DISCONNECTED, _) => goto(OFFLINE) - case Event(WatchFundingLostTriggered(_), _) => goto(ERR_FUNDING_LOST) - case Event(c: CMD_GETSTATE, _) => val replyTo = if (c.replyTo == ActorRef.noSender) sender() else c.replyTo replyTo ! RES_GETSTATE(stateName) From ee2a5fab58da7323a7dee66dde62a33cfdd6b250 Mon Sep 17 00:00:00 2001 From: t-bast Date: Thu, 7 Apr 2022 14:26:27 +0200 Subject: [PATCH 4/6] Rename GET_* channel commands --- .../main/scala/fr/acinq/eclair/Eclair.scala | 14 ++-- .../fr/acinq/eclair/channel/ChannelData.scala | 12 +-- .../fr/acinq/eclair/channel/fsm/Channel.scala | 12 +-- .../fr/acinq/eclair/EclairImplSpec.scala | 38 ++++----- .../integration/ChannelIntegrationSpec.scala | 84 +++++++++---------- .../integration/PaymentIntegrationSpec.scala | 8 +- .../rustytests/SynchronizationPipe.scala | 4 +- 7 files changed, 86 insertions(+), 86 deletions(-) diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/Eclair.scala b/eclair-core/src/main/scala/fr/acinq/eclair/Eclair.scala index c8c9767330..6874f8c357 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/Eclair.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/Eclair.scala @@ -94,9 +94,9 @@ trait Eclair { def updateRelayFee(nodes: List[PublicKey], feeBase: MilliSatoshi, feeProportionalMillionths: Long)(implicit timeout: Timeout): Future[Map[ApiTypes.ChannelIdentifier, Either[Throwable, CommandResponse[CMD_UPDATE_RELAY_FEE]]]] - def channelsInfo(toRemoteNode_opt: Option[PublicKey])(implicit timeout: Timeout): Future[Iterable[RES_GETINFO]] + def channelsInfo(toRemoteNode_opt: Option[PublicKey])(implicit timeout: Timeout): Future[Iterable[RES_GET_CHANNEL_INFO]] - def channelInfo(channel: ApiTypes.ChannelIdentifier)(implicit timeout: Timeout): Future[CommandResponse[CMD_GETINFO]] + def channelInfo(channel: ApiTypes.ChannelIdentifier)(implicit timeout: Timeout): Future[CommandResponse[CMD_GET_CHANNEL_INFO]] def peers()(implicit timeout: Timeout): Future[Iterable[PeerInfo]] @@ -216,7 +216,7 @@ class EclairImpl(appKit: Kit) extends Eclair with Logging { .map(_.filter(n => nodeIds_opt.forall(_.contains(n.nodeId)))) } - override def channelsInfo(toRemoteNode_opt: Option[PublicKey])(implicit timeout: Timeout): Future[Iterable[RES_GETINFO]] = { + override def channelsInfo(toRemoteNode_opt: Option[PublicKey])(implicit timeout: Timeout): Future[Iterable[RES_GET_CHANNEL_INFO]] = { val futureResponse = toRemoteNode_opt match { case Some(pk) => (appKit.register ? Symbol("channelsTo")).mapTo[Map[ByteVector32, PublicKey]].map(_.filter(_._2 == pk).keys) case None => (appKit.register ? Symbol("channels")).mapTo[Map[ByteVector32, ActorRef]].map(_.keys) @@ -224,14 +224,14 @@ class EclairImpl(appKit: Kit) extends Eclair with Logging { for { channelIds <- futureResponse - channels <- Future.sequence(channelIds.map(channelId => sendToChannel[CMD_GETINFO, CommandResponse[CMD_GETINFO]](Left(channelId), CMD_GETINFO(ActorRef.noSender)))) + channels <- Future.sequence(channelIds.map(channelId => sendToChannel[CMD_GET_CHANNEL_INFO, CommandResponse[CMD_GET_CHANNEL_INFO]](Left(channelId), CMD_GET_CHANNEL_INFO(ActorRef.noSender)))) } yield channels.collect { - case properResponse: RES_GETINFO => properResponse + case properResponse: RES_GET_CHANNEL_INFO => properResponse } } - override def channelInfo(channel: ApiTypes.ChannelIdentifier)(implicit timeout: Timeout): Future[CommandResponse[CMD_GETINFO]] = { - sendToChannel[CMD_GETINFO, CommandResponse[CMD_GETINFO]](channel, CMD_GETINFO(ActorRef.noSender)) + override def channelInfo(channel: ApiTypes.ChannelIdentifier)(implicit timeout: Timeout): Future[CommandResponse[CMD_GET_CHANNEL_INFO]] = { + sendToChannel[CMD_GET_CHANNEL_INFO, CommandResponse[CMD_GET_CHANNEL_INFO]](channel, CMD_GET_CHANNEL_INFO(ActorRef.noSender)) } override def allChannels()(implicit timeout: Timeout): Future[Iterable[ChannelDesc]] = { diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/channel/ChannelData.scala b/eclair-core/src/main/scala/fr/acinq/eclair/channel/ChannelData.scala index 380db8a67b..54ce099c7c 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/channel/ChannelData.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/channel/ChannelData.scala @@ -179,9 +179,9 @@ sealed trait CloseCommand extends HasReplyToCommand final case class CMD_CLOSE(replyTo: ActorRef, scriptPubKey: Option[ByteVector], feerates: Option[ClosingFeerates]) extends CloseCommand final case class CMD_FORCECLOSE(replyTo: ActorRef) extends CloseCommand final case class CMD_UPDATE_RELAY_FEE(replyTo: ActorRef, feeBase: MilliSatoshi, feeProportionalMillionths: Long, cltvExpiryDelta_opt: Option[CltvExpiryDelta]) extends HasReplyToCommand -final case class CMD_GETSTATE(replyTo: ActorRef) extends HasReplyToCommand -final case class CMD_GETSTATEDATA(replyTo: ActorRef) extends HasReplyToCommand -final case class CMD_GETINFO(replyTo: ActorRef)extends HasReplyToCommand +final case class CMD_GET_CHANNEL_STATE(replyTo: ActorRef) extends HasReplyToCommand +final case class CMD_GET_CHANNEL_DATA(replyTo: ActorRef) extends HasReplyToCommand +final case class CMD_GET_CHANNEL_INFO(replyTo: ActorRef)extends HasReplyToCommand /* 88888888b. 8888888888 .d8888b. 88888888b. ,ad8888ba, 888b 88 .d8888b. 8888888888 .d8888b. @@ -225,9 +225,9 @@ object HtlcResult { final case class RES_ADD_SETTLED[+O <: Origin, +R <: HtlcResult](origin: O, htlc: UpdateAddHtlc, result: R) extends CommandSuccess[CMD_ADD_HTLC] /** other specific responses */ -final case class RES_GETSTATE[+S <: ChannelState](state: S) extends CommandSuccess[CMD_GETSTATE] -final case class RES_GETSTATEDATA[+D <: ChannelData](data: D) extends CommandSuccess[CMD_GETSTATEDATA] -final case class RES_GETINFO(nodeId: PublicKey, channelId: ByteVector32, state: ChannelState, data: ChannelData) extends CommandSuccess[CMD_GETINFO] +final case class RES_GET_CHANNEL_STATE(state: ChannelState) extends CommandSuccess[CMD_GET_CHANNEL_STATE] +final case class RES_GET_CHANNEL_DATA[+D <: ChannelData](data: D) extends CommandSuccess[CMD_GET_CHANNEL_DATA] +final case class RES_GET_CHANNEL_INFO(nodeId: PublicKey, channelId: ByteVector32, state: ChannelState, data: ChannelData) extends CommandSuccess[CMD_GET_CHANNEL_INFO] /** * Those are not response to [[Command]], but to [[fr.acinq.eclair.io.Peer.OpenChannel]] diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/channel/fsm/Channel.scala b/eclair-core/src/main/scala/fr/acinq/eclair/channel/fsm/Channel.scala index 8fc6d36db4..e8d8aa147d 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/channel/fsm/Channel.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/channel/fsm/Channel.scala @@ -1499,19 +1499,19 @@ class Channel(val nodeParams: NodeParams, val wallet: OnChainChannelFunder, val case Event(INPUT_DISCONNECTED, _) => goto(OFFLINE) - case Event(c: CMD_GETSTATE, _) => + case Event(c: CMD_GET_CHANNEL_STATE, _) => val replyTo = if (c.replyTo == ActorRef.noSender) sender() else c.replyTo - replyTo ! RES_GETSTATE(stateName) + replyTo ! RES_GET_CHANNEL_STATE(stateName) stay() - case Event(c: CMD_GETSTATEDATA, _) => + case Event(c: CMD_GET_CHANNEL_DATA, _) => val replyTo = if (c.replyTo == ActorRef.noSender) sender() else c.replyTo - replyTo ! RES_GETSTATEDATA(stateData) + replyTo ! RES_GET_CHANNEL_DATA(stateData) stay() - case Event(c: CMD_GETINFO, _) => + case Event(c: CMD_GET_CHANNEL_INFO, _) => val replyTo = if (c.replyTo == ActorRef.noSender) sender() else c.replyTo - replyTo ! RES_GETINFO(remoteNodeId, stateData.channelId, stateName, stateData) + replyTo ! RES_GET_CHANNEL_INFO(remoteNodeId, stateData.channelId, stateName, stateData) stay() case Event(c: CMD_ADD_HTLC, d: PersistentChannelData) => diff --git a/eclair-core/src/test/scala/fr/acinq/eclair/EclairImplSpec.scala b/eclair-core/src/test/scala/fr/acinq/eclair/EclairImplSpec.scala index a36188e8f8..f0af4df86f 100644 --- a/eclair-core/src/test/scala/fr/acinq/eclair/EclairImplSpec.scala +++ b/eclair-core/src/test/scala/fr/acinq/eclair/EclairImplSpec.scala @@ -429,17 +429,17 @@ class EclairImplSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike with I register.expectMsg(Symbol("channels")) register.reply(map) - val c1 = register.expectMsgType[Register.Forward[CMD_GETINFO]] - register.reply(RES_GETINFO(map(c1.channelId), c1.channelId, NORMAL, ChannelCodecsSpec.normal)) - register.expectMsgType[Register.Forward[CMD_GETINFO]] - register.reply(RES_FAILURE(CMD_GETINFO(ActorRef.noSender), new IllegalArgumentException("Non-standard channel"))) - val c3 = register.expectMsgType[Register.Forward[CMD_GETINFO]] - register.reply(RES_GETINFO(map(c3.channelId), c3.channelId, NORMAL, ChannelCodecsSpec.normal)) + val c1 = register.expectMsgType[Register.Forward[CMD_GET_CHANNEL_INFO]] + register.reply(RES_GET_CHANNEL_INFO(map(c1.channelId), c1.channelId, NORMAL, ChannelCodecsSpec.normal)) + register.expectMsgType[Register.Forward[CMD_GET_CHANNEL_INFO]] + register.reply(RES_FAILURE(CMD_GET_CHANNEL_INFO(ActorRef.noSender), new IllegalArgumentException("Non-standard channel"))) + val c3 = register.expectMsgType[Register.Forward[CMD_GET_CHANNEL_INFO]] + register.reply(RES_GET_CHANNEL_INFO(map(c3.channelId), c3.channelId, NORMAL, ChannelCodecsSpec.normal)) register.expectNoMessage() - assert(sender.expectMsgType[Iterable[RES_GETINFO]].toSet === Set( - RES_GETINFO(a, a1, NORMAL, ChannelCodecsSpec.normal), - RES_GETINFO(b, b1, NORMAL, ChannelCodecsSpec.normal), + assert(sender.expectMsgType[Iterable[RES_GET_CHANNEL_INFO]].toSet === Set( + RES_GET_CHANNEL_INFO(a, a1, NORMAL, ChannelCodecsSpec.normal), + RES_GET_CHANNEL_INFO(b, b1, NORMAL, ChannelCodecsSpec.normal), )) } @@ -460,15 +460,15 @@ class EclairImplSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike with I register.expectMsg(Symbol("channelsTo")) register.reply(channels2Nodes) - val c1 = register.expectMsgType[Register.Forward[CMD_GETINFO]] - register.reply(RES_GETINFO(channels2Nodes(c1.channelId), c1.channelId, NORMAL, ChannelCodecsSpec.normal)) - val c2 = register.expectMsgType[Register.Forward[CMD_GETINFO]] - register.reply(RES_GETINFO(channels2Nodes(c2.channelId), c2.channelId, NORMAL, ChannelCodecsSpec.normal)) + val c1 = register.expectMsgType[Register.Forward[CMD_GET_CHANNEL_INFO]] + register.reply(RES_GET_CHANNEL_INFO(channels2Nodes(c1.channelId), c1.channelId, NORMAL, ChannelCodecsSpec.normal)) + val c2 = register.expectMsgType[Register.Forward[CMD_GET_CHANNEL_INFO]] + register.reply(RES_GET_CHANNEL_INFO(channels2Nodes(c2.channelId), c2.channelId, NORMAL, ChannelCodecsSpec.normal)) register.expectNoMessage() - assert(sender.expectMsgType[Iterable[RES_GETINFO]].toSet === Set( - RES_GETINFO(a, a1, NORMAL, ChannelCodecsSpec.normal), - RES_GETINFO(a, a2, NORMAL, ChannelCodecsSpec.normal), + assert(sender.expectMsgType[Iterable[RES_GET_CHANNEL_INFO]].toSet === Set( + RES_GET_CHANNEL_INFO(a, a1, NORMAL, ChannelCodecsSpec.normal), + RES_GET_CHANNEL_INFO(a, a2, NORMAL, ChannelCodecsSpec.normal), )) } @@ -486,11 +486,11 @@ class EclairImplSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike with I eclair.channelInfo(Left(a2)).pipeTo(sender.ref) - val c1 = register.expectMsgType[Register.Forward[CMD_GETINFO]] - register.reply(RES_GETINFO(channels2Nodes(c1.channelId), c1.channelId, NORMAL, ChannelCodecsSpec.normal)) + val c1 = register.expectMsgType[Register.Forward[CMD_GET_CHANNEL_INFO]] + register.reply(RES_GET_CHANNEL_INFO(channels2Nodes(c1.channelId), c1.channelId, NORMAL, ChannelCodecsSpec.normal)) register.expectNoMessage() - sender.expectMsg(RES_GETINFO(a, a2, NORMAL, ChannelCodecsSpec.normal)) + sender.expectMsg(RES_GET_CHANNEL_INFO(a, a2, NORMAL, ChannelCodecsSpec.normal)) } test("get sent payment info") { f => diff --git a/eclair-core/src/test/scala/fr/acinq/eclair/integration/ChannelIntegrationSpec.scala b/eclair-core/src/test/scala/fr/acinq/eclair/integration/ChannelIntegrationSpec.scala index 383083091c..c04f621937 100644 --- a/eclair-core/src/test/scala/fr/acinq/eclair/integration/ChannelIntegrationSpec.scala +++ b/eclair-core/src/test/scala/fr/acinq/eclair/integration/ChannelIntegrationSpec.scala @@ -152,12 +152,12 @@ abstract class ChannelIntegrationSpec extends IntegrationSpec { // F gets the htlc val htlc = htlcReceiver.expectMsgType[IncomingPaymentPacket.FinalPacket](max = 60 seconds).add // now that we have the channel id, we retrieve channels default final addresses - sender.send(nodes("C").register, Register.Forward(sender.ref, htlc.channelId, CMD_GETSTATEDATA(ActorRef.noSender))) - val dataC = sender.expectMsgType[RES_GETSTATEDATA[DATA_NORMAL]].data + sender.send(nodes("C").register, Register.Forward(sender.ref, htlc.channelId, CMD_GET_CHANNEL_DATA(ActorRef.noSender))) + val dataC = sender.expectMsgType[RES_GET_CHANNEL_DATA[DATA_NORMAL]].data assert(dataC.commitments.commitmentFormat === commitmentFormat) val finalAddressC = scriptPubKeyToAddress(dataC.commitments.localParams.defaultFinalScriptPubKey) - sender.send(nodes("F").register, Register.Forward(sender.ref, htlc.channelId, CMD_GETSTATEDATA(ActorRef.noSender))) - val dataF = sender.expectMsgType[RES_GETSTATEDATA[DATA_NORMAL]].data + sender.send(nodes("F").register, Register.Forward(sender.ref, htlc.channelId, CMD_GET_CHANNEL_DATA(ActorRef.noSender))) + val dataF = sender.expectMsgType[RES_GET_CHANNEL_DATA[DATA_NORMAL]].data assert(dataF.commitments.commitmentFormat === commitmentFormat) val finalAddressF = scriptPubKeyToAddress(dataF.commitments.localParams.defaultFinalScriptPubKey) ForceCloseFixture(sender, paymentSender, stateListenerC, stateListenerF, paymentId, htlc, preimage, minerAddress, finalAddressC, finalAddressF) @@ -251,8 +251,8 @@ abstract class ChannelIntegrationSpec extends IntegrationSpec { generateBlocks((htlc.cltvExpiry.blockHeight - getBlockHeight()).toInt, Some(minerAddress)) awaitCond(stateListenerC.expectMsgType[ChannelStateChanged](max = 60 seconds).currentState == CLOSING, max = 60 seconds) awaitCond(stateListenerF.expectMsgType[ChannelStateChanged](max = 60 seconds).currentState == CLOSING, max = 60 seconds) - sender.send(nodes("C").register, Register.Forward(sender.ref, htlc.channelId, CMD_GETSTATEDATA(ActorRef.noSender))) - val Some(localCommit) = sender.expectMsgType[RES_GETSTATEDATA[DATA_CLOSING]].data.localCommitPublished + sender.send(nodes("C").register, Register.Forward(sender.ref, htlc.channelId, CMD_GET_CHANNEL_DATA(ActorRef.noSender))) + val Some(localCommit) = sender.expectMsgType[RES_GET_CHANNEL_DATA[DATA_CLOSING]].data.localCommitPublished // we wait until the commit tx has been broadcast val bitcoinClient = new BitcoinCoreClient(bitcoinrpcclient) waitForTxBroadcastOrConfirmed(localCommit.commitTx.txid, bitcoinClient, sender) @@ -299,14 +299,14 @@ abstract class ChannelIntegrationSpec extends IntegrationSpec { sender.expectMsgType[RES_SUCCESS[CMD_FORCECLOSE]] // we wait for C to detect the unilateral close awaitCond({ - sender.send(nodes("C").register, Register.Forward(sender.ref, htlc.channelId, CMD_GETSTATEDATA(ActorRef.noSender))) - sender.expectMsgType[RES_GETSTATEDATA[ChannelData]].data match { + sender.send(nodes("C").register, Register.Forward(sender.ref, htlc.channelId, CMD_GET_CHANNEL_DATA(ActorRef.noSender))) + sender.expectMsgType[RES_GET_CHANNEL_DATA[ChannelData]].data match { case d: DATA_CLOSING if d.remoteCommitPublished.nonEmpty => true case _ => false } }, max = 30 seconds, interval = 1 second) - sender.send(nodes("C").register, Register.Forward(sender.ref, htlc.channelId, CMD_GETSTATEDATA(ActorRef.noSender))) - val Some(remoteCommit) = sender.expectMsgType[RES_GETSTATEDATA[DATA_CLOSING]].data.remoteCommitPublished + sender.send(nodes("C").register, Register.Forward(sender.ref, htlc.channelId, CMD_GET_CHANNEL_DATA(ActorRef.noSender))) + val Some(remoteCommit) = sender.expectMsgType[RES_GET_CHANNEL_DATA[DATA_CLOSING]].data.remoteCommitPublished // we generate enough blocks to make the htlc timeout generateBlocks((htlc.cltvExpiry.blockHeight - getBlockHeight()).toInt, Some(minerAddress)) // we wait until the claim-htlc-timeout has been broadcast @@ -422,8 +422,8 @@ abstract class ChannelIntegrationSpec extends IntegrationSpec { // we then generate blocks to make htlcs timeout (nothing will happen in the channel because all of them have already been fulfilled) generateBlocks(40) // we retrieve C's default final address - sender.send(nodes("C").register, Register.Forward(sender.ref, commitmentsF.channelId, CMD_GETSTATEDATA(ActorRef.noSender))) - val finalAddressC = scriptPubKeyToAddress(sender.expectMsgType[RES_GETSTATEDATA[DATA_NORMAL]].data.commitments.localParams.defaultFinalScriptPubKey) + sender.send(nodes("C").register, Register.Forward(sender.ref, commitmentsF.channelId, CMD_GET_CHANNEL_DATA(ActorRef.noSender))) + val finalAddressC = scriptPubKeyToAddress(sender.expectMsgType[RES_GET_CHANNEL_DATA[DATA_NORMAL]].data.commitments.localParams.defaultFinalScriptPubKey) // we prepare the revoked transactions F will publish val keyManagerF = nodes("F").nodeParams.channelKeyManager val channelKeyPathF = keyManagerF.keyPath(commitmentsF.localParams, commitmentsF.channelConfig) @@ -491,32 +491,32 @@ class StandardChannelIntegrationSpec extends ChannelIntegrationSpec { sender.send(fundee.register, Symbol("channels")) val Some((_, fundeeChannel)) = sender.expectMsgType[Map[ByteVector32, ActorRef]].find(_._1 == tempChannelId) - sender.send(fundeeChannel, CMD_GETSTATEDATA(ActorRef.noSender)) - val channelId = sender.expectMsgType[RES_GETSTATEDATA[PersistentChannelData]].data.channelId + sender.send(fundeeChannel, CMD_GET_CHANNEL_DATA(ActorRef.noSender)) + val channelId = sender.expectMsgType[RES_GET_CHANNEL_DATA[PersistentChannelData]].data.channelId awaitCond({ - funder.register ! Register.Forward(sender.ref, channelId, CMD_GETSTATE(ActorRef.noSender)) - sender.expectMsgType[RES_GETSTATE[_]].state == WAIT_FOR_FUNDING_LOCKED + funder.register ! Register.Forward(sender.ref, channelId, CMD_GET_CHANNEL_STATE(ActorRef.noSender)) + sender.expectMsgType[RES_GET_CHANNEL_STATE].state == WAIT_FOR_FUNDING_LOCKED }) generateBlocks(6) // after 8 blocks the fundee is still waiting for more confirmations - fundee.register ! Register.Forward(sender.ref, channelId, CMD_GETSTATE(ActorRef.noSender)) - assert(sender.expectMsgType[RES_GETSTATE[_]].state == WAIT_FOR_FUNDING_CONFIRMED) + fundee.register ! Register.Forward(sender.ref, channelId, CMD_GET_CHANNEL_STATE(ActorRef.noSender)) + assert(sender.expectMsgType[RES_GET_CHANNEL_STATE].state == WAIT_FOR_FUNDING_CONFIRMED) // after 8 blocks the funder is still waiting for funding_locked from the fundee - funder.register ! Register.Forward(sender.ref, channelId, CMD_GETSTATE(ActorRef.noSender)) - assert(sender.expectMsgType[RES_GETSTATE[_]].state == WAIT_FOR_FUNDING_LOCKED) + funder.register ! Register.Forward(sender.ref, channelId, CMD_GET_CHANNEL_STATE(ActorRef.noSender)) + assert(sender.expectMsgType[RES_GET_CHANNEL_STATE].state == WAIT_FOR_FUNDING_LOCKED) // simulate a disconnection sender.send(funder.switchboard, Peer.Disconnect(fundee.nodeParams.nodeId)) assert(sender.expectMsgType[String] == "disconnecting") awaitCond({ - fundee.register ! Register.Forward(sender.ref, channelId, CMD_GETSTATE(ActorRef.noSender)) - val fundeeState = sender.expectMsgType[RES_GETSTATE[_]].state - funder.register ! Register.Forward(sender.ref, channelId, CMD_GETSTATE(ActorRef.noSender)) - val funderState = sender.expectMsgType[RES_GETSTATE[_]].state + fundee.register ! Register.Forward(sender.ref, channelId, CMD_GET_CHANNEL_STATE(ActorRef.noSender)) + val fundeeState = sender.expectMsgType[RES_GET_CHANNEL_STATE].state + funder.register ! Register.Forward(sender.ref, channelId, CMD_GET_CHANNEL_STATE(ActorRef.noSender)) + val funderState = sender.expectMsgType[RES_GET_CHANNEL_STATE].state fundeeState == OFFLINE && funderState == OFFLINE }) @@ -531,10 +531,10 @@ class StandardChannelIntegrationSpec extends ChannelIntegrationSpec { )) sender.expectMsgType[PeerConnection.ConnectionResult.HasConnection](30 seconds) - fundee.register ! Register.Forward(sender.ref, channelId, CMD_GETSTATE(ActorRef.noSender)) - val fundeeState = sender.expectMsgType[RES_GETSTATE[ChannelState]].state - funder.register ! Register.Forward(sender.ref, channelId, CMD_GETSTATE(ActorRef.noSender)) - val funderState = sender.expectMsgType[RES_GETSTATE[ChannelState]].state + fundee.register ! Register.Forward(sender.ref, channelId, CMD_GET_CHANNEL_STATE(ActorRef.noSender)) + val fundeeState = sender.expectMsgType[RES_GET_CHANNEL_STATE].state + funder.register ! Register.Forward(sender.ref, channelId, CMD_GET_CHANNEL_STATE(ActorRef.noSender)) + val funderState = sender.expectMsgType[RES_GET_CHANNEL_STATE].state fundeeState == WAIT_FOR_FUNDING_CONFIRMED && funderState == WAIT_FOR_FUNDING_LOCKED }, max = 30 seconds, interval = 10 seconds) @@ -542,10 +542,10 @@ class StandardChannelIntegrationSpec extends ChannelIntegrationSpec { generateBlocks(5) awaitCond({ - fundee.register ! Register.Forward(sender.ref, channelId, CMD_GETSTATE(ActorRef.noSender)) - val fundeeState = sender.expectMsgType[RES_GETSTATE[ChannelState]].state - funder.register ! Register.Forward(sender.ref, channelId, CMD_GETSTATE(ActorRef.noSender)) - val funderState = sender.expectMsgType[RES_GETSTATE[ChannelState]].state + fundee.register ! Register.Forward(sender.ref, channelId, CMD_GET_CHANNEL_STATE(ActorRef.noSender)) + val fundeeState = sender.expectMsgType[RES_GET_CHANNEL_STATE].state + funder.register ! Register.Forward(sender.ref, channelId, CMD_GET_CHANNEL_STATE(ActorRef.noSender)) + val funderState = sender.expectMsgType[RES_GET_CHANNEL_STATE].state fundeeState == NORMAL && funderState == NORMAL }) @@ -555,12 +555,12 @@ class StandardChannelIntegrationSpec extends ChannelIntegrationSpec { funder.system.eventStream.subscribe(stateListener.ref, classOf[ChannelStateChanged]) // close that wumbo channel - sender.send(funder.register, Register.Forward(sender.ref, channelId, CMD_GETSTATEDATA(ActorRef.noSender))) - val commitmentsC = sender.expectMsgType[RES_GETSTATEDATA[DATA_NORMAL]].data.commitments + sender.send(funder.register, Register.Forward(sender.ref, channelId, CMD_GET_CHANNEL_DATA(ActorRef.noSender))) + val commitmentsC = sender.expectMsgType[RES_GET_CHANNEL_DATA[DATA_NORMAL]].data.commitments val finalPubKeyScriptC = commitmentsC.localParams.defaultFinalScriptPubKey val fundingOutpoint = commitmentsC.commitInput.outPoint - sender.send(fundee.register, Register.Forward(sender.ref, channelId, CMD_GETSTATEDATA(ActorRef.noSender))) - val finalPubKeyScriptF = sender.expectMsgType[RES_GETSTATEDATA[DATA_NORMAL]].data.commitments.localParams.defaultFinalScriptPubKey + sender.send(fundee.register, Register.Forward(sender.ref, channelId, CMD_GET_CHANNEL_DATA(ActorRef.noSender))) + val finalPubKeyScriptF = sender.expectMsgType[RES_GET_CHANNEL_DATA[DATA_NORMAL]].data.commitments.localParams.defaultFinalScriptPubKey fundee.register ! Register.Forward(sender.ref, channelId, CMD_CLOSE(sender.ref, Some(finalPubKeyScriptF), None)) sender.expectMsgType[RES_SUCCESS[CMD_CLOSE]] @@ -667,8 +667,8 @@ abstract class AnchorChannelIntegrationSpec extends ChannelIntegrationSpec { // retrieve the channelId of C <--> F val Some(channelId) = sender.expectMsgType[Map[ByteVector32, PublicKey]].find(_._2 == nodes("C").nodeParams.nodeId).map(_._1) - sender.send(nodes("F").register, Register.Forward(sender.ref, channelId, CMD_GETSTATEDATA(ActorRef.noSender))) - val initialStateDataF = sender.expectMsgType[RES_GETSTATEDATA[DATA_NORMAL]].data + sender.send(nodes("F").register, Register.Forward(sender.ref, channelId, CMD_GET_CHANNEL_DATA(ActorRef.noSender))) + val initialStateDataF = sender.expectMsgType[RES_GET_CHANNEL_DATA[DATA_NORMAL]].data assert(initialStateDataF.commitments.channelType === expectedChannelType) val initialCommitmentIndex = initialStateDataF.commitments.localCommit.index @@ -692,13 +692,13 @@ abstract class AnchorChannelIntegrationSpec extends ChannelIntegrationSpec { // we make sure the htlc has been removed from F's commitment before we force-close awaitCond({ - sender.send(nodes("F").register, Register.Forward(sender.ref, channelId, CMD_GETSTATEDATA(ActorRef.noSender))) - val stateDataF = sender.expectMsgType[RES_GETSTATEDATA[DATA_NORMAL]].data + sender.send(nodes("F").register, Register.Forward(sender.ref, channelId, CMD_GET_CHANNEL_DATA(ActorRef.noSender))) + val stateDataF = sender.expectMsgType[RES_GET_CHANNEL_DATA[DATA_NORMAL]].data stateDataF.commitments.localCommit.spec.htlcs.isEmpty }, max = 20 seconds, interval = 1 second) - sender.send(nodes("F").register, Register.Forward(sender.ref, channelId, CMD_GETSTATEDATA(ActorRef.noSender))) - val stateDataF = sender.expectMsgType[RES_GETSTATEDATA[DATA_NORMAL]].data + sender.send(nodes("F").register, Register.Forward(sender.ref, channelId, CMD_GET_CHANNEL_DATA(ActorRef.noSender))) + val stateDataF = sender.expectMsgType[RES_GET_CHANNEL_DATA[DATA_NORMAL]].data val commitmentIndex = stateDataF.commitments.localCommit.index val commitTx = stateDataF.commitments.localCommit.commitTxAndRemoteSig.commitTx.tx val Some(toRemoteOutCNew) = commitTx.txOut.find(_.publicKeyScript == Script.write(toRemoteAddress)) diff --git a/eclair-core/src/test/scala/fr/acinq/eclair/integration/PaymentIntegrationSpec.scala b/eclair-core/src/test/scala/fr/acinq/eclair/integration/PaymentIntegrationSpec.scala index a81f02ac00..246f9b4ea8 100644 --- a/eclair-core/src/test/scala/fr/acinq/eclair/integration/PaymentIntegrationSpec.scala +++ b/eclair-core/src/test/scala/fr/acinq/eclair/integration/PaymentIntegrationSpec.scala @@ -180,8 +180,8 @@ class PaymentIntegrationSpec extends IntegrationSpec { sender.send(nodes("B").router, Router.GetChannels) val shortIdBC = sender.expectMsgType[Iterable[ChannelAnnouncement]].find(c => Set(c.nodeId1, c.nodeId2) == Set(nodes("B").nodeParams.nodeId, nodes("C").nodeParams.nodeId)).get.shortChannelId // we also need the full commitment - nodes("B").register ! Register.ForwardShortId(sender.ref, shortIdBC, CMD_GETINFO(ActorRef.noSender)) - val commitmentBC = sender.expectMsgType[RES_GETINFO].data.asInstanceOf[DATA_NORMAL].commitments + nodes("B").register ! Register.ForwardShortId(sender.ref, shortIdBC, CMD_GET_CHANNEL_INFO(ActorRef.noSender)) + val commitmentBC = sender.expectMsgType[RES_GET_CHANNEL_INFO].data.asInstanceOf[DATA_NORMAL].commitments // we then forge a new channel_update for B-C... val channelUpdateBC = Announcements.makeChannelUpdate(Block.RegtestGenesisBlock.hash, nodes("B").nodeParams.privateKey, nodes("C").nodeParams.nodeId, shortIdBC, nodes("B").nodeParams.channelConf.expiryDelta + 1, nodes("C").nodeParams.channelConf.htlcMinimum, nodes("B").nodeParams.relayParams.publicChannelFees.feeBase, nodes("B").nodeParams.relayParams.publicChannelFees.feeProportionalMillionths, 500000000 msat) // ...and notify B's relayer @@ -212,8 +212,8 @@ class PaymentIntegrationSpec extends IntegrationSpec { // first let's wait 3 seconds to make sure the timestamp of the new channel_update will be strictly greater than the former sender.expectNoMessage(3 seconds) nodes("B").register ! Register.ForwardShortId(sender.ref, shortIdBC, BroadcastChannelUpdate(PeriodicRefresh)) - nodes("B").register ! Register.ForwardShortId(sender.ref, shortIdBC, CMD_GETINFO(ActorRef.noSender)) - val channelUpdateBC_new = sender.expectMsgType[RES_GETINFO].data.asInstanceOf[DATA_NORMAL].channelUpdate + nodes("B").register ! Register.ForwardShortId(sender.ref, shortIdBC, CMD_GET_CHANNEL_INFO(ActorRef.noSender)) + val channelUpdateBC_new = sender.expectMsgType[RES_GET_CHANNEL_INFO].data.asInstanceOf[DATA_NORMAL].channelUpdate logger.info(s"channelUpdateBC=$channelUpdateBC") logger.info(s"channelUpdateBC_new=$channelUpdateBC_new") assert(channelUpdateBC_new.timestamp > channelUpdateBC.timestamp) diff --git a/eclair-core/src/test/scala/fr/acinq/eclair/interop/rustytests/SynchronizationPipe.scala b/eclair-core/src/test/scala/fr/acinq/eclair/interop/rustytests/SynchronizationPipe.scala index 17ea91aefa..4fba26eb41 100644 --- a/eclair-core/src/test/scala/fr/acinq/eclair/interop/rustytests/SynchronizationPipe.scala +++ b/eclair-core/src/test/scala/fr/acinq/eclair/interop/rustytests/SynchronizationPipe.scala @@ -81,7 +81,7 @@ class SynchronizationPipe(latch: CountDownLatch) extends Actor with ActorLogging fout.newLine() exec(rest, a, b) case dump(x) :: rest => - resolve(x) ! CMD_GETSTATEDATA(ActorRef.noSender) + resolve(x) ! CMD_GET_CHANNEL_DATA(ActorRef.noSender) context.become(wait(a, b, script)) case "" :: rest => exec(rest, a, b) @@ -126,7 +126,7 @@ class SynchronizationPipe(latch: CountDownLatch) extends Actor with ActorLogging a forward msg unstashAll() exec(script.drop(1), a, b) - case RES_GETSTATEDATA(d: DATA_NORMAL) if script.head.endsWith(":dump") => + case RES_GET_CHANNEL_DATA(d: DATA_NORMAL) if script.head.endsWith(":dump") => def rtrim(s: String) = s.replaceAll("\\s+$", "") import d.commitments._ val l = List( From 9c40a110ffb1ccd42fd748639d373846e465528d Mon Sep 17 00:00:00 2001 From: t-bast Date: Thu, 7 Apr 2022 14:42:00 +0200 Subject: [PATCH 5/6] Refactor channel transition handlers --- .../fr/acinq/eclair/channel/fsm/Channel.scala | 51 ++++++++++--------- 1 file changed, 26 insertions(+), 25 deletions(-) diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/channel/fsm/Channel.scala b/eclair-core/src/main/scala/fr/acinq/eclair/channel/fsm/Channel.scala index e8d8aa147d..a2fd81a407 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/channel/fsm/Channel.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/channel/fsm/Channel.scala @@ -34,9 +34,9 @@ import fr.acinq.eclair.channel.Helpers.Syncing.SyncResult import fr.acinq.eclair.channel.Helpers.{Closing, Syncing, getRelayFees} import fr.acinq.eclair.channel.Monitoring.Metrics.ProcessMessage import fr.acinq.eclair.channel.Monitoring.{Metrics, Tags} +import fr.acinq.eclair.channel._ import fr.acinq.eclair.channel.publish.TxPublisher import fr.acinq.eclair.channel.publish.TxPublisher.{PublishFinalTx, SetChannelId} -import fr.acinq.eclair.channel._ import fr.acinq.eclair.crypto.keymanager.ChannelKeyManager import fr.acinq.eclair.db.DbEventHandler.ChannelEvent.EventType import fr.acinq.eclair.db.PendingCommandsDb @@ -1596,43 +1596,44 @@ class Channel(val nodeParams: NodeParams, val wallet: OnChainChannelFunder, val // if channel is private, we send the channel_update directly to remote // they need it "to learn the other end's forwarding parameters" (BOLT 7) (state, nextState, stateData, nextStateData) match { - case (_, _, d1: DATA_NORMAL, d2: DATA_NORMAL) if !d1.commitments.announceChannel && !d1.buried && d2.buried => + case (NORMAL | SYNCING, NORMAL, d1: DATA_NORMAL, d2: DATA_NORMAL) if !d1.commitments.announceChannel && !d1.buried && d2.buried => // for a private channel, when the tx was just buried we need to send the channel_update to our peer (even if it didn't change) send(d2.channelUpdate) case (SYNCING, NORMAL, d1: DATA_NORMAL, d2: DATA_NORMAL) if !d1.commitments.announceChannel && d2.buried => // otherwise if we're coming back online, we rebroadcast the latest channel_update // this makes sure that if the channel_update was missed, we have a chance to re-send it send(d2.channelUpdate) - case (_, _, d1: DATA_NORMAL, d2: DATA_NORMAL) if !d1.commitments.announceChannel && d1.channelUpdate != d2.channelUpdate && d2.buried => + case (NORMAL | SYNCING, NORMAL, d1: DATA_NORMAL, d2: DATA_NORMAL) if !d1.commitments.announceChannel && d1.channelUpdate != d2.channelUpdate && d2.buried => // otherwise, we only send it when it is different, and tx is already buried send(d2.channelUpdate) case _ => () } - (state, nextState, stateData, nextStateData) match { - // ORDER MATTERS! - case (WAIT_FOR_INIT_INTERNAL, OFFLINE, _, normal: DATA_NORMAL) => - Logs.withMdc(diagLog)(Logs.mdc(category_opt = Some(Logs.LogCategory.CONNECTION))) { - log.debug("re-emitting channel_update={} enabled={} ", normal.channelUpdate, normal.channelUpdate.channelFlags.isEnabled) - } - context.system.eventStream.publish(LocalChannelUpdate(self, normal.commitments.channelId, normal.shortChannelId, normal.commitments.remoteParams.nodeId, normal.channelAnnouncement, normal.channelUpdate, normal.commitments)) - case (_, _, d1: DATA_NORMAL, d2: DATA_NORMAL) if d1.channelUpdate == d2.channelUpdate && d1.channelAnnouncement == d2.channelAnnouncement => - // don't do anything if neither the channel_update nor the channel_announcement didn't change - () - case (WAIT_FOR_FUNDING_LOCKED | NORMAL | OFFLINE | SYNCING, NORMAL | OFFLINE, _, normal: DATA_NORMAL) => - // when we do WAIT_FOR_FUNDING_LOCKED->NORMAL or NORMAL->NORMAL or SYNCING->NORMAL or NORMAL->OFFLINE, we send out the new channel_update (most of the time it will just be to enable/disable the channel) - log.info("emitting channel_update={} enabled={} ", normal.channelUpdate, normal.channelUpdate.channelFlags.isEnabled) - context.system.eventStream.publish(LocalChannelUpdate(self, normal.commitments.channelId, normal.shortChannelId, normal.commitments.remoteParams.nodeId, normal.channelAnnouncement, normal.channelUpdate, normal.commitments)) - case (_, _, _: DATA_NORMAL, _: DATA_NORMAL) => - // in any other case (e.g. OFFLINE->SYNCING) we do nothing - () - case (_, _, normal: DATA_NORMAL, _) => - // when we finally leave the NORMAL state (or OFFLINE with NORMAL data) to go to SHUTDOWN/NEGOTIATING/CLOSING/ERR*, we advertise the fact that channel can't be used for payments anymore - // if the channel is private we don't really need to tell the counterparty because it is already aware that the channel is being closed - context.system.eventStream.publish(LocalChannelDown(self, normal.commitments.channelId, normal.shortChannelId, normal.commitments.remoteParams.nodeId)) - case _ => () + sealed trait EmitLocalChannelEvent + case class EmitLocalChannelUpdate(d: DATA_NORMAL) extends EmitLocalChannelEvent + case class EmitLocalChannelDown(d: DATA_NORMAL) extends EmitLocalChannelEvent + + val emitEvent_opt: Option[EmitLocalChannelEvent] = (state, nextState, stateData, nextStateData) match { + case (WAIT_FOR_INIT_INTERNAL, OFFLINE, _, d: DATA_NORMAL) => Some(EmitLocalChannelUpdate(d)) + case (WAIT_FOR_FUNDING_LOCKED, NORMAL, _, d: DATA_NORMAL) => Some(EmitLocalChannelUpdate(d)) + case (NORMAL, NORMAL, d1: DATA_NORMAL, d2: DATA_NORMAL) if d1.channelUpdate != d2.channelUpdate || d1.channelAnnouncement != d2.channelAnnouncement => Some(EmitLocalChannelUpdate(d2)) + case (SYNCING, NORMAL, d1: DATA_NORMAL, d2: DATA_NORMAL) if d1.channelUpdate != d2.channelUpdate || d1.channelAnnouncement != d2.channelAnnouncement => Some(EmitLocalChannelUpdate(d2)) + case (NORMAL, OFFLINE, d1: DATA_NORMAL, d2: DATA_NORMAL) if d1.channelUpdate != d2.channelUpdate || d1.channelAnnouncement != d2.channelAnnouncement => Some(EmitLocalChannelUpdate(d2)) + case (OFFLINE, OFFLINE, d1: DATA_NORMAL, d2: DATA_NORMAL) if d1.channelUpdate != d2.channelUpdate || d1.channelAnnouncement != d2.channelAnnouncement => Some(EmitLocalChannelUpdate(d2)) + // When a channel that could previously be used to relay payments starts closing, we advertise the fact that this channel can't be used for payments anymore + // If the channel is private we don't really need to tell the counterparty because it is already aware that the channel is being closed + case (NORMAL | SYNCING | OFFLINE, SHUTDOWN | NEGOTIATING | CLOSING | CLOSED | ERR_INFORMATION_LEAK | WAIT_FOR_REMOTE_PUBLISH_FUTURE_COMMITMENT, d: DATA_NORMAL, _) => Some(EmitLocalChannelDown(d)) + case _ => None + } + emitEvent_opt.foreach { + case EmitLocalChannelUpdate(d) => + log.info("emitting channel_update={} enabled={} ", d.channelUpdate, d.channelUpdate.channelFlags.isEnabled) + context.system.eventStream.publish(LocalChannelUpdate(self, d.channelId, d.shortChannelId, d.commitments.remoteParams.nodeId, d.channelAnnouncement, d.channelUpdate, d.commitments)) + case EmitLocalChannelDown(d) => + context.system.eventStream.publish(LocalChannelDown(self, d.channelId, d.shortChannelId, d.commitments.remoteParams.nodeId)) } + // When we change our channel update parameters (e.g. relay fees), we want to advertise it to other actors. (stateData, nextStateData) match { // NORMAL->NORMAL, NORMAL->OFFLINE, SYNCING->NORMAL case (d1: DATA_NORMAL, d2: DATA_NORMAL) => maybeEmitChannelUpdateChangedEvent(newUpdate = d2.channelUpdate, oldUpdate_opt = Some(d1.channelUpdate), d2) From eaa488b59a308307080e71689782d19899c21567 Mon Sep 17 00:00:00 2001 From: t-bast Date: Thu, 7 Apr 2022 15:25:03 +0200 Subject: [PATCH 6/6] Address PR comments --- .../src/main/scala/fr/acinq/eclair/channel/ChannelData.scala | 1 - .../src/main/scala/fr/acinq/eclair/channel/fsm/Channel.scala | 4 ++-- .../fr/acinq/eclair/channel/fsm/ChannelOpenSingleFunder.scala | 1 - 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/channel/ChannelData.scala b/eclair-core/src/main/scala/fr/acinq/eclair/channel/ChannelData.scala index 54ce099c7c..cf7c9db348 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/channel/ChannelData.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/channel/ChannelData.scala @@ -62,7 +62,6 @@ case object CLOSED extends ChannelState case object OFFLINE extends ChannelState case object SYNCING extends ChannelState case object WAIT_FOR_REMOTE_PUBLISH_FUTURE_COMMITMENT extends ChannelState -case object ERR_FUNDING_LOST extends ChannelState case object ERR_INFORMATION_LEAK extends ChannelState /* diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/channel/fsm/Channel.scala b/eclair-core/src/main/scala/fr/acinq/eclair/channel/fsm/Channel.scala index a2fd81a407..988d5106ee 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/channel/fsm/Channel.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/channel/fsm/Channel.scala @@ -1596,14 +1596,14 @@ class Channel(val nodeParams: NodeParams, val wallet: OnChainChannelFunder, val // if channel is private, we send the channel_update directly to remote // they need it "to learn the other end's forwarding parameters" (BOLT 7) (state, nextState, stateData, nextStateData) match { - case (NORMAL | SYNCING, NORMAL, d1: DATA_NORMAL, d2: DATA_NORMAL) if !d1.commitments.announceChannel && !d1.buried && d2.buried => + case (NORMAL, NORMAL, d1: DATA_NORMAL, d2: DATA_NORMAL) if !d1.commitments.announceChannel && !d1.buried && d2.buried => // for a private channel, when the tx was just buried we need to send the channel_update to our peer (even if it didn't change) send(d2.channelUpdate) case (SYNCING, NORMAL, d1: DATA_NORMAL, d2: DATA_NORMAL) if !d1.commitments.announceChannel && d2.buried => // otherwise if we're coming back online, we rebroadcast the latest channel_update // this makes sure that if the channel_update was missed, we have a chance to re-send it send(d2.channelUpdate) - case (NORMAL | SYNCING, NORMAL, d1: DATA_NORMAL, d2: DATA_NORMAL) if !d1.commitments.announceChannel && d1.channelUpdate != d2.channelUpdate && d2.buried => + case (NORMAL, NORMAL, d1: DATA_NORMAL, d2: DATA_NORMAL) if !d1.commitments.announceChannel && d1.channelUpdate != d2.channelUpdate && d2.buried => // otherwise, we only send it when it is different, and tx is already buried send(d2.channelUpdate) case _ => () diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/channel/fsm/ChannelOpenSingleFunder.scala b/eclair-core/src/main/scala/fr/acinq/eclair/channel/fsm/ChannelOpenSingleFunder.scala index 0f974a150e..6bf5fa5389 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/channel/fsm/ChannelOpenSingleFunder.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/channel/fsm/ChannelOpenSingleFunder.scala @@ -50,7 +50,6 @@ trait ChannelOpenSingleFunder extends FundingHandlers with ErrorHandlers { this: Channel => /* - NEW FUNDER FUNDEE | | | open_channel |WAIT_FOR_OPEN_CHANNEL