mirror of
https://github.com/ACINQ/eclair.git
synced 2024-11-20 10:39:19 +01:00
Fix encoding of failure messages (#366)
* Fix encoding of failure messages (fixes #363) When a failure message includes a channel update field, this field must be encoded as: [ len | channel update] and we did not include the len field. * add `ExpiryTooFar` failure message
This commit is contained in:
parent
0781eb7a40
commit
065de8bb5c
@ -39,6 +39,7 @@ case object IncorrectPaymentAmount extends Perm
|
||||
case object FinalExpiryTooSoon extends FailureMessage
|
||||
case class FinalIncorrectCltvExpiry(expiry: Long) extends FailureMessage
|
||||
case class FinalIncorrectHtlcAmount(amountMsat: Long) extends FailureMessage
|
||||
case object ExpiryTooFar extends FailureMessage
|
||||
// @formatter:on
|
||||
|
||||
object FailureMessageCodecs {
|
||||
@ -49,6 +50,8 @@ object FailureMessageCodecs {
|
||||
|
||||
val sha256Codec: Codec[BinaryData] = ("sha256Codec" | binarydata(32))
|
||||
|
||||
val channelUpdateWithLengthCodec = variableSizeBytes(uint16, channelUpdateCodec)
|
||||
|
||||
val failureMessageCodec = discriminated[FailureMessage].by(uint16)
|
||||
.typecase(PERM | 1, provide(InvalidRealm))
|
||||
.typecase(NODE | 2, provide(TemporaryNodeFailure))
|
||||
@ -57,18 +60,19 @@ object FailureMessageCodecs {
|
||||
.typecase(BADONION | PERM | 4, sha256Codec.as[InvalidOnionVersion])
|
||||
.typecase(BADONION | PERM | 5, sha256Codec.as[InvalidOnionHmac])
|
||||
.typecase(BADONION | PERM | 6, sha256Codec.as[InvalidOnionKey])
|
||||
.typecase(UPDATE | 7, (("channelUpdate" | channelUpdateCodec)).as[TemporaryChannelFailure])
|
||||
.typecase(UPDATE | 7, (("channelUpdate" | channelUpdateWithLengthCodec)).as[TemporaryChannelFailure])
|
||||
.typecase(PERM | 8, provide(PermanentChannelFailure))
|
||||
.typecase(PERM | 9, provide(RequiredChannelFeatureMissing))
|
||||
.typecase(PERM | 10, provide(UnknownNextPeer))
|
||||
.typecase(UPDATE | 11, (("amountMsat" | uint64) :: ("channelUpdate" | channelUpdateCodec)).as[AmountBelowMinimum])
|
||||
.typecase(UPDATE | 12, (("amountMsat" | uint64) :: ("channelUpdate" | channelUpdateCodec)).as[FeeInsufficient])
|
||||
.typecase(UPDATE | 13, (("expiry" | uint32) :: ("channelUpdate" | channelUpdateCodec)).as[IncorrectCltvExpiry])
|
||||
.typecase(UPDATE | 14, (("channelUpdate" | channelUpdateCodec)).as[ExpiryTooSoon])
|
||||
.typecase(UPDATE | 20, (("flags" | binarydata(2)) :: ("channelUpdate" | channelUpdateCodec)).as[ChannelDisabled])
|
||||
.typecase(UPDATE | 11, (("amountMsat" | uint64) :: ("channelUpdate" | channelUpdateWithLengthCodec)).as[AmountBelowMinimum])
|
||||
.typecase(UPDATE | 12, (("amountMsat" | uint64) :: ("channelUpdate" | channelUpdateWithLengthCodec)).as[FeeInsufficient])
|
||||
.typecase(UPDATE | 13, (("expiry" | uint32) :: ("channelUpdate" | channelUpdateWithLengthCodec)).as[IncorrectCltvExpiry])
|
||||
.typecase(UPDATE | 14, (("channelUpdate" | channelUpdateWithLengthCodec)).as[ExpiryTooSoon])
|
||||
.typecase(UPDATE | 20, (("flags" | binarydata(2)) :: ("channelUpdate" | channelUpdateWithLengthCodec)).as[ChannelDisabled])
|
||||
.typecase(PERM | 15, provide(UnknownPaymentHash))
|
||||
.typecase(PERM | 16, provide(IncorrectPaymentAmount))
|
||||
.typecase(17, provide(FinalExpiryTooSoon))
|
||||
.typecase(18, (("expiry" | uint32)).as[FinalIncorrectCltvExpiry])
|
||||
.typecase(19, (("amountMsat" | uint32)).as[FinalIncorrectHtlcAmount])
|
||||
.typecase(21, provide(ExpiryTooFar))
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
package fr.acinq.eclair.wire
|
||||
|
||||
import fr.acinq.bitcoin.BinaryData
|
||||
import fr.acinq.bitcoin.{BinaryData, Block}
|
||||
import org.junit.runner.RunWith
|
||||
import org.scalatest.FunSuite
|
||||
import org.scalatest.junit.JUnitRunner
|
||||
@ -12,6 +12,16 @@ import scala.util.Random
|
||||
*/
|
||||
@RunWith(classOf[JUnitRunner])
|
||||
class FailureMessageLightningMessageCodecsSpec extends FunSuite {
|
||||
val channelUpdate = ChannelUpdate(
|
||||
signature = BinaryData("3045022100c451cd65c88f55b1767941a247e849e12f5f4d4a93a07316659e22f5267d2088022009042a595c6bc8942cd9d729317b82b306edc259fb6b3a3cecb3dd1bd446e90601"),
|
||||
chainHash = Block.RegtestGenesisBlock.hash,
|
||||
shortChannelId = 12345,
|
||||
timestamp = 1234567L,
|
||||
cltvExpiryDelta = 100,
|
||||
flags = BinaryData("0001"),
|
||||
htlcMinimumMsat = 1000,
|
||||
feeBaseMsat = 12,
|
||||
feeProportionalMillionths = 76)
|
||||
|
||||
def randomBytes(size: Int): BinaryData = {
|
||||
val bin = new Array[Byte](size)
|
||||
@ -20,14 +30,12 @@ class FailureMessageLightningMessageCodecsSpec extends FunSuite {
|
||||
}
|
||||
|
||||
test("encode/decode all channel messages") {
|
||||
|
||||
val invalidRealm = InvalidRealm
|
||||
val temporaryNodeFailure = TemporaryNodeFailure
|
||||
val permanentNodeFailure = PermanentNodeFailure
|
||||
|
||||
|
||||
val msgs: List[FailureMessage] =
|
||||
invalidRealm :: temporaryNodeFailure :: permanentNodeFailure :: Nil
|
||||
InvalidRealm :: TemporaryNodeFailure :: PermanentNodeFailure :: RequiredNodeFeatureMissing ::
|
||||
InvalidOnionVersion(randomBytes(32)) :: InvalidOnionHmac(randomBytes(32)) :: InvalidOnionKey(randomBytes(32)) ::
|
||||
TemporaryChannelFailure(channelUpdate) :: PermanentChannelFailure :: RequiredChannelFeatureMissing :: UnknownNextPeer ::
|
||||
AmountBelowMinimum(123456, channelUpdate) :: FeeInsufficient(546463, channelUpdate) :: IncorrectCltvExpiry(1211, channelUpdate) :: ExpiryTooSoon(channelUpdate) ::
|
||||
UnknownPaymentHash :: IncorrectPaymentAmount :: FinalExpiryTooSoon :: FinalIncorrectCltvExpiry(1234) :: ChannelDisabled(BinaryData("0101"), channelUpdate) :: ExpiryTooFar :: Nil
|
||||
|
||||
msgs.foreach {
|
||||
case msg => {
|
||||
@ -37,5 +45,4 @@ class FailureMessageLightningMessageCodecsSpec extends FunSuite {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user