diff --git a/eclair-core/src/main/scala/fr/acinq/eclair/api/JsonSerializers.scala b/eclair-core/src/main/scala/fr/acinq/eclair/api/JsonSerializers.scala index 2200d95416..a1a586941f 100644 --- a/eclair-core/src/main/scala/fr/acinq/eclair/api/JsonSerializers.scala +++ b/eclair-core/src/main/scala/fr/acinq/eclair/api/JsonSerializers.scala @@ -82,7 +82,7 @@ class PrivateKeySerializer extends CustomSerializer[PrivateKey](format => ({ nul })) class ChannelVersionSerializer extends CustomSerializer[ChannelVersion](format => ({ null }, { - case x: ChannelVersion => JString(x.toString) + case x: ChannelVersion => JString(x.bits.toBin) })) class TransactionSerializer extends CustomSerializer[TransactionWithInputInfo](ser = format => ({ null }, { 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 4cfbf66c53..4ce00a554e 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 @@ -19,14 +19,14 @@ package fr.acinq.eclair.channel import java.util.UUID import akka.actor.ActorRef -import fr.acinq.bitcoin.Crypto.{PublicKey} +import fr.acinq.bitcoin.Crypto.PublicKey import fr.acinq.bitcoin.{ByteVector32, DeterministicWallet, OutPoint, Satoshi, Transaction} import fr.acinq.eclair.crypto.Sphinx 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, OpenChannel, Shutdown, UpdateAddHtlc} import fr.acinq.eclair.{ShortChannelId, UInt64} -import scodec.bits.ByteVector +import scodec.bits.{BitVector, ByteVector} /** @@ -223,8 +223,11 @@ object ChannelFlags { val Empty = 0x00.toByte } -sealed trait ChannelVersion +case class ChannelVersion(bits: BitVector) { + require(bits.size == ChannelVersion.LENGTH_BITS, "channel version takes 4 bytes") +} object ChannelVersion { - case object STANDARD extends ChannelVersion + val LENGTH_BITS = 4 * 8 + val STANDARD = ChannelVersion(BitVector.fill(LENGTH_BITS)(false)) } // @formatter:on 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 f54e147fed..97937c05de 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 @@ -52,7 +52,7 @@ object ChannelCodecs extends Logging { val channelVersionCodec: Codec[ChannelVersion] = discriminatorWithDefault[ChannelVersion]( discriminator = discriminated[ChannelVersion].by(byte) - .typecase(0x01, provide(ChannelVersion.STANDARD)) + .typecase(0x01, bits(ChannelVersion.LENGTH_BITS).as[ChannelVersion]) // NB: 0x02 and 0x03 are *reserved* for backward compatibility reasons , fallback = provide(ChannelVersion.STANDARD) 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 c147cf1a1e..c5ba94558b 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 @@ -68,15 +68,15 @@ class ChannelCodecsSpec extends FunSuite { // before we had commitment version, public keys were stored first (they started with 0x02 and 0x03) val legacy02 = hex"02a06ea3081f0f7a8ce31eb4f0822d10d2da120d5a1b1451f0727f51c7372f0f9b" val legacy03 = hex"03d5c030835d6a6248b2d1d4cac60813838011b995a66b6f78dcc9fb8b5c40c3f3" - val current02 = hex"0102a06ea3081f0f7a8ce31eb4f0822d10d2da120d5a1b1451f0727f51c7372f0f9b" - val current03 = hex"0103d5c030835d6a6248b2d1d4cac60813838011b995a66b6f78dcc9fb8b5c40c3f3" + val current02 = hex"010000000002a06ea3081f0f7a8ce31eb4f0822d10d2da120d5a1b1451f0727f51c7372f0f9b" + val current03 = hex"010000000003d5c030835d6a6248b2d1d4cac60813838011b995a66b6f78dcc9fb8b5c40c3f3" assert(channelVersionCodec.decode(legacy02.bits) === Attempt.successful(DecodeResult(ChannelVersion.STANDARD, legacy02.bits))) assert(channelVersionCodec.decode(legacy03.bits) === Attempt.successful(DecodeResult(ChannelVersion.STANDARD, legacy03.bits))) - assert(channelVersionCodec.decode(current02.bits) === Attempt.successful(DecodeResult(ChannelVersion.STANDARD, current02.drop(1).bits))) - assert(channelVersionCodec.decode(current03.bits) === Attempt.successful(DecodeResult(ChannelVersion.STANDARD, current03.drop(1).bits))) + assert(channelVersionCodec.decode(current02.bits) === Attempt.successful(DecodeResult(ChannelVersion.STANDARD, current02.drop(5).bits))) + assert(channelVersionCodec.decode(current03.bits) === Attempt.successful(DecodeResult(ChannelVersion.STANDARD, current03.drop(5).bits))) - assert(channelVersionCodec.encode(ChannelVersion.STANDARD) === Attempt.successful(hex"01".bits)) + assert(channelVersionCodec.encode(ChannelVersion.STANDARD) === Attempt.successful(hex"0100000000".bits)) } test("encode/decode localparams") { @@ -312,8 +312,8 @@ class ChannelCodecsSpec extends FunSuite { // and we decode with the new codec val newnormal = stateDataCodec.decode(newbin.bits).require.value // finally we check that the actual data is the same as before (we just remove the new json field) - val oldjson = Serialization.write(oldnormal)(JsonSupport.formats).replace(""","unknownFields":""""", "").replace(""""channelVersion":"STANDARD",""", "") - val newjson = Serialization.write(newnormal)(JsonSupport.formats).replace(""","unknownFields":""""", "").replace(""""channelVersion":"STANDARD",""", "") + val oldjson = Serialization.write(oldnormal)(JsonSupport.formats).replace(""","unknownFields":""""", "").replace(""""channelVersion":"00000000000000000000000000000000",""", "") + val newjson = Serialization.write(newnormal)(JsonSupport.formats).replace(""","unknownFields":""""", "").replace(""""channelVersion":"00000000000000000000000000000000",""", "") assert(oldjson === refjson) assert(newjson === refjson) }