@@ -18,20 +18,19 @@ package fr.acinq.eclair.reputation
18
18
19
19
import akka .actor .testkit .typed .scaladsl .{ScalaTestWithActorTestKit , TestProbe }
20
20
import akka .actor .typed .ActorRef
21
+ import akka .actor .typed .eventstream .EventStream
21
22
import com .typesafe .config .ConfigFactory
22
23
import fr .acinq .bitcoin .scalacompat .Crypto .PublicKey
23
- import fr .acinq .eclair .channel .Upstream
24
+ import fr .acinq .eclair .channel .{ OutgoingHtlcAdded , OutgoingHtlcFailed , OutgoingHtlcFulfilled , Upstream }
24
25
import fr .acinq .eclair .reputation .ReputationRecorder ._
25
- import fr .acinq .eclair .wire .protocol .UpdateAddHtlc
26
- import fr .acinq .eclair .{MilliSatoshiLong , randomKey }
26
+ import fr .acinq .eclair .wire .protocol .{ TlvStream , UpdateAddHtlc , UpdateAddHtlcTlv , UpdateFailHtlc , UpdateFulfillHtlc }
27
+ import fr .acinq .eclair .{CltvExpiry , MilliSatoshi , MilliSatoshiLong , TimestampMilli , randomBytes , randomBytes32 , randomKey , randomLong }
27
28
import org .scalatest .Outcome
28
29
import org .scalatest .funsuite .FixtureAnyFunSuiteLike
29
30
30
- import java .util .UUID
31
31
import scala .concurrent .duration .DurationInt
32
32
33
33
class ReputationRecorderSpec extends ScalaTestWithActorTestKit (ConfigFactory .load(" application" )) with FixtureAnyFunSuiteLike {
34
- val (uuid1, uuid2, uuid3, uuid4, uuid5, uuid6, uuid7, uuid8) = (UUID .randomUUID(), UUID .randomUUID(), UUID .randomUUID(), UUID .randomUUID(), UUID .randomUUID(), UUID .randomUUID(), UUID .randomUUID(), UUID .randomUUID())
35
34
val originNode : PublicKey = randomKey().publicKey
36
35
37
36
case class FixtureParam (config : Reputation .Config , reputationRecorder : ActorRef [Command ], replyTo : TestProbe [Confidence ])
@@ -43,56 +42,107 @@ class ReputationRecorderSpec extends ScalaTestWithActorTestKit(ConfigFactory.loa
43
42
withFixture(test.toNoArgTest(FixtureParam (config, reputationRecorder.ref, replyTo)))
44
43
}
45
44
45
+ def makeChannelUpstream (nodeId : PublicKey , endorsement : Int , amount : MilliSatoshi = 1000000 msat): Upstream .Hot .Channel =
46
+ Upstream .Hot .Channel (UpdateAddHtlc (randomBytes32(), randomLong(), amount, randomBytes32(), CltvExpiry (1234 ), null , TlvStream (UpdateAddHtlcTlv .Endorsement (endorsement))), TimestampMilli .now(), nodeId)
47
+
48
+ def makeOutgoingHtlcAdded (upstream : Upstream .Hot , fee : MilliSatoshi ): OutgoingHtlcAdded =
49
+ OutgoingHtlcAdded (UpdateAddHtlc (randomBytes32(), randomLong(), 100000 msat, randomBytes32(), CltvExpiry (456 ), null , TlvStream .empty), upstream, fee)
50
+
51
+ def makeOutgoingHtlcFulfilled (add : UpdateAddHtlc ): OutgoingHtlcFulfilled =
52
+ OutgoingHtlcFulfilled (UpdateFulfillHtlc (add.channelId, add.id, randomBytes32(), TlvStream .empty))
53
+
54
+ def makeOutgoingHtlcFailed (add : UpdateAddHtlc ): OutgoingHtlcFailed =
55
+ OutgoingHtlcFailed (UpdateFailHtlc (add.channelId, add.id, randomBytes(100 ), TlvStream .empty))
56
+
46
57
test(" channel relay" ) { f =>
47
58
import f ._
48
59
49
- reputationRecorder ! GetConfidence (replyTo.ref, originNode, 7 , uuid1, 2000 msat)
60
+ val listener = TestProbe [Any ]()
61
+ testKit.system.eventStream ! EventStream .Subscribe (listener.ref)
62
+ testKit.system.eventStream ! EventStream .Subscribe (listener.ref)
63
+ testKit.system.eventStream ! EventStream .Subscribe (listener.ref)
64
+
65
+ val upstream1 = makeChannelUpstream(originNode, 7 )
66
+ reputationRecorder ! GetConfidence (replyTo.ref, upstream1, 2000 msat)
50
67
assert(replyTo.expectMessageType[Confidence ].value == 0 )
51
- reputationRecorder ! RecordResult (originNode, 7 , uuid1, isSuccess = true )
52
- reputationRecorder ! GetConfidence (replyTo.ref, originNode, 7 , uuid2, 1000 msat)
68
+ val added1 = makeOutgoingHtlcAdded(upstream1, 2000 msat)
69
+ testKit.system.eventStream ! EventStream .Publish (added1)
70
+ testKit.system.eventStream ! EventStream .Publish (makeOutgoingHtlcFulfilled(added1.add))
71
+ listener.expectMessageType[OutgoingHtlcAdded ]
72
+ listener.expectMessageType[OutgoingHtlcFulfilled ]
73
+ val upstream2 = makeChannelUpstream(originNode, 7 )
74
+ reputationRecorder ! GetConfidence (replyTo.ref, upstream2, 1000 msat)
53
75
assert(replyTo.expectMessageType[Confidence ].value === (2.0 / 4 ) +- 0.001 )
54
- reputationRecorder ! GetConfidence (replyTo.ref, originNode, 7 , uuid3, 3000 msat)
76
+ val added2 = makeOutgoingHtlcAdded(upstream2, 1000 msat)
77
+ testKit.system.eventStream ! EventStream .Publish (added2)
78
+ listener.expectMessageType[OutgoingHtlcAdded ]
79
+ reputationRecorder ! GetConfidence (replyTo.ref, makeChannelUpstream(originNode, 7 ), 3000 msat)
55
80
assert(replyTo.expectMessageType[Confidence ].value === (2.0 / 10 ) +- 0.001 )
56
- reputationRecorder ! CancelRelay (originNode, 7 , uuid3 )
57
- reputationRecorder ! GetConfidence (replyTo.ref, originNode, 7 , uuid4 , 1000 msat)
81
+ val upstream3 = makeChannelUpstream (originNode, 7 )
82
+ reputationRecorder ! GetConfidence (replyTo.ref, upstream3 , 1000 msat)
58
83
assert(replyTo.expectMessageType[Confidence ].value === (2.0 / 6 ) +- 0.001 )
59
- reputationRecorder ! RecordResult (originNode, 7 , uuid4, isSuccess = true )
60
- reputationRecorder ! RecordResult (originNode, 7 , uuid2, isSuccess = false )
84
+ val added3 = makeOutgoingHtlcAdded(upstream3, 1000 msat)
85
+ testKit.system.eventStream ! EventStream .Publish (added3)
86
+ testKit.system.eventStream ! EventStream .Publish (makeOutgoingHtlcFulfilled(added3.add))
87
+ testKit.system.eventStream ! EventStream .Publish (makeOutgoingHtlcFailed(added2.add))
88
+ listener.expectMessageType[OutgoingHtlcAdded ]
89
+ listener.expectMessageType[OutgoingHtlcFulfilled ]
90
+ listener.expectMessageType[OutgoingHtlcFailed ]
61
91
// Not endorsed
62
- reputationRecorder ! GetConfidence (replyTo.ref, originNode, 0 , uuid5 , 1000 msat)
92
+ reputationRecorder ! GetConfidence (replyTo.ref, makeChannelUpstream( originNode, 0 ) , 1000 msat)
63
93
assert(replyTo.expectMessageType[Confidence ].value == 0 )
64
94
// Different origin node
65
- reputationRecorder ! GetConfidence (replyTo.ref, randomKey().publicKey, 7 , uuid6 , 1000 msat)
95
+ reputationRecorder ! GetConfidence (replyTo.ref, makeChannelUpstream( randomKey().publicKey, 7 ) , 1000 msat)
66
96
assert(replyTo.expectMessageType[Confidence ].value == 0 )
67
97
// Very large HTLC
68
- reputationRecorder ! GetConfidence (replyTo.ref, originNode, 7 , uuid5 , 100000000 msat)
98
+ reputationRecorder ! GetConfidence (replyTo.ref, makeChannelUpstream( originNode, 7 ) , 100000000 msat)
69
99
assert(replyTo.expectMessageType[Confidence ].value === 0.0 +- 0.001 )
70
100
}
71
101
72
102
test(" trampoline relay" ) { f =>
73
103
import f ._
74
104
105
+ val listener = TestProbe [Any ]()
106
+ testKit.system.eventStream ! EventStream .Subscribe (listener.ref)
107
+ testKit.system.eventStream ! EventStream .Subscribe (listener.ref)
108
+ testKit.system.eventStream ! EventStream .Subscribe (listener.ref)
109
+
75
110
val (a, b, c) = (randomKey().publicKey, randomKey().publicKey, randomKey().publicKey)
76
111
77
- reputationRecorder ! GetTrampolineConfidence (replyTo.ref, Map (PeerEndorsement (a, 7 ) -> 2000 .msat, PeerEndorsement (b, 7 ) -> 4000 .msat, PeerEndorsement (c, 0 ) -> 6000 .msat), uuid1)
112
+ val upstream1 = Upstream .Hot .Trampoline (makeChannelUpstream(a, 7 , 20000 msat) :: makeChannelUpstream(b, 7 , 40000 msat) :: makeChannelUpstream(c, 0 , 60000 msat) :: Nil )
113
+ reputationRecorder ! GetTrampolineConfidence (replyTo.ref, upstream1, 12000 msat)
78
114
assert(replyTo.expectMessageType[Confidence ].value == 0 )
79
- reputationRecorder ! RecordTrampolineSuccess (Map (PeerEndorsement (a, 7 ) -> 1000 .msat, PeerEndorsement (b, 7 ) -> 2000 .msat, PeerEndorsement (c, 0 ) -> 3000 .msat), uuid1)
80
- reputationRecorder ! GetTrampolineConfidence (replyTo.ref, Map (PeerEndorsement (a, 7 ) -> 1000 .msat, PeerEndorsement (c, 0 ) -> 1000 .msat), uuid2)
115
+ val added1 = makeOutgoingHtlcAdded(upstream1, 6000 msat)
116
+ testKit.system.eventStream ! EventStream .Publish (added1)
117
+ testKit.system.eventStream ! EventStream .Publish (makeOutgoingHtlcFulfilled(added1.add))
118
+ listener.expectMessageType[OutgoingHtlcAdded ]
119
+ listener.expectMessageType[OutgoingHtlcFulfilled ]
120
+ val upstream2 = Upstream .Hot .Trampoline (makeChannelUpstream(a, 7 , 10000 msat) :: makeChannelUpstream(c, 0 , 10000 msat) :: Nil )
121
+ reputationRecorder ! GetTrampolineConfidence (replyTo.ref, upstream2, 2000 msat)
81
122
assert(replyTo.expectMessageType[Confidence ].value === (1.0 / 3 ) +- 0.001 )
82
- reputationRecorder ! GetTrampolineConfidence (replyTo.ref, Map (PeerEndorsement (a, 0 ) -> 1000 .msat, PeerEndorsement (b, 7 ) -> 2000 .msat), uuid3)
123
+ val added2 = makeOutgoingHtlcAdded(upstream2, 2000 msat)
124
+ testKit.system.eventStream ! EventStream .Publish (added2)
125
+ listener.expectMessageType[OutgoingHtlcAdded ]
126
+ val upstream3 = Upstream .Hot .Trampoline (makeChannelUpstream(a, 0 , 10000 msat) :: makeChannelUpstream(b, 7 , 20000 msat) :: Nil )
127
+ reputationRecorder ! GetTrampolineConfidence (replyTo.ref, upstream3, 3000 msat)
83
128
assert(replyTo.expectMessageType[Confidence ].value == 0 )
84
- reputationRecorder ! RecordTrampolineFailure (Set (PeerEndorsement (a, 7 ), PeerEndorsement (c, 0 )), uuid2)
85
- reputationRecorder ! RecordTrampolineSuccess (Map (PeerEndorsement (a, 0 ) -> 1000 .msat, PeerEndorsement (b, 7 ) -> 2000 .msat), uuid3)
129
+ val added3 = makeOutgoingHtlcAdded(upstream3, 3000 msat)
130
+ testKit.system.eventStream ! EventStream .Publish (added3)
131
+ testKit.system.eventStream ! EventStream .Publish (makeOutgoingHtlcFailed(added2.add))
132
+ testKit.system.eventStream ! EventStream .Publish (makeOutgoingHtlcFulfilled(added3.add))
133
+ listener.expectMessageType[OutgoingHtlcAdded ]
134
+ listener.expectMessageType[OutgoingHtlcFailed ]
135
+ listener.expectMessageType[OutgoingHtlcFulfilled ]
86
136
87
- reputationRecorder ! GetConfidence (replyTo.ref, a, 7 , uuid4 , 1000 msat)
88
- assert(replyTo.expectMessageType[Confidence ].value === (1.0 / 4 ) +- 0.001 )
89
- reputationRecorder ! GetConfidence (replyTo.ref, a, 0 , uuid5 , 1000 msat)
137
+ reputationRecorder ! GetConfidence (replyTo.ref, makeChannelUpstream( a, 7 ) , 1000 msat)
138
+ assert(replyTo.expectMessageType[Confidence ].value === (1.0 / 3 ) +- 0.001 )
139
+ reputationRecorder ! GetConfidence (replyTo.ref, makeChannelUpstream( a, 0 ) , 1000 msat)
90
140
assert(replyTo.expectMessageType[Confidence ].value === (1.0 / 3 ) +- 0.001 )
91
- reputationRecorder ! GetConfidence (replyTo.ref, b, 7 , uuid6 , 1000 msat)
141
+ reputationRecorder ! GetConfidence (replyTo.ref, makeChannelUpstream( b, 7 ) , 1000 msat)
92
142
assert(replyTo.expectMessageType[Confidence ].value === (4.0 / 6 ) +- 0.001 )
93
- reputationRecorder ! GetConfidence (replyTo.ref, b, 0 , uuid7 , 1000 msat)
143
+ reputationRecorder ! GetConfidence (replyTo.ref, makeChannelUpstream( b, 0 ) , 1000 msat)
94
144
assert(replyTo.expectMessageType[Confidence ].value == 0.0 )
95
- reputationRecorder ! GetConfidence (replyTo.ref, c, 0 , uuid8 , 1000 msat)
96
- assert(replyTo.expectMessageType[Confidence ].value === (3.0 / 6 ) +- 0.001 )
145
+ reputationRecorder ! GetConfidence (replyTo.ref, makeChannelUpstream( c, 0 ) , 1000 msat)
146
+ assert(replyTo.expectMessageType[Confidence ].value === (3.0 / 5 ) +- 0.001 )
97
147
}
98
148
}
0 commit comments