mirror of
https://github.com/ACINQ/eclair.git
synced 2024-11-19 09:54:02 +01:00
Minor fixes (#163)
* improved router/payment-lifecycle logging * now periodically publish CurrentFeerate events * added a reference to `channelId` in `ChannelException`
This commit is contained in:
parent
a18fac135d
commit
9e3fbbe5da
@ -99,6 +99,7 @@ class Setup(datadir: File, overrideDefaults: Config = ConfigFactory.empty(), act
|
||||
system.scheduler.schedule(0 seconds, 10 minutes)(feeProvider.getFeeratePerKB.map {
|
||||
case feeratePerKB =>
|
||||
Globals.feeratePerKw.set(feerateKb2Kw(feeratePerKB))
|
||||
system.eventStream.publish(CurrentFeerate(Globals.feeratePerKw.get()))
|
||||
logger.info(s"current feeratePerKw=${Globals.feeratePerKw.get()}")
|
||||
})
|
||||
|
||||
|
@ -408,7 +408,7 @@ class Channel(val nodeParams: NodeParams, wallet: EclairWallet, remoteNodeId: Pu
|
||||
|
||||
when(NORMAL)(handleExceptions {
|
||||
case Event(c: CMD_ADD_HTLC, d: DATA_NORMAL) if d.localShutdown.isDefined =>
|
||||
handleCommandError(ClosingInProgress)
|
||||
handleCommandError(ClosingInProgress(d.channelId))
|
||||
|
||||
case Event(c@CMD_ADD_HTLC(_, _, _, _, downstream_opt, do_commit), d: DATA_NORMAL) =>
|
||||
Try(Commitments.sendAdd(d.commitments, c)) match {
|
||||
@ -551,22 +551,22 @@ class Channel(val nodeParams: NodeParams, wallet: EclairWallet, remoteNodeId: Pu
|
||||
case Event(CMD_CLOSE(localScriptPubKey_opt), d: DATA_NORMAL) =>
|
||||
val localScriptPubKey = localScriptPubKey_opt.getOrElse(d.commitments.localParams.defaultFinalScriptPubKey)
|
||||
if (d.localShutdown.isDefined)
|
||||
handleCommandError(ClosingAlreadyInProgress)
|
||||
handleCommandError(ClosingAlreadyInProgress((d.channelId)))
|
||||
else if (Commitments.localHasChanges(d.commitments))
|
||||
// TODO: simplistic behavior, we could also sign-then-close
|
||||
handleCommandError(CannotCloseWithPendingChanges)
|
||||
handleCommandError(CannotCloseWithPendingChanges((d.channelId)))
|
||||
else if (!Closing.isValidFinalScriptPubkey(localScriptPubKey))
|
||||
handleCommandError(InvalidFinalScript)
|
||||
handleCommandError(InvalidFinalScript(d.channelId))
|
||||
else {
|
||||
val shutdown = Shutdown(d.channelId, localScriptPubKey)
|
||||
handleCommandSuccess(sender, store(d.copy(localShutdown = Some(shutdown)))) sending shutdown
|
||||
}
|
||||
|
||||
case Event(Shutdown(_, _), d: DATA_NORMAL) if d.commitments.remoteChanges.proposed.size > 0 =>
|
||||
handleLocalError(CannotCloseWithPendingChanges, d)
|
||||
handleLocalError(CannotCloseWithPendingChanges(d.channelId), d)
|
||||
|
||||
case Event(remoteShutdown@Shutdown(_, remoteScriptPubKey), d: DATA_NORMAL) =>
|
||||
if (!Closing.isValidFinalScriptPubkey(remoteScriptPubKey)) throw InvalidFinalScript
|
||||
if (!Closing.isValidFinalScriptPubkey(remoteScriptPubKey)) throw InvalidFinalScript(d.channelId)
|
||||
Try(d.localShutdown.map(s => (s, d.commitments)).getOrElse {
|
||||
// first if we have pending changes, we need to commit them
|
||||
val commitments2 = if (Commitments.localHasChanges(d.commitments)) {
|
||||
@ -596,7 +596,7 @@ class Channel(val nodeParams: NodeParams, wallet: EclairWallet, remoteNodeId: Pu
|
||||
}
|
||||
|
||||
case Event(CurrentBlockCount(count), d: DATA_NORMAL) if d.commitments.hasTimedoutOutgoingHtlcs(count) =>
|
||||
handleLocalError(HtlcTimedout, d)
|
||||
handleLocalError(HtlcTimedout(d.channelId), d)
|
||||
|
||||
case Event(CurrentFeerate(feeratePerKw), d: DATA_NORMAL) =>
|
||||
d.commitments.localParams.isFunder match {
|
||||
@ -604,7 +604,7 @@ class Channel(val nodeParams: NodeParams, wallet: EclairWallet, remoteNodeId: Pu
|
||||
self ! CMD_UPDATE_FEE(feeratePerKw, commit = true)
|
||||
stay
|
||||
case false if Helpers.isFeeDiffTooHigh(d.commitments.localCommit.spec.feeratePerKw, feeratePerKw, nodeParams.maxFeerateMismatch) =>
|
||||
handleLocalError(FeerateTooDifferent(localFeeratePerKw = feeratePerKw, remoteFeeratePerKw = d.commitments.localCommit.spec.feeratePerKw), d)
|
||||
handleLocalError(FeerateTooDifferent(d.channelId, localFeeratePerKw = feeratePerKw, remoteFeeratePerKw = d.commitments.localCommit.spec.feeratePerKw), d)
|
||||
case _ => stay
|
||||
}
|
||||
|
||||
@ -811,7 +811,7 @@ class Channel(val nodeParams: NodeParams, wallet: EclairWallet, remoteNodeId: Pu
|
||||
}
|
||||
|
||||
case Event(CurrentBlockCount(count), d: DATA_SHUTDOWN) if d.commitments.hasTimedoutOutgoingHtlcs(count) =>
|
||||
handleLocalError(HtlcTimedout, d)
|
||||
handleLocalError(HtlcTimedout(d.channelId), d)
|
||||
|
||||
case Event(CurrentFeerate(feeratePerKw), d: DATA_SHUTDOWN) =>
|
||||
d.commitments.localParams.isFunder match {
|
||||
@ -819,7 +819,7 @@ class Channel(val nodeParams: NodeParams, wallet: EclairWallet, remoteNodeId: Pu
|
||||
self ! CMD_UPDATE_FEE(feeratePerKw, commit = true)
|
||||
stay
|
||||
case false if Helpers.isFeeDiffTooHigh(d.commitments.localCommit.spec.feeratePerKw, feeratePerKw, nodeParams.maxFeerateMismatch) =>
|
||||
handleLocalError(FeerateTooDifferent(localFeeratePerKw = feeratePerKw, remoteFeeratePerKw = d.commitments.localCommit.spec.feeratePerKw), d)
|
||||
handleLocalError(FeerateTooDifferent(d.channelId, localFeeratePerKw = feeratePerKw, remoteFeeratePerKw = d.commitments.localCommit.spec.feeratePerKw), d)
|
||||
case _ => stay
|
||||
}
|
||||
|
||||
@ -829,7 +829,7 @@ class Channel(val nodeParams: NodeParams, wallet: EclairWallet, remoteNodeId: Pu
|
||||
|
||||
case Event(WatchEventSpent(BITCOIN_FUNDING_SPENT, tx: Transaction), d: DATA_SHUTDOWN) => handleRemoteSpentOther(tx, d)
|
||||
|
||||
case Event(CMD_CLOSE(_), d: DATA_SHUTDOWN) => handleCommandError(ClosingAlreadyInProgress)
|
||||
case Event(CMD_CLOSE(_), d: DATA_SHUTDOWN) => handleCommandError(ClosingAlreadyInProgress(d.channelId))
|
||||
|
||||
case Event(e: Error, d: DATA_SHUTDOWN) => handleRemoteError(e, d)
|
||||
|
||||
@ -850,7 +850,7 @@ class Channel(val nodeParams: NodeParams, wallet: EclairWallet, remoteNodeId: Pu
|
||||
}
|
||||
case Failure(cause) =>
|
||||
log.error(cause, "cannot verify their close signature")
|
||||
throw InvalidCloseSignature
|
||||
throw InvalidCloseSignature(d.channelId)
|
||||
}
|
||||
|
||||
case Event(WatchEventSpent(BITCOIN_FUNDING_SPENT, tx: Transaction), d: DATA_NEGOTIATING) if tx.txid == Closing.makeClosingTx(d.commitments, d.localShutdown.scriptPubKey, d.remoteShutdown.scriptPubKey, Satoshi(d.localClosingSigned.feeSatoshis))._1.tx.txid =>
|
||||
@ -863,7 +863,7 @@ class Channel(val nodeParams: NodeParams, wallet: EclairWallet, remoteNodeId: Pu
|
||||
|
||||
case Event(WatchEventSpent(BITCOIN_FUNDING_SPENT, tx: Transaction), d: DATA_NEGOTIATING) => handleRemoteSpentOther(tx, d)
|
||||
|
||||
case Event(CMD_CLOSE(_), d: DATA_NEGOTIATING) => handleCommandError(ClosingAlreadyInProgress)
|
||||
case Event(CMD_CLOSE(_), d: DATA_NEGOTIATING) => handleCommandError(ClosingAlreadyInProgress(d.channelId))
|
||||
|
||||
case Event(e: Error, d: DATA_NEGOTIATING) => handleRemoteError(e, d)
|
||||
|
||||
@ -934,7 +934,7 @@ class Channel(val nodeParams: NodeParams, wallet: EclairWallet, remoteNodeId: Pu
|
||||
|
||||
case Event(WatchEventConfirmed(BITCOIN_PENALTY_DONE, _, _), d: DATA_CLOSING) if d.revokedCommitPublished.size > 0 => goto(CLOSED)
|
||||
|
||||
case Event(CMD_CLOSE(_), d: DATA_CLOSING) => handleCommandError(ClosingAlreadyInProgress)
|
||||
case Event(CMD_CLOSE(_), d: DATA_CLOSING) => handleCommandError(ClosingAlreadyInProgress(d.channelId))
|
||||
|
||||
case Event(e: Error, d: DATA_CLOSING) => stay // nothing to do, there is already a spending tx published
|
||||
|
||||
@ -967,13 +967,13 @@ class Channel(val nodeParams: NodeParams, wallet: EclairWallet, remoteNodeId: Pu
|
||||
|
||||
case Event(c: CMD_ADD_HTLC, d: DATA_NORMAL) =>
|
||||
log.info(s"rejecting htlc (disconnected)")
|
||||
relayer ! AddHtlcFailed(c, ChannelUnavailable)
|
||||
handleCommandError(ChannelUnavailable)
|
||||
relayer ! AddHtlcFailed(c, ChannelUnavailable(d.channelId))
|
||||
handleCommandError(ChannelUnavailable(d.channelId))
|
||||
|
||||
case Event(CMD_CLOSE(_), d: HasCommitments) => handleLocalError(ForcedLocalCommit("can't do a mutual close while disconnected"), d) replying "ok"
|
||||
case Event(CMD_CLOSE(_), d: HasCommitments) => handleLocalError(ForcedLocalCommit(d.channelId, "can't do a mutual close while disconnected"), d) replying "ok"
|
||||
|
||||
case Event(CurrentBlockCount(count), d: HasCommitments) if d.commitments.hasTimedoutOutgoingHtlcs(count) =>
|
||||
handleLocalError(HtlcTimedout, d)
|
||||
handleLocalError(HtlcTimedout(d.channelId), d)
|
||||
|
||||
case Event(WatchEventSpent(BITCOIN_FUNDING_SPENT, tx: Transaction), d: HasCommitments) if tx.txid == d.commitments.remoteCommit.txid => handleRemoteSpentCurrent(tx, d)
|
||||
|
||||
@ -1040,13 +1040,13 @@ class Channel(val nodeParams: NodeParams, wallet: EclairWallet, remoteNodeId: Pu
|
||||
|
||||
case Event(c: CMD_ADD_HTLC, d: DATA_NORMAL) =>
|
||||
log.info(s"rejecting htlc (syncing)")
|
||||
relayer ! AddHtlcFailed(c, ChannelUnavailable)
|
||||
handleCommandError(ChannelUnavailable)
|
||||
relayer ! AddHtlcFailed(c, ChannelUnavailable(d.channelId))
|
||||
handleCommandError(ChannelUnavailable(d.channelId))
|
||||
|
||||
case Event(CMD_CLOSE(_), d: HasCommitments) => handleLocalError(ForcedLocalCommit("can't do a mutual close while syncing"), d)
|
||||
case Event(CMD_CLOSE(_), d: HasCommitments) => handleLocalError(ForcedLocalCommit(d.channelId, "can't do a mutual close while syncing"), d)
|
||||
|
||||
case Event(CurrentBlockCount(count), d: HasCommitments) if d.commitments.hasTimedoutOutgoingHtlcs(count) =>
|
||||
handleLocalError(HtlcTimedout, d)
|
||||
handleLocalError(HtlcTimedout(d.channelId), d)
|
||||
|
||||
case Event(WatchEventSpent(BITCOIN_FUNDING_SPENT, tx: Transaction), d: HasCommitments) if tx.txid == d.commitments.remoteCommit.txid => handleRemoteSpentCurrent(tx, d)
|
||||
|
||||
@ -1061,7 +1061,7 @@ class Channel(val nodeParams: NodeParams, wallet: EclairWallet, remoteNodeId: Pu
|
||||
|
||||
whenUnhandled {
|
||||
|
||||
case Event(INPUT_PUBLISH_LOCALCOMMIT, d: HasCommitments) => handleLocalError(ForcedLocalCommit("manual unilateral close"), d)
|
||||
case Event(INPUT_PUBLISH_LOCALCOMMIT, d: HasCommitments) => handleLocalError(ForcedLocalCommit(d.channelId, "manual unilateral close"), d)
|
||||
|
||||
case Event(INPUT_DISCONNECTED, _) => goto(OFFLINE)
|
||||
|
||||
@ -1363,7 +1363,7 @@ class Channel(val nodeParams: NodeParams, wallet: EclairWallet, remoteNodeId: Pu
|
||||
nextPerCommitmentPoint = localNextPerCommitmentPoint
|
||||
)
|
||||
forwarder ! revocation
|
||||
} else throw RevocationSyncError
|
||||
} else throw RevocationSyncError(d.channelId)
|
||||
}
|
||||
|
||||
// re-sending sig/rev (in the right order)
|
||||
@ -1391,7 +1391,7 @@ class Channel(val nodeParams: NodeParams, wallet: EclairWallet, remoteNodeId: Pu
|
||||
case Right(_) if commitments1.remoteCommit.index + 1 == channelReestablish.nextLocalCommitmentNumber =>
|
||||
// there wasn't any sig in-flight when the disconnection occured
|
||||
resendRevocation
|
||||
case _ => throw CommitmentSyncError
|
||||
case _ => throw CommitmentSyncError(d.channelId)
|
||||
}
|
||||
|
||||
// let's now fail all pending htlc for which we are the final payee
|
||||
|
@ -1,39 +1,40 @@
|
||||
package fr.acinq.eclair.channel
|
||||
|
||||
import fr.acinq.bitcoin.BinaryData
|
||||
import fr.acinq.eclair.UInt64
|
||||
|
||||
/**
|
||||
* Created by PM on 11/04/2017.
|
||||
*/
|
||||
|
||||
class ChannelException(message: String) extends RuntimeException(message)
|
||||
class ChannelException(channelId: BinaryData, message: String) extends RuntimeException(message)
|
||||
|
||||
case object DebugTriggeredException extends ChannelException("debug-mode triggered failure")
|
||||
case object ClosingInProgress extends ChannelException("cannot send new htlcs, closing in progress")
|
||||
case object ClosingAlreadyInProgress extends ChannelException("closing already in progress")
|
||||
case object CannotCloseWithPendingChanges extends ChannelException("cannot close when there are pending changes")
|
||||
case object ChannelUnavailable extends ChannelException("channel is unavailable (offline or closing)")
|
||||
case object InvalidFinalScript extends ChannelException("invalid final script")
|
||||
case object HtlcTimedout extends ChannelException(s"one or more htlcs timed out")
|
||||
case class FeerateTooDifferent(localFeeratePerKw: Long, remoteFeeratePerKw: Long) extends ChannelException(s"local/remote feerates are too different: remoteFeeratePerKw=$remoteFeeratePerKw localFeeratePerKw=$localFeeratePerKw")
|
||||
case object InvalidCloseSignature extends ChannelException("cannot verify their close signature")
|
||||
case object InvalidCommitmentSignature extends ChannelException("invalid commitment signature")
|
||||
case class ForcedLocalCommit(reason: String) extends ChannelException(s"forced local commit: reason")
|
||||
case class UnexpectedHtlcId(expected: Long, actual: Long) extends ChannelException(s"unexpected htlc id: expected=$expected actual=$actual")
|
||||
case object InvalidPaymentHash extends ChannelException("invalid payment hash")
|
||||
case class ExpiryTooSmall(minimum: Long, actual: Long, blockCount: Long) extends ChannelException(s"expiry too small: required=$minimum actual=$actual blockCount=$blockCount")
|
||||
case class ExpiryCannotBeInThePast(expiry: Long, blockCount: Long) extends ChannelException(s"expiry can't be in the past: expiry=$expiry blockCount=$blockCount")
|
||||
case class HtlcValueTooSmall(minimum: Long, actual: Long) extends ChannelException(s"htlc value too small: mininmum=$minimum actual=$actual")
|
||||
case class HtlcValueTooHighInFlight(maximum: UInt64, actual: UInt64) extends ChannelException(s"in-flight htlcs hold too much value: maximum=$maximum actual=$actual")
|
||||
case class TooManyAcceptedHtlcs(maximum: Long) extends ChannelException(s"too many accepted htlcs: maximum=$maximum")
|
||||
case class InsufficientFunds(amountMsat: Long, missingSatoshis: Long, reserveSatoshis: Long, feesSatoshis: Long) extends ChannelException(s"insufficient funds: missingSatoshis=$missingSatoshis reserveSatoshis=$reserveSatoshis fees=$feesSatoshis")
|
||||
case class InvalidHtlcPreimage(id: Long) extends ChannelException(s"invalid htlc preimage for htlc id=$id")
|
||||
case class UnknownHtlcId(id: Long) extends ChannelException(s"unknown htlc id=$id")
|
||||
case object FundeeCannotSendUpdateFee extends ChannelException(s"only the funder should send update_fee messages")
|
||||
case class CannotAffordFees(missingSatoshis: Long, reserveSatoshis: Long, feesSatoshis: Long) extends ChannelException(s"can't pay the fee: missingSatoshis=$missingSatoshis reserveSatoshis=$reserveSatoshis feesSatoshis=$feesSatoshis")
|
||||
case object CannotSignWithoutChanges extends ChannelException("cannot sign when there are no changes")
|
||||
case object CannotSignBeforeRevocation extends ChannelException("cannot sign until next revocation hash is received")
|
||||
case object UnexpectedRevocation extends ChannelException("received unexpected RevokeAndAck message")
|
||||
case object InvalidRevocation extends ChannelException("invalid revocation")
|
||||
case object CommitmentSyncError extends ChannelException("commitment sync error")
|
||||
case object RevocationSyncError extends ChannelException("revocation sync error")
|
||||
case class DebugTriggeredException (channelId: BinaryData) extends ChannelException(channelId, "debug-mode triggered failure")
|
||||
case class ClosingInProgress (channelId: BinaryData) extends ChannelException(channelId, "cannot send new htlcs, closing in progress")
|
||||
case class ClosingAlreadyInProgress (channelId: BinaryData) extends ChannelException(channelId, "closing already in progress")
|
||||
case class CannotCloseWithPendingChanges(channelId: BinaryData) extends ChannelException(channelId, "cannot close when there are pending changes")
|
||||
case class ChannelUnavailable (channelId: BinaryData) extends ChannelException(channelId, "channel is unavailable (offline or closing)")
|
||||
case class InvalidFinalScript (channelId: BinaryData) extends ChannelException(channelId, "invalid final script")
|
||||
case class HtlcTimedout (channelId: BinaryData) extends ChannelException(channelId, s"one or more htlcs timed out")
|
||||
case class FeerateTooDifferent (channelId: BinaryData, localFeeratePerKw: Long, remoteFeeratePerKw: Long) extends ChannelException(channelId, s"local/remote feerates are too different: remoteFeeratePerKw=$remoteFeeratePerKw localFeeratePerKw=$localFeeratePerKw")
|
||||
case class InvalidCloseSignature (channelId: BinaryData) extends ChannelException(channelId, "cannot verify their close signature")
|
||||
case class InvalidCommitmentSignature (channelId: BinaryData) extends ChannelException(channelId, "invalid commitment signature")
|
||||
case class ForcedLocalCommit (channelId: BinaryData, reason: String) extends ChannelException(channelId, s"forced local commit: reason")
|
||||
case class UnexpectedHtlcId (channelId: BinaryData, expected: Long, actual: Long) extends ChannelException(channelId, s"unexpected htlc id: expected=$expected actual=$actual")
|
||||
case class InvalidPaymentHash (channelId: BinaryData) extends ChannelException(channelId, "invalid payment hash")
|
||||
case class ExpiryTooSmall (channelId: BinaryData, minimum: Long, actual: Long, blockCount: Long) extends ChannelException(channelId, s"expiry too small: required=$minimum actual=$actual blockCount=$blockCount")
|
||||
case class ExpiryCannotBeInThePast (channelId: BinaryData, expiry: Long, blockCount: Long) extends ChannelException(channelId, s"expiry can't be in the past: expiry=$expiry blockCount=$blockCount")
|
||||
case class HtlcValueTooSmall (channelId: BinaryData, minimum: Long, actual: Long) extends ChannelException(channelId, s"htlc value too small: mininmum=$minimum actual=$actual")
|
||||
case class HtlcValueTooHighInFlight (channelId: BinaryData, maximum: UInt64, actual: UInt64) extends ChannelException(channelId, s"in-flight htlcs hold too much value: maximum=$maximum actual=$actual")
|
||||
case class TooManyAcceptedHtlcs (channelId: BinaryData, maximum: Long) extends ChannelException(channelId, s"too many accepted htlcs: maximum=$maximum")
|
||||
case class InsufficientFunds (channelId: BinaryData, amountMsat: Long, missingSatoshis: Long, reserveSatoshis: Long, feesSatoshis: Long) extends ChannelException(channelId, s"insufficient funds: missingSatoshis=$missingSatoshis reserveSatoshis=$reserveSatoshis fees=$feesSatoshis")
|
||||
case class InvalidHtlcPreimage (channelId: BinaryData, id: Long) extends ChannelException(channelId, s"invalid htlc preimage for htlc id=$id")
|
||||
case class UnknownHtlcId (channelId: BinaryData, id: Long) extends ChannelException(channelId, s"unknown htlc id=$id")
|
||||
case class FundeeCannotSendUpdateFee (channelId: BinaryData) extends ChannelException(channelId, s"only the funder should send update_fee messages")
|
||||
case class CannotAffordFees (channelId: BinaryData, missingSatoshis: Long, reserveSatoshis: Long, feesSatoshis: Long) extends ChannelException(channelId, s"can't pay the fee: missingSatoshis=$missingSatoshis reserveSatoshis=$reserveSatoshis feesSatoshis=$feesSatoshis")
|
||||
case class CannotSignWithoutChanges (channelId: BinaryData) extends ChannelException(channelId, "cannot sign when there are no changes")
|
||||
case class CannotSignBeforeRevocation (channelId: BinaryData) extends ChannelException(channelId, "cannot sign until next revocation hash is received")
|
||||
case class UnexpectedRevocation (channelId: BinaryData) extends ChannelException(channelId, "received unexpected RevokeAndAck message")
|
||||
case class InvalidRevocation (channelId: BinaryData) extends ChannelException(channelId, "invalid revocation")
|
||||
case class CommitmentSyncError (channelId: BinaryData) extends ChannelException(channelId, "commitment sync error")
|
||||
case class RevocationSyncError (channelId: BinaryData) extends ChannelException(channelId, "revocation sync error")
|
@ -75,16 +75,16 @@ object Commitments extends Logging {
|
||||
def sendAdd(commitments: Commitments, cmd: CMD_ADD_HTLC): Either[ChannelException, (Commitments, UpdateAddHtlc)] = {
|
||||
|
||||
if (cmd.paymentHash.size != 32) {
|
||||
return Left(InvalidPaymentHash)
|
||||
return Left(InvalidPaymentHash(commitments.channelId))
|
||||
}
|
||||
|
||||
val blockCount = Globals.blockCount.get()
|
||||
if (cmd.expiry <= blockCount) {
|
||||
return Left(ExpiryCannotBeInThePast(cmd.expiry, blockCount))
|
||||
return Left(ExpiryCannotBeInThePast(commitments.channelId, cmd.expiry, blockCount))
|
||||
}
|
||||
|
||||
if (cmd.amountMsat < commitments.remoteParams.htlcMinimumMsat) {
|
||||
return Left(HtlcValueTooSmall(minimum = commitments.remoteParams.htlcMinimumMsat, actual = cmd.amountMsat))
|
||||
return Left(HtlcValueTooSmall(commitments.channelId, minimum = commitments.remoteParams.htlcMinimumMsat, actual = cmd.amountMsat))
|
||||
}
|
||||
|
||||
// let's compute the current commitment *as seen by them* with this change taken into account
|
||||
@ -95,13 +95,13 @@ object Commitments extends Logging {
|
||||
val htlcValueInFlight = UInt64(reduced.htlcs.map(_.add.amountMsat).sum)
|
||||
if (htlcValueInFlight > commitments1.remoteParams.maxHtlcValueInFlightMsat) {
|
||||
// TODO: this should be a specific UPDATE error
|
||||
return Left(HtlcValueTooHighInFlight(maximum = commitments1.remoteParams.maxHtlcValueInFlightMsat, actual = htlcValueInFlight))
|
||||
return Left(HtlcValueTooHighInFlight(commitments.channelId, maximum = commitments1.remoteParams.maxHtlcValueInFlightMsat, actual = htlcValueInFlight))
|
||||
}
|
||||
|
||||
// the HTLC we are about to create is outgoing, but from their point of view it is incoming
|
||||
val acceptedHtlcs = reduced.htlcs.count(_.direction == IN)
|
||||
if (acceptedHtlcs > commitments1.remoteParams.maxAcceptedHtlcs) {
|
||||
return Left(TooManyAcceptedHtlcs(maximum = commitments1.remoteParams.maxAcceptedHtlcs))
|
||||
return Left(TooManyAcceptedHtlcs(commitments.channelId, maximum = commitments1.remoteParams.maxAcceptedHtlcs))
|
||||
}
|
||||
|
||||
// a node cannot spend pending incoming htlcs, and need to keep funds above the reserve required by the counterparty, after paying the fee
|
||||
@ -109,7 +109,7 @@ object Commitments extends Logging {
|
||||
val fees = if (commitments1.localParams.isFunder) Transactions.commitTxFee(Satoshi(commitments1.remoteParams.dustLimitSatoshis), reduced).amount else 0
|
||||
val missing = reduced.toRemoteMsat / 1000 - commitments1.remoteParams.channelReserveSatoshis - fees
|
||||
if (missing < 0) {
|
||||
return Left(InsufficientFunds(amountMsat = cmd.amountMsat, missingSatoshis = -1 * missing, reserveSatoshis = commitments1.remoteParams.channelReserveSatoshis, feesSatoshis = fees))
|
||||
return Left(InsufficientFunds(commitments.channelId, amountMsat = cmd.amountMsat, missingSatoshis = -1 * missing, reserveSatoshis = commitments1.remoteParams.channelReserveSatoshis, feesSatoshis = fees))
|
||||
}
|
||||
|
||||
Right(commitments1, add)
|
||||
@ -117,22 +117,22 @@ object Commitments extends Logging {
|
||||
|
||||
def receiveAdd(commitments: Commitments, add: UpdateAddHtlc): Commitments = {
|
||||
if (add.id != commitments.remoteNextHtlcId) {
|
||||
throw UnexpectedHtlcId(expected = commitments.remoteNextHtlcId, actual = add.id)
|
||||
throw UnexpectedHtlcId(commitments.channelId, expected = commitments.remoteNextHtlcId, actual = add.id)
|
||||
}
|
||||
|
||||
if (add.paymentHash.size != 32) {
|
||||
throw InvalidPaymentHash
|
||||
throw InvalidPaymentHash(commitments.channelId)
|
||||
}
|
||||
|
||||
val blockCount = Globals.blockCount.get()
|
||||
// we need a reasonable amount of time to pull the funds before the sender can get refunded
|
||||
val minExpiry = blockCount + 3
|
||||
if (add.expiry < minExpiry) {
|
||||
throw ExpiryTooSmall(minimum = minExpiry, actual = add.expiry, blockCount = blockCount)
|
||||
throw ExpiryTooSmall(commitments.channelId, minimum = minExpiry, actual = add.expiry, blockCount = blockCount)
|
||||
}
|
||||
|
||||
if (add.amountMsat < commitments.localParams.htlcMinimumMsat) {
|
||||
throw HtlcValueTooSmall(minimum = commitments.localParams.htlcMinimumMsat, actual = add.amountMsat)
|
||||
throw HtlcValueTooSmall(commitments.channelId, minimum = commitments.localParams.htlcMinimumMsat, actual = add.amountMsat)
|
||||
}
|
||||
|
||||
// let's compute the current commitment *as seen by us* including this change
|
||||
@ -141,19 +141,19 @@ object Commitments extends Logging {
|
||||
|
||||
val htlcValueInFlight = UInt64(reduced.htlcs.map(_.add.amountMsat).sum)
|
||||
if (htlcValueInFlight > commitments1.localParams.maxHtlcValueInFlightMsat) {
|
||||
throw HtlcValueTooHighInFlight(maximum = commitments1.localParams.maxHtlcValueInFlightMsat, actual = htlcValueInFlight)
|
||||
throw HtlcValueTooHighInFlight(commitments.channelId, maximum = commitments1.localParams.maxHtlcValueInFlightMsat, actual = htlcValueInFlight)
|
||||
}
|
||||
|
||||
val acceptedHtlcs = reduced.htlcs.count(_.direction == IN)
|
||||
if (acceptedHtlcs > commitments1.localParams.maxAcceptedHtlcs) {
|
||||
throw TooManyAcceptedHtlcs(maximum = commitments1.localParams.maxAcceptedHtlcs)
|
||||
throw TooManyAcceptedHtlcs(commitments.channelId, maximum = commitments1.localParams.maxAcceptedHtlcs)
|
||||
}
|
||||
|
||||
// a node cannot spend pending incoming htlcs, and need to keep funds above the reserve required by the counterparty, after paying the fee
|
||||
val fees = if (commitments1.localParams.isFunder) 0 else Transactions.commitTxFee(Satoshi(commitments1.localParams.dustLimitSatoshis), reduced).amount
|
||||
val missing = reduced.toRemoteMsat / 1000 - commitments1.localParams.channelReserveSatoshis - fees
|
||||
if (missing < 0) {
|
||||
throw InsufficientFunds(amountMsat = add.amountMsat, missingSatoshis = -1 * missing, reserveSatoshis = commitments1.localParams.channelReserveSatoshis, feesSatoshis = fees)
|
||||
throw InsufficientFunds(commitments.channelId, amountMsat = add.amountMsat, missingSatoshis = -1 * missing, reserveSatoshis = commitments1.localParams.channelReserveSatoshis, feesSatoshis = fees)
|
||||
}
|
||||
|
||||
commitments1
|
||||
@ -178,20 +178,20 @@ object Commitments extends Logging {
|
||||
case _ => false
|
||||
} =>
|
||||
// we have already sent a fail/fulfill for this htlc
|
||||
throw UnknownHtlcId(cmd.id)
|
||||
throw UnknownHtlcId(commitments.channelId, cmd.id)
|
||||
case Some(htlc) if htlc.paymentHash == sha256(cmd.r) =>
|
||||
val fulfill = UpdateFulfillHtlc(commitments.channelId, cmd.id, cmd.r)
|
||||
val commitments1 = addLocalProposal(commitments, fulfill)
|
||||
(commitments1, fulfill)
|
||||
case Some(htlc) => throw InvalidHtlcPreimage(cmd.id)
|
||||
case None => throw UnknownHtlcId(cmd.id)
|
||||
case Some(htlc) => throw InvalidHtlcPreimage(commitments.channelId, cmd.id)
|
||||
case None => throw UnknownHtlcId(commitments.channelId, cmd.id)
|
||||
}
|
||||
|
||||
def receiveFulfill(commitments: Commitments, fulfill: UpdateFulfillHtlc): Either[Commitments, Commitments] =
|
||||
getHtlcCrossSigned(commitments, OUT, fulfill.id) match {
|
||||
case Some(htlc) if htlc.paymentHash == sha256(fulfill.paymentPreimage) => Right(addRemoteProposal(commitments, fulfill))
|
||||
case Some(htlc) => throw InvalidHtlcPreimage(fulfill.id)
|
||||
case None => throw UnknownHtlcId(fulfill.id)
|
||||
case Some(htlc) => throw InvalidHtlcPreimage(commitments.channelId, fulfill.id)
|
||||
case None => throw UnknownHtlcId(commitments.channelId, fulfill.id)
|
||||
}
|
||||
|
||||
def sendFail(commitments: Commitments, cmd: CMD_FAIL_HTLC, nodeSecret: PrivateKey): (Commitments, UpdateFailHtlc) =
|
||||
@ -203,7 +203,7 @@ object Commitments extends Logging {
|
||||
case _ => false
|
||||
} =>
|
||||
// we have already sent a fail/fulfill for this htlc
|
||||
throw UnknownHtlcId(cmd.id)
|
||||
throw UnknownHtlcId(commitments.channelId, cmd.id)
|
||||
case Some(htlc) =>
|
||||
// we need the shared secret to build the error packet
|
||||
val sharedSecret = Sphinx.parsePacket(nodeSecret, htlc.paymentHash, htlc.onionRoutingPacket).sharedSecret
|
||||
@ -214,7 +214,7 @@ object Commitments extends Logging {
|
||||
val fail = UpdateFailHtlc(commitments.channelId, cmd.id, reason)
|
||||
val commitments1 = addLocalProposal(commitments, fail)
|
||||
(commitments1, fail)
|
||||
case None => throw UnknownHtlcId(cmd.id)
|
||||
case None => throw UnknownHtlcId(commitments.channelId, cmd.id)
|
||||
}
|
||||
|
||||
def sendFailMalformed(commitments: Commitments, cmd: CMD_FAIL_MALFORMED_HTLC): (Commitments, UpdateFailMalformedHtlc) =
|
||||
@ -226,29 +226,29 @@ object Commitments extends Logging {
|
||||
case _ => false
|
||||
} =>
|
||||
// we have already sent a fail/fulfill for this htlc
|
||||
throw UnknownHtlcId(cmd.id)
|
||||
throw UnknownHtlcId(commitments.channelId, cmd.id)
|
||||
case Some(htlc) =>
|
||||
val fail = UpdateFailMalformedHtlc(commitments.channelId, cmd.id, cmd.onionHash, cmd.failureCode)
|
||||
val commitments1 = addLocalProposal(commitments, fail)
|
||||
(commitments1, fail)
|
||||
case None => throw UnknownHtlcId(cmd.id)
|
||||
case None => throw UnknownHtlcId(commitments.channelId, cmd.id)
|
||||
}
|
||||
|
||||
def receiveFail(commitments: Commitments, fail: UpdateFailHtlc): Either[Commitments, Commitments] =
|
||||
getHtlcCrossSigned(commitments, OUT, fail.id) match {
|
||||
case Some(htlc) => Right(addRemoteProposal(commitments, fail))
|
||||
case None => throw UnknownHtlcId(fail.id)
|
||||
case None => throw UnknownHtlcId(commitments.channelId, fail.id)
|
||||
}
|
||||
|
||||
def receiveFailMalformed(commitments: Commitments, fail: UpdateFailMalformedHtlc): Either[Commitments, Commitments] =
|
||||
getHtlcCrossSigned(commitments, OUT, fail.id) match {
|
||||
case Some(htlc) => Right(addRemoteProposal(commitments, fail))
|
||||
case None => throw UnknownHtlcId(fail.id)
|
||||
case None => throw UnknownHtlcId(commitments.channelId, fail.id)
|
||||
}
|
||||
|
||||
def sendFee(commitments: Commitments, cmd: CMD_UPDATE_FEE): (Commitments, UpdateFee) = {
|
||||
if (!commitments.localParams.isFunder) {
|
||||
throw FundeeCannotSendUpdateFee
|
||||
throw FundeeCannotSendUpdateFee(commitments.channelId)
|
||||
}
|
||||
// let's compute the current commitment *as seen by them* with this change taken into account
|
||||
val fee = UpdateFee(commitments.channelId, cmd.feeratePerKw)
|
||||
@ -260,7 +260,7 @@ object Commitments extends Logging {
|
||||
val fees = Transactions.commitTxFee(Satoshi(commitments1.remoteParams.dustLimitSatoshis), reduced).amount
|
||||
val missing = reduced.toRemoteMsat / 1000 - commitments1.remoteParams.channelReserveSatoshis - fees
|
||||
if (missing < 0) {
|
||||
throw CannotAffordFees(missingSatoshis = -1 * missing, reserveSatoshis = commitments1.localParams.channelReserveSatoshis, feesSatoshis = fees)
|
||||
throw CannotAffordFees(commitments.channelId, missingSatoshis = -1 * missing, reserveSatoshis = commitments1.localParams.channelReserveSatoshis, feesSatoshis = fees)
|
||||
}
|
||||
|
||||
(commitments1, fee)
|
||||
@ -268,12 +268,12 @@ object Commitments extends Logging {
|
||||
|
||||
def receiveFee(commitments: Commitments, fee: UpdateFee, maxFeerateMismatch: Double): Commitments = {
|
||||
if (commitments.localParams.isFunder) {
|
||||
throw FundeeCannotSendUpdateFee
|
||||
throw FundeeCannotSendUpdateFee(commitments.channelId)
|
||||
}
|
||||
|
||||
val localFeeratePerKw = Globals.feeratePerKw.get()
|
||||
if (Helpers.isFeeDiffTooHigh(fee.feeratePerKw, localFeeratePerKw, maxFeerateMismatch)) {
|
||||
throw FeerateTooDifferent(localFeeratePerKw = localFeeratePerKw, remoteFeeratePerKw = fee.feeratePerKw)
|
||||
throw FeerateTooDifferent(commitments.channelId, localFeeratePerKw = localFeeratePerKw, remoteFeeratePerKw = fee.feeratePerKw)
|
||||
}
|
||||
|
||||
// NB: we check that the funder can afford this new fee even if spec allows to do it at next signature
|
||||
@ -289,7 +289,7 @@ object Commitments extends Logging {
|
||||
val fees = Transactions.commitTxFee(Satoshi(commitments1.remoteParams.dustLimitSatoshis), reduced).amount
|
||||
val missing = reduced.toRemoteMsat / 1000 - commitments1.localParams.channelReserveSatoshis - fees
|
||||
if (missing < 0) {
|
||||
throw CannotAffordFees(missingSatoshis = -1 * missing, reserveSatoshis = commitments1.localParams.channelReserveSatoshis, feesSatoshis = fees)
|
||||
throw CannotAffordFees(commitments.channelId, missingSatoshis = -1 * missing, reserveSatoshis = commitments1.localParams.channelReserveSatoshis, feesSatoshis = fees)
|
||||
}
|
||||
|
||||
commitments1
|
||||
@ -307,7 +307,7 @@ object Commitments extends Logging {
|
||||
import commitments._
|
||||
commitments.remoteNextCommitInfo match {
|
||||
case Right(_) if !localHasChanges(commitments) =>
|
||||
throw CannotSignWithoutChanges
|
||||
throw CannotSignWithoutChanges(commitments.channelId)
|
||||
case Right(remoteNextPerCommitmentPoint) =>
|
||||
// remote commitment will includes all local changes + remote acked changes
|
||||
val spec = CommitmentSpec.reduce(remoteCommit.spec, remoteChanges.acked, localChanges.proposed)
|
||||
@ -331,7 +331,7 @@ object Commitments extends Logging {
|
||||
remoteChanges = remoteChanges.copy(acked = Nil, signed = remoteChanges.acked))
|
||||
(commitments1, commitSig)
|
||||
case Left(_) =>
|
||||
throw CannotSignBeforeRevocation
|
||||
throw CannotSignBeforeRevocation(commitments.channelId)
|
||||
}
|
||||
}
|
||||
|
||||
@ -347,7 +347,7 @@ object Commitments extends Logging {
|
||||
// and will increment our index
|
||||
|
||||
if (!remoteHasChanges(commitments))
|
||||
throw CannotSignWithoutChanges
|
||||
throw CannotSignWithoutChanges(commitments.channelId)
|
||||
|
||||
// check that their signature is valid
|
||||
// signatures are now optional in the commit message, and will be sent only if the other party is actually
|
||||
@ -363,7 +363,7 @@ object Commitments extends Logging {
|
||||
// no need to compute htlc sigs if commit sig doesn't check out
|
||||
val signedCommitTx = Transactions.addSigs(localCommitTx, localParams.fundingPrivKey.publicKey, remoteParams.fundingPubKey, sig, commit.signature)
|
||||
if (Transactions.checkSpendable(signedCommitTx).isFailure) {
|
||||
throw InvalidCommitmentSignature
|
||||
throw InvalidCommitmentSignature(commitments.channelId)
|
||||
}
|
||||
|
||||
val sortedHtlcTxs: Seq[TransactionWithInputInfo] = (htlcTimeoutTxs ++ htlcSuccessTxs).sortBy(_.input.outPoint.index)
|
||||
@ -410,7 +410,7 @@ object Commitments extends Logging {
|
||||
// we receive a revocation because we just sent them a sig for their next commit tx
|
||||
remoteNextCommitInfo match {
|
||||
case Left(_) if revocation.perCommitmentSecret.toPoint != remoteCommit.remotePerCommitmentPoint =>
|
||||
throw InvalidRevocation
|
||||
throw InvalidRevocation(commitments.channelId)
|
||||
case Left(WaitingForRevocation(theirNextCommit, _, _, _)) =>
|
||||
val commitments1 = commitments.copy(
|
||||
localChanges = localChanges.copy(signed = Nil, acked = localChanges.acked ++ localChanges.signed),
|
||||
@ -421,7 +421,7 @@ object Commitments extends Logging {
|
||||
|
||||
commitments1
|
||||
case Right(_) =>
|
||||
throw UnexpectedRevocation
|
||||
throw UnexpectedRevocation(commitments.channelId)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -52,11 +52,11 @@ class PaymentLifecycle(sourceNodeId: PublicKey, router: ActorRef, register: Acto
|
||||
|
||||
when(WAITING_FOR_ROUTE) {
|
||||
case Event(RouteResponse(hops, ignoreNodes, ignoreChannels), WaitingForRoute(s, c, failures)) =>
|
||||
log.info(s"route found: attempt=${failures.size + 1}/${c.maxAttempts} route=${hops.map(_.nextNodeId).mkString("->")}")
|
||||
log.info(s"route found: attempt=${failures.size + 1}/${c.maxAttempts} route=${hops.map(_.nextNodeId).mkString("->")} channels=${hops.map(_.lastUpdate.shortChannelId.toHexString).mkString("->")}")
|
||||
val firstHop = hops.head
|
||||
val finalExpiry = Globals.blockCount.get().toInt + defaultHtlcExpiry
|
||||
val (cmd, sharedSecrets) = buildCommand(c.amountMsat, finalExpiry, c.paymentHash, hops)
|
||||
// TODO: HACK!!!! see Router.scala
|
||||
// TODO: HACK!!!! see Router.scala (we actually store the first node id in the sig)
|
||||
if (firstHop.lastUpdate.signature.size == 32) {
|
||||
register ! Register.Forward(firstHop.lastUpdate.signature, cmd)
|
||||
} else {
|
||||
|
@ -304,7 +304,7 @@ class Router(nodeParams: NodeParams, watcher: ActorRef) extends FSM[State, Data]
|
||||
val updates2 = updates1.filterKeys(!d.excludedChannels.contains(_))
|
||||
// we also filter out excluded channels
|
||||
val updates3 = filterUpdates(updates2, ignoreNodes, ignoreChannels)
|
||||
log.info(s"finding a route $start->$end with ignoreNodes=${ignoreNodes.map(_.toBin).mkString(",")} ignoreChannels=${ignoreChannels.mkString(",")}")
|
||||
log.info(s"finding a route $start->$end with ignoreNodes=${ignoreNodes.map(_.toBin).mkString(",")} ignoreChannels=${ignoreChannels.map(_.toHexString).mkString(",")}")
|
||||
findRoute(start, end, updates3).map(r => RouteResponse(r, ignoreNodes, ignoreChannels)) pipeTo sender
|
||||
stay
|
||||
}
|
||||
|
@ -142,4 +142,6 @@ trait StateTestsHelperMethods extends TestKitBase {
|
||||
|
||||
}
|
||||
|
||||
def channelId(a: TestFSMRef[State, Data, Channel]) = Helpers.getChannelId(a.stateData)
|
||||
|
||||
}
|
||||
|
@ -95,8 +95,8 @@ class NormalStateSpec extends TestkitBaseClass with StateTestsHelperMethods {
|
||||
val sender = TestProbe()
|
||||
val add = CMD_ADD_HTLC(500000000, "11" * 42, expiry = 400144)
|
||||
sender.send(alice, add)
|
||||
sender.expectMsg(Failure(InvalidPaymentHash))
|
||||
relayer.expectMsg(AddHtlcFailed(add, InvalidPaymentHash))
|
||||
sender.expectMsg(Failure(InvalidPaymentHash(channelId(alice))))
|
||||
relayer.expectMsg(AddHtlcFailed(add, InvalidPaymentHash(channelId(alice))))
|
||||
alice2bob.expectNoMsg(200 millis)
|
||||
}
|
||||
}
|
||||
@ -106,7 +106,7 @@ class NormalStateSpec extends TestkitBaseClass with StateTestsHelperMethods {
|
||||
val sender = TestProbe()
|
||||
val add = CMD_ADD_HTLC(500000000, "11" * 32, expiry = 300000)
|
||||
sender.send(alice, add)
|
||||
val error = ExpiryCannotBeInThePast(300000, 400000)
|
||||
val error = ExpiryCannotBeInThePast(channelId(alice), 300000, 400000)
|
||||
sender.expectMsg(Failure(error))
|
||||
relayer.expectMsg(AddHtlcFailed(add, error))
|
||||
alice2bob.expectNoMsg(200 millis)
|
||||
@ -118,7 +118,7 @@ class NormalStateSpec extends TestkitBaseClass with StateTestsHelperMethods {
|
||||
val sender = TestProbe()
|
||||
val add = CMD_ADD_HTLC(50, "11" * 32, 400144)
|
||||
sender.send(alice, add)
|
||||
val error = HtlcValueTooSmall(1000, 50)
|
||||
val error = HtlcValueTooSmall(channelId(alice), 1000, 50)
|
||||
sender.expectMsg(Failure(error))
|
||||
relayer.expectMsg(AddHtlcFailed(add, error))
|
||||
alice2bob.expectNoMsg(200 millis)
|
||||
@ -130,7 +130,7 @@ class NormalStateSpec extends TestkitBaseClass with StateTestsHelperMethods {
|
||||
val sender = TestProbe()
|
||||
val add = CMD_ADD_HTLC(Int.MaxValue, "11" * 32, 400144)
|
||||
sender.send(alice, add)
|
||||
val error = InsufficientFunds(amountMsat = Int.MaxValue, missingSatoshis = 1376443, reserveSatoshis = 20000, feesSatoshis = 8960)
|
||||
val error = InsufficientFunds(channelId(alice), amountMsat = Int.MaxValue, missingSatoshis = 1376443, reserveSatoshis = 20000, feesSatoshis = 8960)
|
||||
sender.expectMsg(Failure(error))
|
||||
relayer.expectMsg(AddHtlcFailed(add, error))
|
||||
alice2bob.expectNoMsg(200 millis)
|
||||
@ -154,7 +154,7 @@ class NormalStateSpec extends TestkitBaseClass with StateTestsHelperMethods {
|
||||
alice2bob.expectMsgType[UpdateAddHtlc]
|
||||
val add = CMD_ADD_HTLC(1000000, "44" * 32, 400144)
|
||||
sender.send(alice, add)
|
||||
val error = InsufficientFunds(amountMsat = 1000000, missingSatoshis = 1000, reserveSatoshis = 20000, feesSatoshis = 12400)
|
||||
val error = InsufficientFunds(channelId(alice), amountMsat = 1000000, missingSatoshis = 1000, reserveSatoshis = 20000, feesSatoshis = 12400)
|
||||
sender.expectMsg(Failure(error))
|
||||
relayer.expectMsg(AddHtlcFailed(add, error))
|
||||
alice2bob.expectNoMsg(200 millis)
|
||||
@ -174,7 +174,7 @@ class NormalStateSpec extends TestkitBaseClass with StateTestsHelperMethods {
|
||||
alice2bob.expectMsgType[UpdateAddHtlc]
|
||||
val add = CMD_ADD_HTLC(500000000, "33" * 32, 400144)
|
||||
sender.send(alice, add)
|
||||
val error = InsufficientFunds(amountMsat = 500000000, missingSatoshis = 332400, reserveSatoshis = 20000, feesSatoshis = 12400)
|
||||
val error = InsufficientFunds(channelId(alice), amountMsat = 500000000, missingSatoshis = 332400, reserveSatoshis = 20000, feesSatoshis = 12400)
|
||||
sender.expectMsg(Failure(error))
|
||||
relayer.expectMsg(AddHtlcFailed(add, error))
|
||||
alice2bob.expectNoMsg(200 millis)
|
||||
@ -186,7 +186,7 @@ class NormalStateSpec extends TestkitBaseClass with StateTestsHelperMethods {
|
||||
val sender = TestProbe()
|
||||
val add = CMD_ADD_HTLC(151000000, "11" * 32, 400144)
|
||||
sender.send(bob, add)
|
||||
val error = HtlcValueTooHighInFlight(maximum = 150000000, actual = 151000000)
|
||||
val error = HtlcValueTooHighInFlight(channelId(bob), maximum = 150000000, actual = 151000000)
|
||||
sender.expectMsg(Failure(error))
|
||||
relayer.expectMsg(AddHtlcFailed(add, error))
|
||||
bob2alice.expectNoMsg(200 millis)
|
||||
@ -205,7 +205,7 @@ class NormalStateSpec extends TestkitBaseClass with StateTestsHelperMethods {
|
||||
}
|
||||
val add = CMD_ADD_HTLC(10000000, "33" * 32, 400144)
|
||||
sender.send(alice, add)
|
||||
val error = TooManyAcceptedHtlcs(maximum = 30)
|
||||
val error = TooManyAcceptedHtlcs(channelId(alice), maximum = 30)
|
||||
sender.expectMsg(Failure(error))
|
||||
relayer.expectMsg(AddHtlcFailed(add, error))
|
||||
alice2bob.expectNoMsg(200 millis)
|
||||
@ -222,7 +222,7 @@ class NormalStateSpec extends TestkitBaseClass with StateTestsHelperMethods {
|
||||
|
||||
// actual test starts here
|
||||
sender.send(alice, CMD_ADD_HTLC(300000000, "11" * 32, 400144))
|
||||
sender.expectMsg(Failure(ClosingInProgress))
|
||||
sender.expectMsg(Failure(ClosingInProgress(channelId(alice))))
|
||||
}
|
||||
}
|
||||
|
||||
@ -245,7 +245,7 @@ class NormalStateSpec extends TestkitBaseClass with StateTestsHelperMethods {
|
||||
bob ! htlc.copy(id = 3)
|
||||
bob ! htlc.copy(id = 42)
|
||||
val error = bob2alice.expectMsgType[Error]
|
||||
assert(new String(error.data) === UnexpectedHtlcId(expected = 4, actual = 42).getMessage)
|
||||
assert(new String(error.data) === UnexpectedHtlcId(channelId(bob), expected = 4, actual = 42).getMessage)
|
||||
awaitCond(bob.stateName == CLOSING)
|
||||
bob2blockchain.expectMsg(PublishAsap(tx))
|
||||
bob2blockchain.expectMsgType[WatchConfirmed]
|
||||
@ -258,7 +258,7 @@ class NormalStateSpec extends TestkitBaseClass with StateTestsHelperMethods {
|
||||
val htlc = UpdateAddHtlc("00" * 32, 0, 150000, "11" * 42, 400144, defaultOnion)
|
||||
alice2bob.forward(bob, htlc)
|
||||
val error = bob2alice.expectMsgType[Error]
|
||||
assert(new String(error.data) === InvalidPaymentHash.getMessage)
|
||||
assert(new String(error.data) === InvalidPaymentHash(channelId(bob)).getMessage)
|
||||
awaitCond(bob.stateName == CLOSING)
|
||||
bob2blockchain.expectMsg(PublishAsap(tx))
|
||||
bob2blockchain.expectMsgType[WatchConfirmed]
|
||||
@ -271,7 +271,7 @@ class NormalStateSpec extends TestkitBaseClass with StateTestsHelperMethods {
|
||||
val htlc = UpdateAddHtlc("00" * 32, 0, 150000, BinaryData("42" * 32), expiry = 1, defaultOnion)
|
||||
alice2bob.forward(bob, htlc)
|
||||
val error = bob2alice.expectMsgType[Error]
|
||||
assert(new String(error.data) === ExpiryTooSmall(minimum = 400003, actual = 1, blockCount = 400000).getMessage)
|
||||
assert(new String(error.data) === ExpiryTooSmall(channelId(bob), minimum = 400003, actual = 1, blockCount = 400000).getMessage)
|
||||
awaitCond(bob.stateName == CLOSING)
|
||||
bob2blockchain.expectMsg(PublishAsap(tx))
|
||||
bob2blockchain.expectMsgType[WatchConfirmed]
|
||||
@ -284,7 +284,7 @@ class NormalStateSpec extends TestkitBaseClass with StateTestsHelperMethods {
|
||||
val htlc = UpdateAddHtlc("00" * 32, 0, 150, BinaryData("42" * 32), expiry = 400144, defaultOnion)
|
||||
alice2bob.forward(bob, htlc)
|
||||
val error = bob2alice.expectMsgType[Error]
|
||||
assert(new String(error.data) === HtlcValueTooSmall(minimum = 1000, actual = 150).getMessage)
|
||||
assert(new String(error.data) === HtlcValueTooSmall(channelId(bob), minimum = 1000, actual = 150).getMessage)
|
||||
awaitCond(bob.stateName == CLOSING)
|
||||
bob2blockchain.expectMsg(PublishAsap(tx))
|
||||
bob2blockchain.expectMsgType[WatchConfirmed]
|
||||
@ -297,7 +297,7 @@ class NormalStateSpec extends TestkitBaseClass with StateTestsHelperMethods {
|
||||
val htlc = UpdateAddHtlc("00" * 32, 0, Long.MaxValue, BinaryData("42" * 32), 400144, defaultOnion)
|
||||
alice2bob.forward(bob, htlc)
|
||||
val error = bob2alice.expectMsgType[Error]
|
||||
assert(new String(error.data) === InsufficientFunds(amountMsat = Long.MaxValue, missingSatoshis = 9223372036083735L, reserveSatoshis = 20000, feesSatoshis = 8960).getMessage)
|
||||
assert(new String(error.data) === InsufficientFunds(channelId(bob), amountMsat = Long.MaxValue, missingSatoshis = 9223372036083735L, reserveSatoshis = 20000, feesSatoshis = 8960).getMessage)
|
||||
awaitCond(bob.stateName == CLOSING)
|
||||
bob2blockchain.expectMsg(PublishAsap(tx))
|
||||
bob2blockchain.expectMsgType[WatchConfirmed]
|
||||
@ -312,7 +312,7 @@ class NormalStateSpec extends TestkitBaseClass with StateTestsHelperMethods {
|
||||
alice2bob.forward(bob, UpdateAddHtlc("00" * 32, 2, 167600000, "33" * 32, 400144, defaultOnion))
|
||||
alice2bob.forward(bob, UpdateAddHtlc("00" * 32, 3, 10000000, "44" * 32, 400144, defaultOnion))
|
||||
val error = bob2alice.expectMsgType[Error]
|
||||
assert(new String(error.data) === InsufficientFunds(amountMsat = 10000000, missingSatoshis = 11720, reserveSatoshis = 20000, feesSatoshis = 14120).getMessage)
|
||||
assert(new String(error.data) === InsufficientFunds(channelId(bob), amountMsat = 10000000, missingSatoshis = 11720, reserveSatoshis = 20000, feesSatoshis = 14120).getMessage)
|
||||
awaitCond(bob.stateName == CLOSING)
|
||||
bob2blockchain.expectMsg(PublishAsap(tx))
|
||||
bob2blockchain.expectMsgType[WatchConfirmed]
|
||||
@ -326,7 +326,7 @@ class NormalStateSpec extends TestkitBaseClass with StateTestsHelperMethods {
|
||||
alice2bob.forward(bob, UpdateAddHtlc("00" * 32, 1, 300000000, "22" * 32, 400144, defaultOnion))
|
||||
alice2bob.forward(bob, UpdateAddHtlc("00" * 32, 2, 500000000, "33" * 32, 400144, defaultOnion))
|
||||
val error = bob2alice.expectMsgType[Error]
|
||||
assert(new String(error.data) === InsufficientFunds(amountMsat = 500000000, missingSatoshis = 332400, reserveSatoshis = 20000, feesSatoshis = 12400).getMessage)
|
||||
assert(new String(error.data) === InsufficientFunds(channelId(bob), amountMsat = 500000000, missingSatoshis = 332400, reserveSatoshis = 20000, feesSatoshis = 12400).getMessage)
|
||||
awaitCond(bob.stateName == CLOSING)
|
||||
bob2blockchain.expectMsg(PublishAsap(tx))
|
||||
bob2blockchain.expectMsgType[WatchConfirmed]
|
||||
@ -338,7 +338,7 @@ class NormalStateSpec extends TestkitBaseClass with StateTestsHelperMethods {
|
||||
val tx = alice.stateData.asInstanceOf[DATA_NORMAL].commitments.localCommit.publishableTxs.commitTx.tx
|
||||
alice2bob.forward(alice, UpdateAddHtlc("00" * 32, 0, 151000000, "11" * 32, 400144, defaultOnion))
|
||||
val error = alice2bob.expectMsgType[Error]
|
||||
assert(new String(error.data) === HtlcValueTooHighInFlight(maximum = 150000000, actual = 151000000).getMessage)
|
||||
assert(new String(error.data) === HtlcValueTooHighInFlight(channelId(alice), maximum = 150000000, actual = 151000000).getMessage)
|
||||
awaitCond(alice.stateName == CLOSING)
|
||||
alice2blockchain.expectMsg(PublishAsap(tx))
|
||||
alice2blockchain.expectMsgType[WatchConfirmed]
|
||||
@ -354,7 +354,7 @@ class NormalStateSpec extends TestkitBaseClass with StateTestsHelperMethods {
|
||||
}
|
||||
alice2bob.forward(bob, UpdateAddHtlc("00" * 32, 30, 1000000, "11" * 32, 400144, defaultOnion))
|
||||
val error = bob2alice.expectMsgType[Error]
|
||||
assert(new String(error.data) === TooManyAcceptedHtlcs(maximum = 30).getMessage)
|
||||
assert(new String(error.data) === TooManyAcceptedHtlcs(channelId(bob), maximum = 30).getMessage)
|
||||
awaitCond(bob.stateName == CLOSING)
|
||||
bob2blockchain.expectMsg(PublishAsap(tx))
|
||||
bob2blockchain.expectMsgType[WatchConfirmed]
|
||||
@ -720,7 +720,7 @@ class NormalStateSpec extends TestkitBaseClass with StateTestsHelperMethods {
|
||||
val initialState = bob.stateData.asInstanceOf[DATA_NORMAL]
|
||||
|
||||
sender.send(bob, CMD_FULFILL_HTLC(42, r))
|
||||
sender.expectMsg(Failure(UnknownHtlcId(42)))
|
||||
sender.expectMsg(Failure(UnknownHtlcId(channelId(bob), 42)))
|
||||
assert(initialState == bob.stateData)
|
||||
}
|
||||
}
|
||||
@ -734,7 +734,7 @@ class NormalStateSpec extends TestkitBaseClass with StateTestsHelperMethods {
|
||||
// actual test begins
|
||||
val initialState = bob.stateData.asInstanceOf[DATA_NORMAL]
|
||||
sender.send(bob, CMD_FULFILL_HTLC(htlc.id, "00" * 32))
|
||||
sender.expectMsg(Failure(InvalidHtlcPreimage(0)))
|
||||
sender.expectMsg(Failure(InvalidHtlcPreimage(channelId(bob), 0)))
|
||||
assert(initialState == bob.stateData)
|
||||
}
|
||||
}
|
||||
@ -836,14 +836,14 @@ class NormalStateSpec extends TestkitBaseClass with StateTestsHelperMethods {
|
||||
}
|
||||
}
|
||||
|
||||
test("recv CMD_FAIL_HTLC (unknown htlc id)") { case (alice, bob, alice2bob, bob2alice, _, _, _) =>
|
||||
test("recv CMD_FAIL_HTLC (unknown htlc id)") { case (_, bob, _, _, _, _, _) =>
|
||||
within(30 seconds) {
|
||||
val sender = TestProbe()
|
||||
val r: BinaryData = "11" * 32
|
||||
val initialState = bob.stateData.asInstanceOf[DATA_NORMAL]
|
||||
|
||||
sender.send(bob, CMD_FAIL_HTLC(42, Right(PermanentChannelFailure)))
|
||||
sender.expectMsg(Failure(UnknownHtlcId(42)))
|
||||
sender.expectMsg(Failure(UnknownHtlcId(channelId(bob), 42)))
|
||||
assert(initialState == bob.stateData)
|
||||
}
|
||||
}
|
||||
@ -932,7 +932,7 @@ class NormalStateSpec extends TestkitBaseClass with StateTestsHelperMethods {
|
||||
val sender = TestProbe()
|
||||
val initialState = bob.stateData.asInstanceOf[DATA_NORMAL]
|
||||
sender.send(bob, CMD_UPDATE_FEE(20000))
|
||||
sender.expectMsg(Failure(FundeeCannotSendUpdateFee))
|
||||
sender.expectMsg(Failure(FundeeCannotSendUpdateFee(channelId(bob))))
|
||||
assert(initialState == bob.stateData)
|
||||
}
|
||||
}
|
||||
@ -967,7 +967,7 @@ class NormalStateSpec extends TestkitBaseClass with StateTestsHelperMethods {
|
||||
Globals.feeratePerKw.set(fee.feeratePerKw)
|
||||
sender.send(bob, fee)
|
||||
val error = bob2alice.expectMsgType[Error]
|
||||
assert(new String(error.data) === CannotAffordFees(missingSatoshis = 71620000L, reserveSatoshis = 20000L, feesSatoshis=72400000L).getMessage)
|
||||
assert(new String(error.data) === CannotAffordFees(channelId(bob), missingSatoshis = 71620000L, reserveSatoshis = 20000L, feesSatoshis=72400000L).getMessage)
|
||||
awaitCond(bob.stateName == CLOSING)
|
||||
bob2blockchain.expectMsg(PublishAsap(tx))
|
||||
bob2blockchain.expectMsgType[WatchConfirmed]
|
||||
@ -1004,15 +1004,15 @@ class NormalStateSpec extends TestkitBaseClass with StateTestsHelperMethods {
|
||||
val sender = TestProbe()
|
||||
val (r, htlc) = addHtlc(50000000, alice, bob, alice2bob, bob2alice)
|
||||
sender.send(alice, CMD_CLOSE(None))
|
||||
sender.expectMsg(Failure(CannotCloseWithPendingChanges))
|
||||
sender.expectMsg(Failure(CannotCloseWithPendingChanges(channelId(bob))))
|
||||
}
|
||||
}
|
||||
|
||||
test("recv CMD_CLOSE (with invalid final script)") { case (alice, bob, alice2bob, bob2alice, _, _, _) =>
|
||||
test("recv CMD_CLOSE (with invalid final script)") { case (alice, _, _, _, _, _, _) =>
|
||||
within(30 seconds) {
|
||||
val sender = TestProbe()
|
||||
sender.send(alice, CMD_CLOSE(Some(BinaryData("00112233445566778899"))))
|
||||
sender.expectMsg(Failure(InvalidFinalScript))
|
||||
sender.expectMsg(Failure(InvalidFinalScript(channelId(alice))))
|
||||
}
|
||||
}
|
||||
|
||||
@ -1029,7 +1029,7 @@ class NormalStateSpec extends TestkitBaseClass with StateTestsHelperMethods {
|
||||
}
|
||||
}
|
||||
|
||||
test("recv CMD_CLOSE (two in a row)") { case (alice, _, alice2bob, _, alice2blockchain, _, _) =>
|
||||
test("recv CMD_CLOSE (two in a row)") { case (alice, _, alice2bob, _, _, _, _) =>
|
||||
within(30 seconds) {
|
||||
val sender = TestProbe()
|
||||
awaitCond(alice.stateData.asInstanceOf[DATA_NORMAL].localShutdown.isEmpty)
|
||||
@ -1039,11 +1039,11 @@ class NormalStateSpec extends TestkitBaseClass with StateTestsHelperMethods {
|
||||
awaitCond(alice.stateName == NORMAL)
|
||||
awaitCond(alice.stateData.asInstanceOf[DATA_NORMAL].localShutdown.isDefined)
|
||||
sender.send(alice, CMD_CLOSE(None))
|
||||
sender.expectMsg(Failure(ClosingAlreadyInProgress))
|
||||
sender.expectMsg(Failure(ClosingAlreadyInProgress(channelId(alice))))
|
||||
}
|
||||
}
|
||||
|
||||
test("recv CMD_CLOSE (while waiting for a RevokeAndAck)") { case (alice, bob, alice2bob, bob2alice, alice2blockchain, _, _) =>
|
||||
test("recv CMD_CLOSE (while waiting for a RevokeAndAck)") { case (alice, bob, alice2bob, bob2alice, _, _, _) =>
|
||||
within(30 seconds) {
|
||||
val sender = TestProbe()
|
||||
val (r, htlc) = addHtlc(50000000, alice, bob, alice2bob, bob2alice)
|
||||
@ -1058,7 +1058,7 @@ class NormalStateSpec extends TestkitBaseClass with StateTestsHelperMethods {
|
||||
}
|
||||
}
|
||||
|
||||
test("recv Shutdown (no pending htlcs)") { case (alice, _, alice2bob, _, alice2blockchain, _, _) =>
|
||||
test("recv Shutdown (no pending htlcs)") { case (alice, _, alice2bob, _, _, _, _) =>
|
||||
within(30 seconds) {
|
||||
val sender = TestProbe()
|
||||
sender.send(alice, Shutdown("00" * 32, Bob.channelParams.defaultFinalScriptPubKey))
|
||||
@ -1068,7 +1068,7 @@ class NormalStateSpec extends TestkitBaseClass with StateTestsHelperMethods {
|
||||
}
|
||||
}
|
||||
|
||||
test("recv Shutdown (with unacked sent htlcs)") { case (alice, bob, alice2bob, bob2alice, alice2blockchain, _, _) =>
|
||||
test("recv Shutdown (with unacked sent htlcs)") { case (alice, bob, alice2bob, bob2alice, _, _, _) =>
|
||||
within(30 seconds) {
|
||||
val sender = TestProbe()
|
||||
val (r, htlc) = addHtlc(50000000, alice, bob, alice2bob, bob2alice)
|
||||
@ -1122,7 +1122,7 @@ class NormalStateSpec extends TestkitBaseClass with StateTestsHelperMethods {
|
||||
}
|
||||
}
|
||||
|
||||
test("recv Shutdown (with signed htlcs)") { case (alice, bob, alice2bob, bob2alice, alice2blockchain, _, _) =>
|
||||
test("recv Shutdown (with signed htlcs)") { case (alice, bob, alice2bob, bob2alice, _, _, _) =>
|
||||
within(30 seconds) {
|
||||
val sender = TestProbe()
|
||||
val (r, htlc) = addHtlc(50000000, alice, bob, alice2bob, bob2alice)
|
||||
@ -1135,7 +1135,7 @@ class NormalStateSpec extends TestkitBaseClass with StateTestsHelperMethods {
|
||||
}
|
||||
}
|
||||
|
||||
test("recv Shutdown (while waiting for a RevokeAndAck)") { case (alice, bob, alice2bob, bob2alice, alice2blockchain, _, _) =>
|
||||
test("recv Shutdown (while waiting for a RevokeAndAck)") { case (alice, bob, alice2bob, bob2alice, _, _, _) =>
|
||||
within(30 seconds) {
|
||||
val sender = TestProbe()
|
||||
val (r, htlc) = addHtlc(50000000, alice, bob, alice2bob, bob2alice)
|
||||
|
@ -88,27 +88,27 @@ class ShutdownStateSpec extends TestkitBaseClass with StateTestsHelperMethods {
|
||||
}
|
||||
}
|
||||
|
||||
test("recv CMD_FULFILL_HTLC (unknown htlc id)") { case (alice, bob, alice2bob, bob2alice, _, _) =>
|
||||
test("recv CMD_FULFILL_HTLC (unknown htlc id)") { case (_, bob, _, _, _, _) =>
|
||||
within(30 seconds) {
|
||||
val sender = TestProbe()
|
||||
val initialState = bob.stateData.asInstanceOf[DATA_SHUTDOWN]
|
||||
sender.send(bob, CMD_FULFILL_HTLC(42, "12" * 32))
|
||||
sender.expectMsg(Failure(UnknownHtlcId(42)))
|
||||
sender.expectMsg(Failure(UnknownHtlcId(channelId(bob), 42)))
|
||||
assert(initialState == bob.stateData)
|
||||
}
|
||||
}
|
||||
|
||||
test("recv CMD_FULFILL_HTLC (invalid preimage)") { case (alice, bob, alice2bob, bob2alice, _, _) =>
|
||||
test("recv CMD_FULFILL_HTLC (invalid preimage)") { case (_, bob, _, _, _, _) =>
|
||||
within(30 seconds) {
|
||||
val sender = TestProbe()
|
||||
val initialState = bob.stateData.asInstanceOf[DATA_SHUTDOWN]
|
||||
sender.send(bob, CMD_FULFILL_HTLC(1, "00" * 32))
|
||||
sender.expectMsg(Failure(InvalidHtlcPreimage(1)))
|
||||
sender.expectMsg(Failure(InvalidHtlcPreimage(channelId(bob), 1)))
|
||||
assert(initialState == bob.stateData)
|
||||
}
|
||||
}
|
||||
|
||||
test("recv UpdateFulfillHtlc") { case (alice, bob, alice2bob, bob2alice, _, _) =>
|
||||
test("recv UpdateFulfillHtlc") { case (alice, _, _, _, _, _) =>
|
||||
within(30 seconds) {
|
||||
val sender = TestProbe()
|
||||
val initialState = alice.stateData.asInstanceOf[DATA_SHUTDOWN]
|
||||
@ -118,7 +118,7 @@ class ShutdownStateSpec extends TestkitBaseClass with StateTestsHelperMethods {
|
||||
}
|
||||
}
|
||||
|
||||
test("recv UpdateFulfillHtlc (unknown htlc id)") { case (alice, bob, alice2bob, bob2alice, alice2blockchain, _) =>
|
||||
test("recv UpdateFulfillHtlc (unknown htlc id)") { case (alice, _, alice2bob, _, alice2blockchain, _) =>
|
||||
within(30 seconds) {
|
||||
val tx = alice.stateData.asInstanceOf[DATA_SHUTDOWN].commitments.localCommit.publishableTxs.commitTx.tx
|
||||
val sender = TestProbe()
|
||||
@ -131,7 +131,7 @@ class ShutdownStateSpec extends TestkitBaseClass with StateTestsHelperMethods {
|
||||
}
|
||||
}
|
||||
|
||||
test("recv UpdateFulfillHtlc (invalid preimage)") { case (alice, bob, alice2bob, bob2alice, alice2blockchain, _) =>
|
||||
test("recv UpdateFulfillHtlc (invalid preimage)") { case (alice, _, alice2bob, _, alice2blockchain, _) =>
|
||||
within(30 seconds) {
|
||||
val tx = alice.stateData.asInstanceOf[DATA_SHUTDOWN].commitments.localCommit.publishableTxs.commitTx.tx
|
||||
val sender = TestProbe()
|
||||
@ -169,17 +169,17 @@ class ShutdownStateSpec extends TestkitBaseClass with StateTestsHelperMethods {
|
||||
}
|
||||
}
|
||||
|
||||
test("recv CMD_FAIL_HTLC (unknown htlc id)") { case (alice, bob, alice2bob, bob2alice, _, _) =>
|
||||
test("recv CMD_FAIL_HTLC (unknown htlc id)") { case (_, bob, _, _, _, _) =>
|
||||
within(30 seconds) {
|
||||
val sender = TestProbe()
|
||||
val initialState = bob.stateData.asInstanceOf[DATA_SHUTDOWN]
|
||||
sender.send(bob, CMD_FAIL_HTLC(42, Right(PermanentChannelFailure)))
|
||||
sender.expectMsg(Failure(UnknownHtlcId(42)))
|
||||
sender.expectMsg(Failure(UnknownHtlcId(channelId(bob), 42)))
|
||||
assert(initialState == bob.stateData)
|
||||
}
|
||||
}
|
||||
|
||||
test("recv UpdateFailHtlc") { case (alice, bob, alice2bob, bob2alice, _, _) =>
|
||||
test("recv UpdateFailHtlc") { case (alice, _, _, _, _, _) =>
|
||||
within(30 seconds) {
|
||||
val sender = TestProbe()
|
||||
val initialState = alice.stateData.asInstanceOf[DATA_SHUTDOWN]
|
||||
@ -392,7 +392,7 @@ class ShutdownStateSpec extends TestkitBaseClass with StateTestsHelperMethods {
|
||||
val sender = TestProbe()
|
||||
val initialState = bob.stateData.asInstanceOf[DATA_SHUTDOWN]
|
||||
sender.send(bob, CMD_UPDATE_FEE(20000))
|
||||
sender.expectMsg(Failure(FundeeCannotSendUpdateFee))
|
||||
sender.expectMsg(Failure(FundeeCannotSendUpdateFee(channelId(bob))))
|
||||
assert(initialState == bob.stateData)
|
||||
}
|
||||
}
|
||||
@ -427,7 +427,7 @@ class ShutdownStateSpec extends TestkitBaseClass with StateTestsHelperMethods {
|
||||
Globals.feeratePerKw.set(fee.feeratePerKw)
|
||||
sender.send(bob, fee)
|
||||
val error = bob2alice.expectMsgType[Error]
|
||||
assert(new String(error.data) === CannotAffordFees(missingSatoshis = 72120000L, reserveSatoshis = 20000L, feesSatoshis = 72400000L).getMessage)
|
||||
assert(new String(error.data) === CannotAffordFees(channelId(bob), missingSatoshis = 72120000L, reserveSatoshis = 20000L, feesSatoshis = 72400000L).getMessage)
|
||||
awaitCond(bob.stateName == CLOSING)
|
||||
bob2blockchain.expectMsg(PublishAsap(tx))
|
||||
bob2blockchain.expectMsgType[WatchConfirmed]
|
||||
@ -635,11 +635,11 @@ class ShutdownStateSpec extends TestkitBaseClass with StateTestsHelperMethods {
|
||||
within(30 seconds) {
|
||||
val sender = TestProbe()
|
||||
sender.send(alice, CMD_CLOSE(None))
|
||||
sender.expectMsg(Failure(ClosingAlreadyInProgress))
|
||||
sender.expectMsg(Failure(ClosingAlreadyInProgress(channelId(alice))))
|
||||
}
|
||||
}
|
||||
|
||||
test("recv Error") { case (alice, bob, alice2bob, bob2alice, alice2blockchain, _) =>
|
||||
test("recv Error") { case (alice, _, _, _, alice2blockchain, _) =>
|
||||
within(30 seconds) {
|
||||
val aliceCommitTx = alice.stateData.asInstanceOf[DATA_SHUTDOWN].commitments.localCommit.publishableTxs.commitTx.tx
|
||||
alice ! Error("00" * 32, "oops".getBytes)
|
||||
|
@ -118,11 +118,11 @@ class NegotiatingStateSpec extends TestkitBaseClass with StateTestsHelperMethods
|
||||
within(30 seconds) {
|
||||
val sender = TestProbe()
|
||||
sender.send(alice, CMD_CLOSE(None))
|
||||
sender.expectMsg(Failure(ClosingAlreadyInProgress))
|
||||
sender.expectMsg(Failure(ClosingAlreadyInProgress(channelId(alice))))
|
||||
}
|
||||
}
|
||||
|
||||
test("recv Error") { case (alice, _, alice2bob, bob2alice, alice2blockchain, _) =>
|
||||
test("recv Error") { case (alice, _, _, _, alice2blockchain, _) =>
|
||||
within(30 seconds) {
|
||||
val tx = alice.stateData.asInstanceOf[DATA_NEGOTIATING].commitments.localCommit.publishableTxs.commitTx.tx
|
||||
alice ! Error("00" * 32, "oops".getBytes())
|
||||
|
@ -90,7 +90,7 @@ class ClosingStateSpec extends TestkitBaseClass with StateTestsHelperMethods {
|
||||
// actual test starts here
|
||||
val sender = TestProbe()
|
||||
sender.send(alice, CMD_FULFILL_HTLC(42, "42" * 32))
|
||||
sender.expectMsg(Failure(UnknownHtlcId(42)))
|
||||
sender.expectMsg(Failure(UnknownHtlcId(channelId(alice), 42)))
|
||||
|
||||
// NB: nominal case is tested in IntegrationSpec
|
||||
}
|
||||
@ -231,7 +231,7 @@ class ClosingStateSpec extends TestkitBaseClass with StateTestsHelperMethods {
|
||||
mutualClose(alice, bob, alice2bob, bob2alice, alice2blockchain, bob2blockchain)
|
||||
val sender = TestProbe()
|
||||
sender.send(alice, CMD_CLOSE(None))
|
||||
sender.expectMsg(Failure(ClosingAlreadyInProgress))
|
||||
sender.expectMsg(Failure(ClosingAlreadyInProgress(channelId(alice))))
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user