From 823aaedc1cfa54a3cdcb3e9867272b32e844a04f Mon Sep 17 00:00:00 2001 From: sstone Date: Mon, 16 Sep 2019 17:25:40 +0200 Subject: [PATCH] Add a "funding pubkey path" option to the channel version field This option is checked when we need to compute channel keys. For old channels it won't be set, and we always set it for new ones. --- .../fr/acinq/eclair/channel/Channel.scala | 30 ++++++++-------- .../acinq/eclair/channel/ChannelTypes.scala | 29 +++++++-------- .../fr/acinq/eclair/channel/Commitments.scala | 16 ++++----- .../fr/acinq/eclair/channel/Helpers.scala | 25 ++++++------- .../fr/acinq/eclair/crypto/KeyManager.scala | 9 +++++ .../main/scala/fr/acinq/eclair/io/Peer.scala | 3 +- .../fr/acinq/eclair/wire/ChannelCodecs.scala | 12 +------ .../states/StateTestsHelperMethods.scala | 2 +- .../a/WaitForAcceptChannelStateSpec.scala | 2 +- .../a/WaitForOpenChannelStateSpec.scala | 4 +-- ...itForFundingCreatedInternalStateSpec.scala | 4 +-- .../b/WaitForFundingCreatedStateSpec.scala | 2 +- .../b/WaitForFundingSignedStateSpec.scala | 3 +- .../c/WaitForFundingConfirmedStateSpec.scala | 2 +- .../c/WaitForFundingLockedStateSpec.scala | 2 +- .../channel/states/e/OfflineStateSpec.scala | 8 ++--- .../channel/states/h/ClosingStateSpec.scala | 2 +- .../eclair/transactions/LocalParamsSpec.scala | 35 ------------------- .../acinq/eclair/wire/ChannelCodecsSpec.scala | 2 -- 19 files changed, 73 insertions(+), 119 deletions(-) delete mode 100644 eclair-core/src/test/scala/fr/acinq/eclair/transactions/LocalParamsSpec.scala diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/channel/Channel.scala b/eclair-core/src/main/scala/fr/acinq/eclair/channel/Channel.scala index 700f98a4ef..9e92ead3e1 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/channel/Channel.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/channel/Channel.scala @@ -145,11 +145,11 @@ class Channel(val nodeParams: NodeParams, val wallet: EclairWallet, remoteNodeId startWith(WAIT_FOR_INIT_INTERNAL, Nothing) when(WAIT_FOR_INIT_INTERNAL)(handleExceptions { - case Event(initFunder@INPUT_INIT_FUNDER(temporaryChannelId, fundingSatoshis, pushMsat, initialFeeratePerKw, fundingTxFeeratePerKw, localParams, remote, _, channelFlags, _), Nothing) => + case Event(initFunder@INPUT_INIT_FUNDER(temporaryChannelId, fundingSatoshis, pushMsat, initialFeeratePerKw, fundingTxFeeratePerKw, localParams, remote, _, channelFlags, channelVersion), Nothing) => context.system.eventStream.publish(ChannelCreated(self, context.parent, remoteNodeId, isFunder = true, temporaryChannelId, initialFeeratePerKw, Some(fundingTxFeeratePerKw))) forwarder ! remote val fundingPubKey = keyManager.fundingPublicKey(localParams.fundingKeyPath).publicKey - val channelKeyPath = localParams.channelKeyPath(nodeParams.keyManager) + val channelKeyPath = keyManager.channelKeyPath(localParams, channelVersion) val open = OpenChannel(nodeParams.chainHash, temporaryChannelId = temporaryChannelId, fundingSatoshis = fundingSatoshis, @@ -161,7 +161,7 @@ class Channel(val nodeParams: NodeParams, val wallet: EclairWallet, remoteNodeId feeratePerKw = initialFeeratePerKw, toSelfDelay = localParams.toSelfDelay, maxAcceptedHtlcs = localParams.maxAcceptedHtlcs, - fundingPubkey = keyManager.fundingPublicKey(localParams.fundingKeyPath).publicKey, + fundingPubkey = fundingPubKey, revocationBasepoint = keyManager.revocationPoint(channelKeyPath).publicKey, paymentBasepoint = keyManager.paymentPoint(channelKeyPath).publicKey, delayedPaymentBasepoint = keyManager.delayedPaymentPoint(channelKeyPath).publicKey, @@ -273,7 +273,9 @@ class Channel(val nodeParams: NodeParams, val wallet: EclairWallet, remoteNodeId case Failure(t) => handleLocalError(t, d, Some(open)) case Success(_) => context.system.eventStream.publish(ChannelCreated(self, context.parent, remoteNodeId, isFunder = false, open.temporaryChannelId, open.feeratePerKw, None)) - val channelKeyPath = localParams.channelKeyPath(nodeParams.keyManager) + val fundingPubkey = keyManager.fundingPublicKey(localParams.fundingKeyPath).publicKey + val channelVersion = ChannelVersion.STANDARD | ChannelVersion.USE_PUBKEY_KEYPATH + val channelKeyPath = keyManager.channelKeyPath(localParams, channelVersion) // TODO: maybe also check uniqueness of temporary channel id val minimumDepth = nodeParams.minDepthBlocks val accept = AcceptChannel(temporaryChannelId = open.temporaryChannelId, @@ -284,7 +286,7 @@ class Channel(val nodeParams: NodeParams, val wallet: EclairWallet, remoteNodeId htlcMinimumMsat = localParams.htlcMinimum, toSelfDelay = localParams.toSelfDelay, maxAcceptedHtlcs = localParams.maxAcceptedHtlcs, - fundingPubkey = keyManager.fundingPublicKey(localParams.fundingKeyPath).publicKey, + fundingPubkey = fundingPubkey, revocationBasepoint = keyManager.revocationPoint(channelKeyPath).publicKey, paymentBasepoint = keyManager.paymentPoint(channelKeyPath).publicKey, delayedPaymentBasepoint = keyManager.delayedPaymentPoint(channelKeyPath).publicKey, @@ -306,7 +308,7 @@ class Channel(val nodeParams: NodeParams, val wallet: EclairWallet, remoteNodeId globalFeatures = remoteInit.globalFeatures, localFeatures = remoteInit.localFeatures) log.debug(s"remote params: $remoteParams") - goto(WAIT_FOR_FUNDING_CREATED) using DATA_WAIT_FOR_FUNDING_CREATED(open.temporaryChannelId, localParams, remoteParams, open.fundingSatoshis, open.pushMsat, open.feeratePerKw, open.firstPerCommitmentPoint, open.channelFlags, ChannelVersion.STANDARD, accept) sending accept + goto(WAIT_FOR_FUNDING_CREATED) using DATA_WAIT_FOR_FUNDING_CREATED(open.temporaryChannelId, localParams, remoteParams, open.fundingSatoshis, open.pushMsat, open.feeratePerKw, open.firstPerCommitmentPoint, open.channelFlags, channelVersion, accept) sending accept } case Event(CMD_CLOSE(_), _) => goto(CLOSED) replying "ok" @@ -365,7 +367,7 @@ class Channel(val nodeParams: NodeParams, val wallet: EclairWallet, remoteNodeId when(WAIT_FOR_FUNDING_INTERNAL)(handleExceptions { case Event(MakeFundingTxResponse(fundingTx, fundingTxOutputIndex, fundingTxFee), DATA_WAIT_FOR_FUNDING_INTERNAL(temporaryChannelId, localParams, remoteParams, fundingAmount, pushMsat, initialFeeratePerKw, remoteFirstPerCommitmentPoint, channelVersion, open)) => // let's create the first commitment tx that spends the yet uncommitted funding tx - val (localSpec, localCommitTx, remoteSpec, remoteCommitTx) = Funding.makeFirstCommitTxs(keyManager, temporaryChannelId, localParams, remoteParams, fundingAmount, pushMsat, initialFeeratePerKw, fundingTx.hash, fundingTxOutputIndex, remoteFirstPerCommitmentPoint, nodeParams.onChainFeeConf.maxFeerateMismatch) + val (localSpec, localCommitTx, remoteSpec, remoteCommitTx) = Funding.makeFirstCommitTxs(keyManager, channelVersion, temporaryChannelId, localParams, remoteParams, fundingAmount, pushMsat, initialFeeratePerKw, fundingTx.hash, fundingTxOutputIndex, remoteFirstPerCommitmentPoint, nodeParams.onChainFeeConf.maxFeerateMismatch) require(fundingTx.txOut(fundingTxOutputIndex).publicKeyScript == localCommitTx.input.txOut.publicKeyScript, s"pubkey script mismatch!") val localSigOfRemoteTx = keyManager.sign(remoteCommitTx, keyManager.fundingPublicKey(localParams.fundingKeyPath)) // signature of their initial commitment tx that pays remote pushMsat @@ -406,7 +408,7 @@ class Channel(val nodeParams: NodeParams, val wallet: EclairWallet, remoteNodeId when(WAIT_FOR_FUNDING_CREATED)(handleExceptions { case Event(FundingCreated(_, fundingTxHash, fundingTxOutputIndex, remoteSig), d@DATA_WAIT_FOR_FUNDING_CREATED(temporaryChannelId, localParams, remoteParams, fundingAmount, pushMsat, initialFeeratePerKw, remoteFirstPerCommitmentPoint, channelFlags, channelVersion, _)) => // they fund the channel with their funding tx, so the money is theirs (but we are paid pushMsat) - val (localSpec, localCommitTx, remoteSpec, remoteCommitTx) = Funding.makeFirstCommitTxs(keyManager, temporaryChannelId, localParams, remoteParams, fundingAmount, pushMsat, initialFeeratePerKw, fundingTxHash, fundingTxOutputIndex, remoteFirstPerCommitmentPoint, nodeParams.onChainFeeConf.maxFeerateMismatch) + val (localSpec, localCommitTx, remoteSpec, remoteCommitTx) = Funding.makeFirstCommitTxs(keyManager, channelVersion, temporaryChannelId, localParams, remoteParams, fundingAmount, pushMsat, initialFeeratePerKw, fundingTxHash, fundingTxOutputIndex, remoteFirstPerCommitmentPoint, nodeParams.onChainFeeConf.maxFeerateMismatch) // check remote signature validity val fundingPubKey = keyManager.fundingPublicKey(localParams.fundingKeyPath) @@ -529,8 +531,7 @@ class Channel(val nodeParams: NodeParams, val wallet: EclairWallet, remoteNodeId case Success(_) => log.info(s"channelId=${commitments.channelId} was confirmed at blockHeight=$blockHeight txIndex=$txIndex") blockchain ! WatchLost(self, commitments.commitInput.outPoint.txid, nodeParams.minDepthBlocks, BITCOIN_FUNDING_LOST) - val fundingPubKey = keyManager.fundingPublicKey(d.commitments.localParams.fundingKeyPath).publicKey - val channelKeyPath = d.commitments.localParams.channelKeyPath(keyManager) + val channelKeyPath = keyManager.channelKeyPath(d.commitments.localParams, commitments.channelVersion) val nextPerCommitmentPoint = keyManager.commitmentPoint(channelKeyPath, 1) val fundingLocked = FundingLocked(commitments.channelId, nextPerCommitmentPoint) deferred.foreach(self ! _) @@ -1407,8 +1408,7 @@ class Channel(val nodeParams: NodeParams, val wallet: EclairWallet, remoteNodeId forwarder ! r val yourLastPerCommitmentSecret = d.commitments.remotePerCommitmentSecrets.lastIndex.flatMap(d.commitments.remotePerCommitmentSecrets.getHash).getOrElse(ByteVector32.Zeroes) - val fundingPubKey = keyManager.fundingPublicKey(d.commitments.localParams.fundingKeyPath) - val channelKeyPath = d.commitments.localParams.channelKeyPath(keyManager) + val channelKeyPath = keyManager.channelKeyPath(d.commitments.localParams, d.commitments.channelVersion) val myCurrentPerCommitmentPoint = keyManager.commitmentPoint(channelKeyPath, d.commitments.localCommit.index) val channelReestablish = ChannelReestablish( @@ -1466,13 +1466,13 @@ class Channel(val nodeParams: NodeParams, val wallet: EclairWallet, remoteNodeId case Event(_: ChannelReestablish, d: DATA_WAIT_FOR_FUNDING_LOCKED) => log.debug(s"re-sending fundingLocked") - val channelKeyPath = d.commitments.localParams.channelKeyPath(keyManager) + val channelKeyPath = keyManager.channelKeyPath(d.commitments.localParams, d.commitments.channelVersion) val nextPerCommitmentPoint = keyManager.commitmentPoint(channelKeyPath, 1) val fundingLocked = FundingLocked(d.commitments.channelId, nextPerCommitmentPoint) goto(WAIT_FOR_FUNDING_LOCKED) sending fundingLocked case Event(channelReestablish: ChannelReestablish, d: DATA_NORMAL) => - val channelKeyPath = d.commitments.localParams.channelKeyPath(keyManager) + val channelKeyPath = keyManager.channelKeyPath(d.commitments.localParams, d.commitments.channelVersion) channelReestablish match { case ChannelReestablish(_, _, nextRemoteRevocationNumber, Some(yourLastPerCommitmentSecret), _) if !Helpers.checkLocalCommit(d, nextRemoteRevocationNumber) => // if next_remote_revocation_number is greater than our local commitment index, it means that either we are using an outdated commitment, or they are lying @@ -2126,7 +2126,7 @@ class Channel(val nodeParams: NodeParams, val wallet: EclairWallet, remoteNodeId } else if (commitments1.localCommit.index == channelReestablish.nextRemoteRevocationNumber + 1) { // our last revocation got lost, let's resend it log.debug(s"re-sending last revocation") - val channelKeyPath = d.commitments.localParams.channelKeyPath(keyManager) + val channelKeyPath = keyManager.channelKeyPath(d.commitments.localParams, d.commitments.channelVersion) val localPerCommitmentSecret = keyManager.commitmentSecret(channelKeyPath, d.commitments.localCommit.index - 1) val localNextPerCommitmentPoint = keyManager.commitmentPoint(channelKeyPath, d.commitments.localCommit.index + 1) val revocation = RevokeAndAck( diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/channel/ChannelTypes.scala b/eclair-core/src/main/scala/fr/acinq/eclair/channel/ChannelTypes.scala index ab87eb1815..dd898cb1c0 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/channel/ChannelTypes.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/channel/ChannelTypes.scala @@ -21,7 +21,6 @@ import java.util.UUID import akka.actor.ActorRef import fr.acinq.bitcoin.Crypto.PublicKey import fr.acinq.bitcoin.{ByteVector32, DeterministicWallet, OutPoint, Satoshi, Transaction} -import fr.acinq.eclair.crypto.KeyManager import fr.acinq.eclair.transactions.CommitmentSpec import fr.acinq.eclair.transactions.Transactions.CommitTx import fr.acinq.eclair.wire.{AcceptChannel, ChannelAnnouncement, ChannelReestablish, ChannelUpdate, ClosingSigned, FailureMessage, FundingCreated, FundingLocked, FundingSigned, Init, OnionRoutingPacket, OpenChannel, Shutdown, UpdateAddHtlc} @@ -190,8 +189,7 @@ final case class DATA_CLOSING(commitments: Commitments, final case class DATA_WAIT_FOR_REMOTE_PUBLISH_FUTURE_COMMITMENT(commitments: Commitments, remoteChannelReestablish: ChannelReestablish) extends Data with HasCommitments -final case class LocalParams(version: Int, - nodeId: PublicKey, +final case class LocalParams(nodeId: PublicKey, fundingKeyPath: DeterministicWallet.KeyPath, dustLimit: Satoshi, maxHtlcValueInFlightMsat: UInt64, // this is not MilliSatoshi because it can exceed the total amount of MilliSatoshi @@ -202,18 +200,7 @@ final case class LocalParams(version: Int, isFunder: Boolean, defaultFinalScriptPubKey: ByteVector, globalFeatures: ByteVector, - localFeatures: ByteVector) { - - def channelKeyPath(keyManager: KeyManager) = version match { - case 0 => - // legacy mode: we reuse the funding key path as our channel key path - fundingKeyPath - case 1 => - // deterministic mode: use the funding pubkey to compute the channel key path - KeyManager.channelKeyPath(keyManager.fundingPublicKey(fundingKeyPath)) - - } -} + localFeatures: ByteVector) final case class RemoteParams(nodeId: PublicKey, dustLimit: Satoshi, @@ -237,9 +224,19 @@ object ChannelFlags { case class ChannelVersion(bits: BitVector) { require(bits.size == ChannelVersion.LENGTH_BITS, "channel version takes 4 bytes") + + def |(other: ChannelVersion) = ChannelVersion(bits | other.bits) + def &(other: ChannelVersion) = ChannelVersion(bits & other.bits) + def ^(other: ChannelVersion) = ChannelVersion(bits ^ other.bits) + def isSet(bit: Int) = bits.reverse.get(bit) } + object ChannelVersion { + import scodec.bits._ val LENGTH_BITS = 4 * 8 - val STANDARD = ChannelVersion(BitVector.fill(LENGTH_BITS)(false)) + val ZEROES = ChannelVersion(bin"00000000000000000000000000000000") + val STANDARD = ZEROES + val USE_PUBKEY_KEYPATH_BIT = 0 // bit numbers start at 0 + val USE_PUBKEY_KEYPATH = STANDARD | ChannelVersion(bin"00000000000000000000000000000001") } // @formatter:on diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/channel/Commitments.scala b/eclair-core/src/main/scala/fr/acinq/eclair/channel/Commitments.scala index 619c6975dc..e16af2418c 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/channel/Commitments.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/channel/Commitments.scala @@ -376,11 +376,11 @@ object Commitments { case Right(remoteNextPerCommitmentPoint) => // remote commitment will includes all local changes + remote acked changes val spec = CommitmentSpec.reduce(remoteCommit.spec, remoteChanges.acked, localChanges.proposed) - val (remoteCommitTx, htlcTimeoutTxs, htlcSuccessTxs) = makeRemoteTxs(keyManager, remoteCommit.index + 1, localParams, remoteParams, commitInput, remoteNextPerCommitmentPoint, spec) + val (remoteCommitTx, htlcTimeoutTxs, htlcSuccessTxs) = makeRemoteTxs(keyManager, channelVersion, remoteCommit.index + 1, localParams, remoteParams, commitInput, remoteNextPerCommitmentPoint, spec) val sig = keyManager.sign(remoteCommitTx, keyManager.fundingPublicKey(commitments.localParams.fundingKeyPath)) val sortedHtlcTxs: Seq[TransactionWithInputInfo] = (htlcTimeoutTxs ++ htlcSuccessTxs).sortBy(_.input.outPoint.index) - val channelKeyPath = localParams.channelKeyPath(keyManager) + val channelKeyPath = keyManager.channelKeyPath(commitments.localParams, commitments.channelVersion) val htlcSigs = sortedHtlcTxs.map(keyManager.sign(_, keyManager.htlcPoint(channelKeyPath), remoteNextPerCommitmentPoint)) // NB: IN/OUT htlcs are inverted because this is the remote commit @@ -425,9 +425,9 @@ object Commitments { // receiving money i.e its commit tx has one output for them val spec = CommitmentSpec.reduce(localCommit.spec, localChanges.acked, remoteChanges.proposed) - val channelKeyPath = localParams.channelKeyPath(keyManager) + val channelKeyPath = keyManager.channelKeyPath(commitments.localParams, commitments.channelVersion) val localPerCommitmentPoint = keyManager.commitmentPoint(channelKeyPath, commitments.localCommit.index + 1) - val (localCommitTx, htlcTimeoutTxs, htlcSuccessTxs) = makeLocalTxs(keyManager, localCommit.index + 1, localParams, remoteParams, commitInput, localPerCommitmentPoint, spec) + val (localCommitTx, htlcTimeoutTxs, htlcSuccessTxs) = makeLocalTxs(keyManager, channelVersion, localCommit.index + 1, localParams, remoteParams, commitInput, localPerCommitmentPoint, spec) val sig = keyManager.sign(localCommitTx, keyManager.fundingPublicKey(commitments.localParams.fundingKeyPath)) log.info(s"built local commit number=${localCommit.index + 1} htlc_in={} htlc_out={} feeratePerKw=${spec.feeratePerKw} txid=${localCommitTx.tx.txid} tx={}", spec.htlcs.filter(_.direction == IN).map(_.add.id).mkString(","), spec.htlcs.filter(_.direction == OUT).map(_.add.id).mkString(","), localCommitTx.tx) @@ -523,8 +523,8 @@ object Commitments { } } - def makeLocalTxs(keyManager: KeyManager, commitTxNumber: Long, localParams: LocalParams, remoteParams: RemoteParams, commitmentInput: InputInfo, localPerCommitmentPoint: PublicKey, spec: CommitmentSpec): (CommitTx, Seq[HtlcTimeoutTx], Seq[HtlcSuccessTx]) = { - val channelKeyPath = localParams.channelKeyPath(keyManager) + def makeLocalTxs(keyManager: KeyManager, channelVersion: ChannelVersion, commitTxNumber: Long, localParams: LocalParams, remoteParams: RemoteParams, commitmentInput: InputInfo, localPerCommitmentPoint: PublicKey, spec: CommitmentSpec): (CommitTx, Seq[HtlcTimeoutTx], Seq[HtlcSuccessTx]) = { + val channelKeyPath = keyManager.channelKeyPath(localParams, channelVersion) val localDelayedPaymentPubkey = Generators.derivePubKey(keyManager.delayedPaymentPoint(channelKeyPath).publicKey, localPerCommitmentPoint) val localHtlcPubkey = Generators.derivePubKey(keyManager.htlcPoint(channelKeyPath).publicKey, localPerCommitmentPoint) val remotePaymentPubkey = Generators.derivePubKey(remoteParams.paymentBasepoint, localPerCommitmentPoint) @@ -535,8 +535,8 @@ object Commitments { (commitTx, htlcTimeoutTxs, htlcSuccessTxs) } - def makeRemoteTxs(keyManager: KeyManager, commitTxNumber: Long, localParams: LocalParams, remoteParams: RemoteParams, commitmentInput: InputInfo, remotePerCommitmentPoint: PublicKey, spec: CommitmentSpec): (CommitTx, Seq[HtlcTimeoutTx], Seq[HtlcSuccessTx]) = { - val channelKeyPath = localParams.channelKeyPath(keyManager) + def makeRemoteTxs(keyManager: KeyManager, channelVersion: ChannelVersion, commitTxNumber: Long, localParams: LocalParams, remoteParams: RemoteParams, commitmentInput: InputInfo, remotePerCommitmentPoint: PublicKey, spec: CommitmentSpec): (CommitTx, Seq[HtlcTimeoutTx], Seq[HtlcSuccessTx]) = { + val channelKeyPath = keyManager.channelKeyPath(localParams, channelVersion) val localPaymentPubkey = Generators.derivePubKey(keyManager.paymentPoint(channelKeyPath).publicKey, remotePerCommitmentPoint) val localHtlcPubkey = Generators.derivePubKey(keyManager.htlcPoint(channelKeyPath).publicKey, remotePerCommitmentPoint) val remoteDelayedPaymentPubkey = Generators.derivePubKey(remoteParams.delayedPaymentBasepoint, remotePerCommitmentPoint) 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 52fc9d5ce8..9a5147134d 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 @@ -252,7 +252,7 @@ object Helpers { * @param remoteFirstPerCommitmentPoint * @return (localSpec, localTx, remoteSpec, remoteTx, fundingTxOutput) */ - def makeFirstCommitTxs(keyManager: KeyManager, temporaryChannelId: ByteVector32, localParams: LocalParams, remoteParams: RemoteParams, fundingAmount: Satoshi, pushMsat: MilliSatoshi, initialFeeratePerKw: Long, fundingTxHash: ByteVector32, fundingTxOutputIndex: Int, remoteFirstPerCommitmentPoint: PublicKey, maxFeerateMismatch: Double): (CommitmentSpec, CommitTx, CommitmentSpec, CommitTx) = { + def makeFirstCommitTxs(keyManager: KeyManager, channelVersion: ChannelVersion, temporaryChannelId: ByteVector32, localParams: LocalParams, remoteParams: RemoteParams, fundingAmount: Satoshi, pushMsat: MilliSatoshi, initialFeeratePerKw: Long, fundingTxHash: ByteVector32, fundingTxOutputIndex: Int, remoteFirstPerCommitmentPoint: PublicKey, maxFeerateMismatch: Double): (CommitmentSpec, CommitTx, CommitmentSpec, CommitTx) = { val toLocalMsat = if (localParams.isFunder) fundingAmount.toMilliSatoshi - pushMsat else pushMsat val toRemoteMsat = if (localParams.isFunder) pushMsat else fundingAmount.toMilliSatoshi - pushMsat @@ -270,11 +270,11 @@ object Helpers { } val fundingPubKey = keyManager.fundingPublicKey(localParams.fundingKeyPath) - val channelKeyPath = localParams.channelKeyPath(keyManager) + val channelKeyPath = keyManager.channelKeyPath(localParams, channelVersion) val commitmentInput = makeFundingInputInfo(fundingTxHash, fundingTxOutputIndex, fundingAmount, fundingPubKey.publicKey, remoteParams.fundingPubKey) val localPerCommitmentPoint = keyManager.commitmentPoint(channelKeyPath, 0) - val (localCommitTx, _, _) = Commitments.makeLocalTxs(keyManager, 0, localParams, remoteParams, commitmentInput, localPerCommitmentPoint, localSpec) - val (remoteCommitTx, _, _) = Commitments.makeRemoteTxs(keyManager, 0, localParams, remoteParams, commitmentInput, remoteFirstPerCommitmentPoint, remoteSpec) + val (localCommitTx, _, _) = Commitments.makeLocalTxs(keyManager, channelVersion, 0, localParams, remoteParams, commitmentInput, localPerCommitmentPoint, localSpec) + val (remoteCommitTx, _, _) = Commitments.makeRemoteTxs(keyManager, channelVersion, 0, localParams, remoteParams, commitmentInput, remoteFirstPerCommitmentPoint, remoteSpec) (localSpec, localCommitTx, remoteSpec, remoteCommitTx) } @@ -501,8 +501,7 @@ object Helpers { def claimCurrentLocalCommitTxOutputs(keyManager: KeyManager, commitments: Commitments, tx: Transaction, feeEstimator: FeeEstimator, feeTargets: FeeTargets)(implicit log: LoggingAdapter): LocalCommitPublished = { import commitments._ require(localCommit.publishableTxs.commitTx.tx.txid == tx.txid, "txid mismatch, provided tx is not the current local commit tx") - val fundingPubKey = keyManager.fundingPublicKey(commitments.localParams.fundingKeyPath) - val channelKeyPath = localParams.channelKeyPath(keyManager) + val channelKeyPath = keyManager.channelKeyPath(localParams, channelVersion) val localPerCommitmentPoint = keyManager.commitmentPoint(channelKeyPath, commitments.localCommit.index.toInt) val localRevocationPubkey = Generators.revocationPubKey(remoteParams.revocationBasepoint, localPerCommitmentPoint) val localDelayedPubkey = Generators.derivePubKey(keyManager.delayedPaymentPoint(channelKeyPath).publicKey, localPerCommitmentPoint) @@ -571,12 +570,11 @@ object Helpers { * @return a list of transactions (one per HTLC that we can claim) */ def claimRemoteCommitTxOutputs(keyManager: KeyManager, commitments: Commitments, remoteCommit: RemoteCommit, tx: Transaction, feeEstimator: FeeEstimator, feeTargets: FeeTargets)(implicit log: LoggingAdapter): RemoteCommitPublished = { - import commitments.{commitInput, localParams, remoteParams} + import commitments.{channelVersion, commitInput, localParams, remoteParams} require(remoteCommit.txid == tx.txid, "txid mismatch, provided tx is not the current remote commit tx") - val (remoteCommitTx, _, _) = Commitments.makeRemoteTxs(keyManager, remoteCommit.index, localParams, remoteParams, commitInput, remoteCommit.remotePerCommitmentPoint, remoteCommit.spec) + val (remoteCommitTx, _, _) = Commitments.makeRemoteTxs(keyManager, channelVersion, remoteCommit.index, localParams, remoteParams, commitInput, remoteCommit.remotePerCommitmentPoint, remoteCommit.spec) require(remoteCommitTx.tx.txid == tx.txid, "txid mismatch, cannot recompute the current remote commit tx") - //val fundingPubKey = localParams.fundingPubKey(keyManager) - val channelKeyPath = localParams.channelKeyPath(keyManager) + val channelKeyPath = keyManager.channelKeyPath(localParams, channelVersion) val localHtlcPubkey = Generators.derivePubKey(keyManager.htlcPoint(channelKeyPath).publicKey, remoteCommit.remotePerCommitmentPoint) val remoteHtlcPubkey = Generators.derivePubKey(remoteParams.htlcBasepoint, remoteCommit.remotePerCommitmentPoint) val localPerCommitmentPoint = keyManager.commitmentPoint(channelKeyPath, commitments.localCommit.index.toInt) @@ -629,8 +627,7 @@ object Helpers { * @return a list of transactions (one per HTLC that we can claim) */ def claimRemoteCommitMainOutput(keyManager: KeyManager, commitments: Commitments, remotePerCommitmentPoint: PublicKey, tx: Transaction, feeEstimator: FeeEstimator, feeTargets: FeeTargets)(implicit log: LoggingAdapter): RemoteCommitPublished = { - //val fundingPubKey = commitments.localParams.fundingPubKey(keyManager) - val channelKeyPath = commitments.localParams.channelKeyPath(keyManager) + val channelKeyPath = keyManager.channelKeyPath(commitments.localParams, commitments.channelVersion) val localPubkey = Generators.derivePubKey(keyManager.paymentPoint(channelKeyPath).publicKey, remotePerCommitmentPoint) val feeratePerKwMain = feeEstimator.getFeeratePerKw(feeTargets.claimMainBlockTarget) @@ -664,7 +661,7 @@ object Helpers { import commitments._ require(tx.txIn.size == 1, "commitment tx should have 1 input") //val fundingPubKey = commitments.localParams.fundingPubKey(keyManager) - val channelKeyPath = commitments.localParams.channelKeyPath(keyManager) + val channelKeyPath = keyManager.channelKeyPath(localParams, channelVersion) val obscuredTxNumber = Transactions.decodeTxNumber(tx.txIn(0).sequence, tx.lockTime) // this tx has been published by remote, so we need to invert local/remote params val txnumber = Transactions.obscuredCommitTxNumber(obscuredTxNumber, !localParams.isFunder, remoteParams.paymentBasepoint, keyManager.paymentPoint(channelKeyPath).publicKey) @@ -756,7 +753,7 @@ object Helpers { import commitments._ val tx = revokedCommitPublished.commitTx val obscuredTxNumber = Transactions.decodeTxNumber(tx.txIn(0).sequence, tx.lockTime) - val channelKeyPath = commitments.localParams.channelKeyPath(keyManager) + val channelKeyPath = keyManager.channelKeyPath(localParams, channelVersion) // this tx has been published by remote, so we need to invert local/remote params val txnumber = Transactions.obscuredCommitTxNumber(obscuredTxNumber, !localParams.isFunder, remoteParams.paymentBasepoint, keyManager.paymentPoint(channelKeyPath).publicKey) // now we know what commit number this tx is referring to, we can derive the commitment point from the shachain diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/crypto/KeyManager.scala b/eclair-core/src/main/scala/fr/acinq/eclair/crypto/KeyManager.scala index 086a9a831b..1fb5d5aa82 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/crypto/KeyManager.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/crypto/KeyManager.scala @@ -23,6 +23,7 @@ import fr.acinq.bitcoin.Crypto.{PrivateKey, PublicKey} import fr.acinq.bitcoin.DeterministicWallet.ExtendedPublicKey import fr.acinq.bitcoin.{ByteVector32, ByteVector64, Crypto, DeterministicWallet, Protocol} import fr.acinq.eclair.ShortChannelId +import fr.acinq.eclair.channel.{ChannelVersion, LocalParams} import fr.acinq.eclair.transactions.Transactions.TransactionWithInputInfo import scodec.bits.ByteVector @@ -45,6 +46,14 @@ trait KeyManager { def commitmentPoint(channelKeyPath: DeterministicWallet.KeyPath, index: Long): Crypto.PublicKey + def channelKeyPath(localParams: LocalParams, channelVersion: ChannelVersion): DeterministicWallet.KeyPath = if (channelVersion.isSet(ChannelVersion.USE_PUBKEY_KEYPATH_BIT)) { + // deterministic mode: use the funding pubkey to compute the channel key path + KeyManager.channelKeyPath(fundingPublicKey(localParams.fundingKeyPath)) + } else { + // legacy mode: we reuse the funding key path as our channel key path + localParams.fundingKeyPath + } + /** * * @param tx input transaction 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 f8ba34fb41..7a06acc4a3 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 @@ -297,7 +297,7 @@ class Peer(val nodeParams: NodeParams, remoteNodeId: PublicKey, authenticator: A val channelFeeratePerKw = nodeParams.onChainFeeConf.feeEstimator.getFeeratePerKw(target = nodeParams.onChainFeeConf.feeTargets.commitmentBlockTarget) val fundingTxFeeratePerKw = c.fundingTxFeeratePerKw_opt.getOrElse(nodeParams.onChainFeeConf.feeEstimator.getFeeratePerKw(target = nodeParams.onChainFeeConf.feeTargets.fundingBlockTarget)) log.info(s"requesting a new channel with fundingSatoshis=${c.fundingSatoshis}, pushMsat=${c.pushMsat} and fundingFeeratePerByte=${c.fundingTxFeeratePerKw_opt} temporaryChannelId=$temporaryChannelId localParams=$localParams") - channel ! INPUT_INIT_FUNDER(temporaryChannelId, c.fundingSatoshis, c.pushMsat, channelFeeratePerKw, fundingTxFeeratePerKw, localParams, d.transport, d.remoteInit, c.channelFlags.getOrElse(nodeParams.channelFlags), ChannelVersion.STANDARD) + channel ! INPUT_INIT_FUNDER(temporaryChannelId, c.fundingSatoshis, c.pushMsat, channelFeeratePerKw, fundingTxFeeratePerKw, localParams, d.transport, d.remoteInit, c.channelFlags.getOrElse(nodeParams.channelFlags), ChannelVersion.STANDARD | ChannelVersion.USE_PUBKEY_KEYPATH) stay using d.copy(channels = d.channels + (TemporaryChannelId(temporaryChannelId) -> channel)) case Event(msg: wire.OpenChannel, d: ConnectedData) => @@ -670,7 +670,6 @@ object Peer { def makeChannelParams(nodeParams: NodeParams, defaultFinalScriptPubKey: ByteVector, isFunder: Boolean, fundingAmount: Satoshi, fundingKeyPath: DeterministicWallet.KeyPath): LocalParams = { LocalParams( - version = 1, nodeParams.nodeId, fundingKeyPath, dustLimit = nodeParams.dustLimit, diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/wire/ChannelCodecs.scala b/eclair-core/src/main/scala/fr/acinq/eclair/wire/ChannelCodecs.scala index 08547078f2..536023b513 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/wire/ChannelCodecs.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/wire/ChannelCodecs.scala @@ -58,18 +58,8 @@ object ChannelCodecs extends Logging { fallback = provide(ChannelVersion.STANDARD) ) - // we use the same trick here: un-versioned LocalParams instances start with a node id so the first byte cannot be 0x01 - val localParamsVersionCodec: Codec[Int] = discriminatorWithDefault[Int]( - discriminator = discriminated[Int].by(byte) - .typecase(0x01, int16) - // NB: 0x02 and 0x03 are *reserved* for backward compatibility reasons - , - fallback = provide(0) - ) - val localParamsCodec: Codec[LocalParams] = ( - ("version" | localParamsVersionCodec) :: - ("nodeId" | publicKey) :: + ("nodeId" | publicKey) :: ("channelPath" | keyPathCodec) :: ("dustLimit" | satoshi) :: ("maxHtlcValueInFlightMsat" | uint64) :: diff --git a/eclair-core/src/test/scala/fr/acinq/eclair/channel/states/StateTestsHelperMethods.scala b/eclair-core/src/test/scala/fr/acinq/eclair/channel/states/StateTestsHelperMethods.scala index 9df32f77c7..94c50aa80c 100644 --- a/eclair-core/src/test/scala/fr/acinq/eclair/channel/states/StateTestsHelperMethods.scala +++ b/eclair-core/src/test/scala/fr/acinq/eclair/channel/states/StateTestsHelperMethods.scala @@ -70,7 +70,7 @@ trait StateTestsHelperMethods extends TestKitBase with fixture.TestSuite with Pa def reachNormal(setup: SetupFixture, tags: Set[String] = Set.empty): Unit = { import setup._ - val channelVersion = ChannelVersion.STANDARD + val channelVersion = ChannelVersion.STANDARD | ChannelVersion.USE_PUBKEY_KEYPATH val channelFlags = if (tags.contains("channels_public")) ChannelFlags.AnnounceChannel else ChannelFlags.Empty val pushMsat = if (tags.contains("no_push_msat")) 0.msat else TestConstants.pushMsat val (aliceParams, bobParams) = (Alice.channelParams, Bob.channelParams) diff --git a/eclair-core/src/test/scala/fr/acinq/eclair/channel/states/a/WaitForAcceptChannelStateSpec.scala b/eclair-core/src/test/scala/fr/acinq/eclair/channel/states/a/WaitForAcceptChannelStateSpec.scala index 1b102e748d..8758aa6b5e 100644 --- a/eclair-core/src/test/scala/fr/acinq/eclair/channel/states/a/WaitForAcceptChannelStateSpec.scala +++ b/eclair-core/src/test/scala/fr/acinq/eclair/channel/states/a/WaitForAcceptChannelStateSpec.scala @@ -49,7 +49,7 @@ class WaitForAcceptChannelStateSpec extends TestkitBaseClass with StateTestsHelp init(wallet = noopWallet) } import setup._ - val channelVersion = ChannelVersion.STANDARD + val channelVersion = ChannelVersion.STANDARD | ChannelVersion.USE_PUBKEY_KEYPATH val (aliceParams, bobParams) = (Alice.channelParams, Bob.channelParams) val aliceInit = Init(aliceParams.globalFeatures, aliceParams.localFeatures) val bobInit = Init(bobParams.globalFeatures, bobParams.localFeatures) diff --git a/eclair-core/src/test/scala/fr/acinq/eclair/channel/states/a/WaitForOpenChannelStateSpec.scala b/eclair-core/src/test/scala/fr/acinq/eclair/channel/states/a/WaitForOpenChannelStateSpec.scala index da61ba884c..a3568ce9c6 100644 --- a/eclair-core/src/test/scala/fr/acinq/eclair/channel/states/a/WaitForOpenChannelStateSpec.scala +++ b/eclair-core/src/test/scala/fr/acinq/eclair/channel/states/a/WaitForOpenChannelStateSpec.scala @@ -22,7 +22,7 @@ import fr.acinq.eclair.TestConstants.{Alice, Bob} import fr.acinq.eclair.channel._ import fr.acinq.eclair.channel.states.StateTestsHelperMethods import fr.acinq.eclair.wire.{Error, Init, OpenChannel} -import fr.acinq.eclair.{CltvExpiryDelta, LongToBtcAmount, MilliSatoshi, TestConstants, TestkitBaseClass, ToMilliSatoshiConversion} +import fr.acinq.eclair.{CltvExpiryDelta, LongToBtcAmount, TestConstants, TestkitBaseClass, ToMilliSatoshiConversion} import org.scalatest.Outcome import scala.concurrent.duration._ @@ -38,7 +38,7 @@ class WaitForOpenChannelStateSpec extends TestkitBaseClass with StateTestsHelper override def withFixture(test: OneArgTest): Outcome = { val setup = init() import setup._ - val channelVersion = ChannelVersion.STANDARD + val channelVersion = ChannelVersion.STANDARD | ChannelVersion.USE_PUBKEY_KEYPATH val (aliceParams, bobParams) = (Alice.channelParams, Bob.channelParams) val aliceInit = Init(aliceParams.globalFeatures, aliceParams.localFeatures) val bobInit = Init(bobParams.globalFeatures, bobParams.localFeatures) diff --git a/eclair-core/src/test/scala/fr/acinq/eclair/channel/states/b/WaitForFundingCreatedInternalStateSpec.scala b/eclair-core/src/test/scala/fr/acinq/eclair/channel/states/b/WaitForFundingCreatedInternalStateSpec.scala index 0c5facf221..64a94aba5c 100644 --- a/eclair-core/src/test/scala/fr/acinq/eclair/channel/states/b/WaitForFundingCreatedInternalStateSpec.scala +++ b/eclair-core/src/test/scala/fr/acinq/eclair/channel/states/b/WaitForFundingCreatedInternalStateSpec.scala @@ -27,8 +27,8 @@ import fr.acinq.eclair.{TestConstants, TestkitBaseClass} import org.scalatest.Outcome import scodec.bits.ByteVector -import scala.concurrent.{Future, Promise} import scala.concurrent.duration._ +import scala.concurrent.{Future, Promise} /** * Created by PM on 05/07/2016. @@ -47,7 +47,7 @@ class WaitForFundingCreatedInternalStateSpec extends TestkitBaseClass with State val aliceInit = Init(Alice.channelParams.globalFeatures, Alice.channelParams.localFeatures) val bobInit = Init(Bob.channelParams.globalFeatures, Bob.channelParams.localFeatures) within(30 seconds) { - alice ! INPUT_INIT_FUNDER(ByteVector32.Zeroes, TestConstants.fundingSatoshis, TestConstants.pushMsat, TestConstants.feeratePerKw, TestConstants.feeratePerKw, Alice.channelParams, alice2bob.ref, bobInit, ChannelFlags.Empty, ChannelVersion.STANDARD) + alice ! INPUT_INIT_FUNDER(ByteVector32.Zeroes, TestConstants.fundingSatoshis, TestConstants.pushMsat, TestConstants.feeratePerKw, TestConstants.feeratePerKw, Alice.channelParams, alice2bob.ref, bobInit, ChannelFlags.Empty, ChannelVersion.STANDARD | ChannelVersion.USE_PUBKEY_KEYPATH) bob ! INPUT_INIT_FUNDEE(ByteVector32.Zeroes, Bob.channelParams, bob2alice.ref, aliceInit) alice2bob.expectMsgType[OpenChannel] alice2bob.forward(bob) diff --git a/eclair-core/src/test/scala/fr/acinq/eclair/channel/states/b/WaitForFundingCreatedStateSpec.scala b/eclair-core/src/test/scala/fr/acinq/eclair/channel/states/b/WaitForFundingCreatedStateSpec.scala index 93be60649f..8f721262fd 100644 --- a/eclair-core/src/test/scala/fr/acinq/eclair/channel/states/b/WaitForFundingCreatedStateSpec.scala +++ b/eclair-core/src/test/scala/fr/acinq/eclair/channel/states/b/WaitForFundingCreatedStateSpec.scala @@ -48,7 +48,7 @@ class WaitForFundingCreatedStateSpec extends TestkitBaseClass with StateTestsHel val aliceInit = Init(Alice.channelParams.globalFeatures, Alice.channelParams.localFeatures) val bobInit = Init(Bob.channelParams.globalFeatures, Bob.channelParams.localFeatures) within(30 seconds) { - alice ! INPUT_INIT_FUNDER(ByteVector32.Zeroes, fundingSatoshis, pushMsat, TestConstants.feeratePerKw, TestConstants.feeratePerKw, Alice.channelParams, alice2bob.ref, bobInit, ChannelFlags.Empty, ChannelVersion.STANDARD) + alice ! INPUT_INIT_FUNDER(ByteVector32.Zeroes, fundingSatoshis, pushMsat, TestConstants.feeratePerKw, TestConstants.feeratePerKw, Alice.channelParams, alice2bob.ref, bobInit, ChannelFlags.Empty, ChannelVersion.STANDARD | ChannelVersion.USE_PUBKEY_KEYPATH) bob ! INPUT_INIT_FUNDEE(ByteVector32.Zeroes, Bob.channelParams, bob2alice.ref, aliceInit) alice2bob.expectMsgType[OpenChannel] alice2bob.forward(bob) diff --git a/eclair-core/src/test/scala/fr/acinq/eclair/channel/states/b/WaitForFundingSignedStateSpec.scala b/eclair-core/src/test/scala/fr/acinq/eclair/channel/states/b/WaitForFundingSignedStateSpec.scala index 4afe51eee6..6b0fefa539 100644 --- a/eclair-core/src/test/scala/fr/acinq/eclair/channel/states/b/WaitForFundingSignedStateSpec.scala +++ b/eclair-core/src/test/scala/fr/acinq/eclair/channel/states/b/WaitForFundingSignedStateSpec.scala @@ -26,7 +26,6 @@ import fr.acinq.eclair.channel.states.StateTestsHelperMethods import fr.acinq.eclair.wire.{AcceptChannel, Error, FundingCreated, FundingSigned, Init, OpenChannel} import fr.acinq.eclair.{TestConstants, TestkitBaseClass} import org.scalatest.Outcome -import scodec.bits.ByteVector import scala.concurrent.duration._ @@ -44,7 +43,7 @@ class WaitForFundingSignedStateSpec extends TestkitBaseClass with StateTestsHelp val aliceInit = Init(Alice.channelParams.globalFeatures, Alice.channelParams.localFeatures) val bobInit = Init(Bob.channelParams.globalFeatures, Bob.channelParams.localFeatures) within(30 seconds) { - alice ! INPUT_INIT_FUNDER(ByteVector32.Zeroes, TestConstants.fundingSatoshis, TestConstants.pushMsat, TestConstants.feeratePerKw, TestConstants.feeratePerKw, Alice.channelParams, alice2bob.ref, bobInit, ChannelFlags.Empty, ChannelVersion.STANDARD) + alice ! INPUT_INIT_FUNDER(ByteVector32.Zeroes, TestConstants.fundingSatoshis, TestConstants.pushMsat, TestConstants.feeratePerKw, TestConstants.feeratePerKw, Alice.channelParams, alice2bob.ref, bobInit, ChannelFlags.Empty, ChannelVersion.STANDARD | ChannelVersion.USE_PUBKEY_KEYPATH) bob ! INPUT_INIT_FUNDEE(ByteVector32.Zeroes, Bob.channelParams, bob2alice.ref, aliceInit) alice2bob.expectMsgType[OpenChannel] alice2bob.forward(bob) diff --git a/eclair-core/src/test/scala/fr/acinq/eclair/channel/states/c/WaitForFundingConfirmedStateSpec.scala b/eclair-core/src/test/scala/fr/acinq/eclair/channel/states/c/WaitForFundingConfirmedStateSpec.scala index 5c54affbf6..8379e7923d 100644 --- a/eclair-core/src/test/scala/fr/acinq/eclair/channel/states/c/WaitForFundingConfirmedStateSpec.scala +++ b/eclair-core/src/test/scala/fr/acinq/eclair/channel/states/c/WaitForFundingConfirmedStateSpec.scala @@ -44,7 +44,7 @@ class WaitForFundingConfirmedStateSpec extends TestkitBaseClass with StateTestsH val aliceInit = Init(Alice.channelParams.globalFeatures, Alice.channelParams.localFeatures) val bobInit = Init(Bob.channelParams.globalFeatures, Bob.channelParams.localFeatures) within(30 seconds) { - alice ! INPUT_INIT_FUNDER(ByteVector32.Zeroes, TestConstants.fundingSatoshis, TestConstants.pushMsat, TestConstants.feeratePerKw, TestConstants.feeratePerKw, Alice.channelParams, alice2bob.ref, bobInit, ChannelFlags.Empty, ChannelVersion.STANDARD) + alice ! INPUT_INIT_FUNDER(ByteVector32.Zeroes, TestConstants.fundingSatoshis, TestConstants.pushMsat, TestConstants.feeratePerKw, TestConstants.feeratePerKw, Alice.channelParams, alice2bob.ref, bobInit, ChannelFlags.Empty, ChannelVersion.STANDARD | ChannelVersion.USE_PUBKEY_KEYPATH) bob ! INPUT_INIT_FUNDEE(ByteVector32.Zeroes, Bob.channelParams, bob2alice.ref, aliceInit) alice2bob.expectMsgType[OpenChannel] alice2bob.forward(bob) diff --git a/eclair-core/src/test/scala/fr/acinq/eclair/channel/states/c/WaitForFundingLockedStateSpec.scala b/eclair-core/src/test/scala/fr/acinq/eclair/channel/states/c/WaitForFundingLockedStateSpec.scala index 9068f0dec1..53b6918e61 100644 --- a/eclair-core/src/test/scala/fr/acinq/eclair/channel/states/c/WaitForFundingLockedStateSpec.scala +++ b/eclair-core/src/test/scala/fr/acinq/eclair/channel/states/c/WaitForFundingLockedStateSpec.scala @@ -43,7 +43,7 @@ class WaitForFundingLockedStateSpec extends TestkitBaseClass with StateTestsHelp val aliceInit = Init(Alice.channelParams.globalFeatures, Alice.channelParams.localFeatures) val bobInit = Init(Bob.channelParams.globalFeatures, Bob.channelParams.localFeatures) within(30 seconds) { - alice ! INPUT_INIT_FUNDER(ByteVector32.Zeroes, TestConstants.fundingSatoshis, TestConstants.pushMsat, TestConstants.feeratePerKw, TestConstants.feeratePerKw, Alice.channelParams, alice2bob.ref, bobInit, ChannelFlags.Empty, ChannelVersion.STANDARD) + alice ! INPUT_INIT_FUNDER(ByteVector32.Zeroes, TestConstants.fundingSatoshis, TestConstants.pushMsat, TestConstants.feeratePerKw, TestConstants.feeratePerKw, Alice.channelParams, alice2bob.ref, bobInit, ChannelFlags.Empty, ChannelVersion.STANDARD | ChannelVersion.USE_PUBKEY_KEYPATH) bob ! INPUT_INIT_FUNDEE(ByteVector32.Zeroes, Bob.channelParams, bob2alice.ref, aliceInit) alice2bob.expectMsgType[OpenChannel] alice2bob.forward(bob) 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 bb87841b7a..810c972973 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 @@ -88,10 +88,10 @@ class OfflineStateSpec extends TestkitBaseClass with StateTestsHelperMethods { val aliceCommitments = alice.stateData.asInstanceOf[HasCommitments].commitments val bobCurrentPerCommitmentPoint = TestConstants.Bob.keyManager.commitmentPoint( - bobCommitments.localParams.channelKeyPath(TestConstants.Bob.keyManager), + TestConstants.Bob.keyManager.channelKeyPath(bobCommitments.localParams, bobCommitments.channelVersion), bobCommitments.localCommit.index) val aliceCurrentPerCommitmentPoint = TestConstants.Alice.keyManager.commitmentPoint( - aliceCommitments.localParams.channelKeyPath(TestConstants.Alice.keyManager), + TestConstants.Alice.keyManager.channelKeyPath(aliceCommitments.localParams, aliceCommitments.channelVersion), aliceCommitments.localCommit.index) @@ -176,10 +176,10 @@ class OfflineStateSpec extends TestkitBaseClass with StateTestsHelperMethods { val aliceCommitments = alice.stateData.asInstanceOf[HasCommitments].commitments val bobCurrentPerCommitmentPoint = TestConstants.Bob.keyManager.commitmentPoint( - bobCommitments.localParams.channelKeyPath(TestConstants.Bob.keyManager), + TestConstants.Bob.keyManager.channelKeyPath(bobCommitments.localParams, bobCommitments.channelVersion), bobCommitments.localCommit.index) val aliceCurrentPerCommitmentPoint = TestConstants.Alice.keyManager.commitmentPoint( - aliceCommitments.localParams.channelKeyPath(TestConstants.Alice.keyManager), + TestConstants.Alice.keyManager.channelKeyPath(aliceCommitments.localParams, aliceCommitments.channelVersion), aliceCommitments.localCommit.index) // a didn't receive the sig 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 c9b3628452..cd595638e4 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 @@ -65,7 +65,7 @@ class ClosingStateSpec extends TestkitBaseClass with StateTestsHelperMethods { within(30 seconds) { val aliceInit = Init(Alice.channelParams.globalFeatures, Alice.channelParams.localFeatures) val bobInit = Init(Bob.channelParams.globalFeatures, Bob.channelParams.localFeatures) - alice ! INPUT_INIT_FUNDER(ByteVector32.Zeroes, TestConstants.fundingSatoshis, TestConstants.pushMsat, TestConstants.feeratePerKw, TestConstants.feeratePerKw, Alice.channelParams, alice2bob.ref, bobInit, ChannelFlags.Empty, ChannelVersion.STANDARD) + alice ! INPUT_INIT_FUNDER(ByteVector32.Zeroes, TestConstants.fundingSatoshis, TestConstants.pushMsat, TestConstants.feeratePerKw, TestConstants.feeratePerKw, Alice.channelParams, alice2bob.ref, bobInit, ChannelFlags.Empty, ChannelVersion.STANDARD | ChannelVersion.USE_PUBKEY_KEYPATH) bob ! INPUT_INIT_FUNDEE(ByteVector32.Zeroes, Bob.channelParams, bob2alice.ref, aliceInit) alice2bob.expectMsgType[OpenChannel] alice2bob.forward(bob) diff --git a/eclair-core/src/test/scala/fr/acinq/eclair/transactions/LocalParamsSpec.scala b/eclair-core/src/test/scala/fr/acinq/eclair/transactions/LocalParamsSpec.scala deleted file mode 100644 index 10b87bc6d5..0000000000 --- a/eclair-core/src/test/scala/fr/acinq/eclair/transactions/LocalParamsSpec.scala +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright 2019 ACINQ SAS - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package fr.acinq.eclair.transactions - -import fr.acinq.bitcoin.{Block, ByteVector32, DeterministicWallet} -import fr.acinq.eclair.crypto.LocalKeyManager -import fr.acinq.eclair.wire.ChannelCodecs -import org.scalatest.FunSuite -import scodec.bits.{BitVector, ByteVector} - -class LocalParamsSpec extends FunSuite { - test("read legacy data correctly") { - val seed = ByteVector32(ByteVector.fill(32)(2)) - val keyManager = new LocalKeyManager(seed, Block.RegtestGenesisBlock.hash) - // read version 0 local params from data produced with an older version of eclair - val localParams = ChannelCodecs.localParamsCodec.decode(BitVector.fromValidHex("0x03af0ed6052cf28d670665549bc86f4b721c9fdb309d40c58f5811f63966e005d00004e3fbd1afb75d37604f7de0755c7e3e01000000000000044c0000000008f0d18000000000000027100000000000000000009000648000000000008000")).require.value - val channelKeyPath = localParams.channelKeyPath(keyManager) - val fundingPubKey = keyManager.fundingPublicKey(localParams.fundingKeyPath) - assert(channelKeyPath == DeterministicWallet.KeyPath("m/1677447599'/928855904'/1333649525/1551777281")) - assert(fundingPubKey.toString == "ExtendedPublicKey(ByteVector(33 bytes, 0x02f8eea36e21551d30ce9329538c8652b5ecc1f8dc5b84ab52a4eb5e95759cdbc8),a1e0ccf8ac45652752ebfd578c3b7a6adcbdb693fbc0ff3f1d1797db4af9f8bd,7,m/46'/1'/1677447599'/928855904'/1333649525/1551777281/0',1132704962)") - } -} diff --git a/eclair-core/src/test/scala/fr/acinq/eclair/wire/ChannelCodecsSpec.scala b/eclair-core/src/test/scala/fr/acinq/eclair/wire/ChannelCodecsSpec.scala index 0d234fd2f4..bc5787342d 100644 --- a/eclair-core/src/test/scala/fr/acinq/eclair/wire/ChannelCodecsSpec.scala +++ b/eclair-core/src/test/scala/fr/acinq/eclair/wire/ChannelCodecsSpec.scala @@ -84,7 +84,6 @@ class ChannelCodecsSpec extends FunSuite { test("encode/decode localparams") { val o = LocalParams( - version = 1, nodeId = randomKey.publicKey, fundingKeyPath = DeterministicWallet.KeyPath(Seq(42L)), dustLimit = Satoshi(Random.nextInt(Int.MaxValue)), @@ -347,7 +346,6 @@ class ChannelCodecsSpec extends FunSuite { object ChannelCodecsSpec { val keyManager = new LocalKeyManager(ByteVector32(ByteVector.fill(32)(1)), Block.RegtestGenesisBlock.hash) val localParams = LocalParams( - version = 1, keyManager.nodeId, fundingKeyPath = DeterministicWallet.KeyPath(Seq(42L)), dustLimit = Satoshi(546),