Skip to content

Commit

Permalink
Never serialize ActorRef (#2697)
Browse files Browse the repository at this point in the history
It turns out that #2688 broke the JSON serialization of the `channels`
API by introducing a new `ActorRef`. We never want to surface `ActorRef`
in JSON responses, so we're defining serializers to filter them out.

Co-authored-by: Fabrice Drouin <sstone@users.noreply.github.com>
  • Loading branch information
t-bast and sstone committed Jun 16, 2023
1 parent fe9f32b commit 3a351f4
Show file tree
Hide file tree
Showing 2 changed files with 143 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,14 @@ class ConvertClassSerializer[T: Manifest](f: T => Any) extends Serializer[Nothin
}
}

object ActorRefSerializer extends MinimalSerializer({
case _: akka.actor.ActorRef => JNothing
})

object TypedActorRefSerializer extends MinimalSerializer({
case _: akka.actor.typed.ActorRef[_] => JNothing
})

object ByteVectorSerializer extends MinimalSerializer({
case x: ByteVector => JString(x.toHex)
})
Expand Down Expand Up @@ -610,6 +618,8 @@ object JsonSerializers {
CustomTypeHints.channelStates +
CustomTypeHints.realScidStatuses +
CustomTypeHints.remoteFundingStatuses +
ActorRefSerializer +
TypedActorRefSerializer +
ByteVectorSerializer +
ByteVector32Serializer +
ByteVector64Serializer +
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,27 +17,31 @@
package fr.acinq.eclair.json

import akka.actor.ActorRef
import fr.acinq.bitcoin.scalacompat.Crypto.PublicKey
import fr.acinq.bitcoin.scalacompat.{Btc, ByteVector32, OutPoint, Satoshi, SatoshiLong, Transaction, TxOut}
import akka.testkit.TestProbe
import fr.acinq.bitcoin.scalacompat.Crypto.{PrivateKey, PublicKey}
import fr.acinq.bitcoin.scalacompat.{Block, Btc, ByteVector32, ByteVector64, DeterministicWallet, OutPoint, Satoshi, SatoshiLong, Transaction, TxOut}
import fr.acinq.eclair._
import fr.acinq.eclair.balance.CheckBalance
import fr.acinq.eclair.balance.CheckBalance.{ClosingBalance, GlobalBalance, MainAndHtlcBalance, PossiblyPublishedMainAndHtlcBalance, PossiblyPublishedMainBalance}
import fr.acinq.eclair.blockchain.fee.FeeratePerKw
import fr.acinq.eclair.channel.Helpers.Funding
import fr.acinq.eclair.channel._
import fr.acinq.eclair.crypto.ShaChain
import fr.acinq.eclair.io.Peer
import fr.acinq.eclair.io.Peer.PeerInfo
import fr.acinq.eclair.payment.{Invoice, PaymentSettlingOnChain}
import fr.acinq.eclair.transactions.Transactions._
import fr.acinq.eclair.transactions.{IncomingHtlc, OutgoingHtlc}
import fr.acinq.eclair.transactions.{CommitmentSpec, IncomingHtlc, OutgoingHtlc}
import fr.acinq.eclair.wire.internal.channel.ChannelCodecs
import fr.acinq.eclair.wire.protocol._
import org.scalatest.funsuite.AnyFunSuite
import org.scalatest.funsuite.AnyFunSuiteLike
import org.scalatest.matchers.should.Matchers
import scodec.bits._

import java.net.InetAddress
import java.util.UUID

class JsonSerializersSpec extends AnyFunSuite with Matchers {
class JsonSerializersSpec extends TestKitBaseClass with AnyFunSuiteLike with Matchers {

test("deserialize Map[OutPoint, ByteVector]") {
val output1 = OutPoint(ByteVector32(hex"11418a2d282a40461966e4f578e1fdf633ad15c1b7fb3e771d14361127233be1"), 0)
Expand Down Expand Up @@ -111,6 +115,130 @@ class JsonSerializersSpec extends AnyFunSuite with Matchers {
JsonSerializers.serialization.write(peerInfo)(JsonSerializers.formats) shouldBe expected
}

test("RES_GET_CHANNEL_INFO serialization") {
val probe = TestProbe()(system)
val dummyPublicKey = PrivateKey(hex"0101010101010101010101010101010101010101010101010101010101010101").publicKey
val dummyBytes32 = ByteVector32(hex"0202020202020202020202020202020202020202020202020202020202020202")
val localParams = LocalParams(dummyPublicKey, DeterministicWallet.KeyPath(Seq(42L)), 546 sat, Long.MaxValue.msat, Some(1000 sat), 1 msat, CltvExpiryDelta(144), 50, isInitiator = true, None, None, Features.empty)
val remoteParams = RemoteParams(dummyPublicKey, 546 sat, UInt64.MaxValue, Some(1000 sat), 1 msat, CltvExpiryDelta(144), 50, dummyPublicKey, dummyPublicKey, dummyPublicKey, dummyPublicKey, Features.empty, None)
val commitmentInput = Funding.makeFundingInputInfo(dummyBytes32, 0, 150_000 sat, dummyPublicKey, dummyPublicKey)
val localCommit = LocalCommit(0, CommitmentSpec(Set.empty, FeeratePerKw(2500 sat), 100_000_000 msat, 50_000_000 msat), CommitTxAndRemoteSig(CommitTx(commitmentInput, Transaction(2, Nil, Nil, 0)), ByteVector64.Zeroes), Nil)
val remoteCommit = RemoteCommit(0, CommitmentSpec(Set.empty, FeeratePerKw(2500 sat), 50_000_000 msat, 100_000_000 msat), dummyBytes32, dummyPublicKey)
val channelInfo = RES_GET_CHANNEL_INFO(
PublicKey(hex"0270685ca81a8e4d4d01beec5781f4cc924684072ae52c507f8ebe9daf0caaab7b"),
ByteVector32(hex"345b2b05ec046ffe0c14d3b61838c79980713ad1cf8ae7a45c172ce90c9c0b9f"),
probe.ref,
NORMAL,
DATA_NORMAL(
Commitments(
ChannelParams(dummyBytes32, ChannelConfig.standard, ChannelFeatures(), localParams, remoteParams, ChannelFlags(announceChannel = true)),
CommitmentChanges(LocalChanges(Nil, Nil, Nil), RemoteChanges(Nil, Nil, Nil), localNextHtlcId = 1, remoteNextHtlcId = 1),
List(Commitment(0, dummyPublicKey, LocalFundingStatus.SingleFundedUnconfirmedFundingTx(None), RemoteFundingStatus.Locked, localCommit, remoteCommit, None)),
inactive = Nil,
Right(dummyPublicKey),
ShaChain.init,
Map.empty,
),
ShortIds(RealScidStatus.Unknown, Alias(42), None),
None,
ChannelUpdate(ByteVector64(hex"345b2b05ec046ffe0c14d3b61838c79980713ad1cf8ae7a45c172ce90c9c0b9f345b2b05ec046ffe0c14d3b61838c79980713ad1cf8ae7a45c172ce90c9c0b9f"), Block.RegtestGenesisBlock.hash, ShortChannelId(0), 0 unixsec, ChannelUpdate.MessageFlags(dontForward = false), ChannelUpdate.ChannelFlags.DUMMY, CltvExpiryDelta(12), 1 msat, 100 msat, 0, 2_000_000 msat),
None, None, None, SpliceStatus.NoSplice
)
)
val expected =
"""{
| "nodeId": "0270685ca81a8e4d4d01beec5781f4cc924684072ae52c507f8ebe9daf0caaab7b",
| "channelId": "345b2b05ec046ffe0c14d3b61838c79980713ad1cf8ae7a45c172ce90c9c0b9f",
| "state": "NORMAL",
| "data": {
| "type": "DATA_NORMAL",
| "commitments": {
| "params": {
| "channelId": "0202020202020202020202020202020202020202020202020202020202020202",
| "channelConfig": ["funding_pubkey_based_channel_keypath"],
| "channelFeatures": [],
| "localParams": {
| "nodeId": "031b84c5567b126440995d3ed5aaba0565d71e1834604819ff9c17f5e9d5dd078f",
| "fundingKeyPath": [42],
| "dustLimit": 546,
| "maxHtlcValueInFlightMsat": 9223372036854775807,
| "requestedChannelReserve_opt": 1000,
| "htlcMinimum": 1,
| "toSelfDelay": 144,
| "maxAcceptedHtlcs": 50,
| "isInitiator": true,
| "initFeatures": { "activated": {}, "unknown": [] }
| },
| "remoteParams": {
| "nodeId": "031b84c5567b126440995d3ed5aaba0565d71e1834604819ff9c17f5e9d5dd078f",
| "dustLimit": 546,
| "maxHtlcValueInFlightMsat": 18446744073709551615,
| "requestedChannelReserve_opt": 1000,
| "htlcMinimum": 1,
| "toSelfDelay": 144,
| "maxAcceptedHtlcs": 50,
| "revocationBasepoint": "031b84c5567b126440995d3ed5aaba0565d71e1834604819ff9c17f5e9d5dd078f",
| "paymentBasepoint": "031b84c5567b126440995d3ed5aaba0565d71e1834604819ff9c17f5e9d5dd078f",
| "delayedPaymentBasepoint": "031b84c5567b126440995d3ed5aaba0565d71e1834604819ff9c17f5e9d5dd078f",
| "htlcBasepoint": "031b84c5567b126440995d3ed5aaba0565d71e1834604819ff9c17f5e9d5dd078f",
| "initFeatures": { "activated": {}, "unknown": [] }
| },
| "channelFlags": {
| "announceChannel": true
| }
| },
| "changes": {
| "localChanges": { "proposed": [], "signed": [], "acked": [] },
| "remoteChanges": { "proposed": [], "acked": [], "signed": [] },
| "localNextHtlcId": 1,
| "remoteNextHtlcId": 1
| },
| "active": [
| {
| "fundingTxIndex": 0,
| "fundingTx": { "outPoint": "0202020202020202020202020202020202020202020202020202020202020202:0", "amountSatoshis": 150000 },
| "localFunding": { "status":"unconfirmed" },
| "remoteFunding": { "status":"locked" },
| "localCommit": {
| "index": 0,
| "spec": { "htlcs": [], "commitTxFeerate": 2500, "toLocal": 100000000, "toRemote": 50000000 },
| "commitTxAndRemoteSig": { "commitTx": { "txid": "4ebd325a4b394cff8c57e8317ccf5a8d0e2bdf1b8526f8aad6c8e43d8240621a", "tx": "02000000000000000000" },"remoteSig": "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" },
| "htlcTxsAndRemoteSigs": []
| },
| "remoteCommit": {
| "index": 0,
| "spec": { "htlcs": [], "commitTxFeerate": 2500, "toLocal": 50000000, "toRemote": 100000000 },
| "txid": "0202020202020202020202020202020202020202020202020202020202020202",
| "remotePerCommitmentPoint": "031b84c5567b126440995d3ed5aaba0565d71e1834604819ff9c17f5e9d5dd078f"
| }
| }
| ],
| "inactive": [],
| "remoteNextCommitInfo": "031b84c5567b126440995d3ed5aaba0565d71e1834604819ff9c17f5e9d5dd078f",
| "remotePerCommitmentSecrets": null,
| "originChannels": {}
| },
| "shortIds": { "real": { "status": "unknown" }, "localAlias": "0x2a" },
| "channelUpdate": {
| "signature": "345b2b05ec046ffe0c14d3b61838c79980713ad1cf8ae7a45c172ce90c9c0b9f345b2b05ec046ffe0c14d3b61838c79980713ad1cf8ae7a45c172ce90c9c0b9f",
| "chainHash": "06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f",
| "shortChannelId": "0x0x0",
| "timestamp": { "iso": "1970-01-01T00:00:00Z", "unix": 0 },
| "messageFlags": { "dontForward": false },
| "channelFlags": { "isEnabled": true, "isNode1": true },
| "cltvExpiryDelta": 12,
| "htlcMinimumMsat": 1,
| "feeBaseMsat": 100,
| "feeProportionalMillionths": 0,
| "htlcMaximumMsat": 2000000,
| "tlvStream": {}
| }
| }
|}""".stripMargin
val json = JsonSerializers.serialization.write(channelInfo)(JsonSerializers.formats)
assertJsonEquals(json, expected)
}

test("DirectedHtlc serialization") {
val add = UpdateAddHtlc(
channelId = ByteVector32(hex"345b2b05ec046ffe0c14d3b61838c79980713ad1cf8ae7a45c172ce90c9c0b9f"),
Expand Down

0 comments on commit 3a351f4

Please sign in to comment.