1
1
// SPDX-License-Identifier: Apache-2.0
2
2
package com .hedera .services .bdd .suites .integration ;
3
3
4
+ import static com .hedera .hapi .util .HapiUtils .asInstant ;
5
+ import static com .hedera .node .app .hapi .utils .CommonPbjConverters .toPbj ;
4
6
import static com .hedera .services .bdd .junit .RepeatableReason .NEEDS_VIRTUAL_TIME_FOR_FAST_EXECUTION ;
5
7
import static com .hedera .services .bdd .junit .TestTags .INTEGRATION ;
6
8
import static com .hedera .services .bdd .junit .hedera .embedded .EmbeddedMode .REPEATABLE ;
48
50
import com .hederahashgraph .api .proto .java .AccountAmount ;
49
51
import edu .umd .cs .findbugs .annotations .NonNull ;
50
52
import java .time .Duration ;
53
+ import java .time .Instant ;
51
54
import java .util .List ;
52
55
import java .util .Map ;
53
56
import java .util .concurrent .atomic .AtomicLong ;
57
+ import java .util .concurrent .atomic .AtomicReference ;
54
58
import java .util .function .LongSupplier ;
55
59
import java .util .stream .Stream ;
56
60
import org .junit .jupiter .api .BeforeAll ;
@@ -98,18 +102,20 @@ static void beforeAll(@NonNull final TestLifecycle testLifecycle) {
98
102
final Stream <DynamicTest > paysAdjustedFeesToAllEligibleActiveAccountsAtStartOfNewPeriod () {
99
103
final AtomicLong expectedNodeFees = new AtomicLong (0 );
100
104
final AtomicLong expectedNodeRewards = new AtomicLong (0 );
105
+ final AtomicReference <Instant > startConsensusTime = new AtomicReference <>();
101
106
return hapiTest (
102
- recordStreamMustIncludePassFrom (
103
- selectedItems (
104
- nodeRewardsValidator (expectedNodeRewards ::get ),
105
- // We expect two node rewards payments in this test.
106
- // But first staking period all nodes are inactive and minReward is 0.
107
- // So no synthetic node rewards payment is expected.
108
- 1 ,
109
- (spec , item ) -> item .getRecord ().getTransferList ().getAccountAmountsList ().stream ()
110
- .anyMatch (aa ->
111
- aa .getAccountID ().getAccountNum () == 801L && aa .getAmount () < 0L )),
112
- Duration .ofSeconds (1 )),
107
+ doingContextual (spec -> startConsensusTime .set (spec .consensusTime ())),
108
+ recordStreamMustIncludePassFrom (selectedItems (
109
+ nodeRewardsValidator (expectedNodeRewards ::get ),
110
+ // We expect two node rewards payments in this test.
111
+ // But first staking period all nodes are inactive and minReward is 0.
112
+ // So no synthetic node rewards payment is expected.
113
+ 1 ,
114
+ (spec , item ) -> item .getRecord ().getTransferList ().getAccountAmountsList ().stream ()
115
+ .anyMatch (
116
+ aa -> aa .getAccountID ().getAccountNum () == 801L && aa .getAmount () < 0L )
117
+ && asInstant (toPbj (item .getRecord ().getConsensusTimestamp ()))
118
+ .isAfter (startConsensusTime .get ()))),
113
119
cryptoTransfer (TokenMovement .movingHbar (100000 * ONE_HBAR ).between (GENESIS , NODE_REWARD )),
114
120
nodeUpdate ("0" ).declineReward (true ),
115
121
// Start a new period
@@ -121,12 +127,13 @@ final Stream<DynamicTest> paysAdjustedFeesToAllEligibleActiveAccountsAtStartOfNe
121
127
.payingWith (CIVILIAN_PAYER )
122
128
.via ("notFree" ),
123
129
// Collects ~1.8M tinybar in node fees; so ~450k tinybar per node
124
- getTxnRecord ("notFree" )
125
- .exposingTo (r -> expectedNodeFees .set (r .getTransferList ().getAccountAmountsList ().stream ()
126
- .filter (a -> a .getAccountID ().getAccountNum () == 3L )
127
- .findFirst ()
128
- .orElseThrow ()
129
- .getAmount ())),
130
+ getTxnRecord ("notFree" ).exposingTo (r -> {
131
+ expectedNodeFees .set (r .getTransferList ().getAccountAmountsList ().stream ()
132
+ .filter (a -> a .getAccountID ().getAccountNum () == 3L )
133
+ .findFirst ()
134
+ .orElseThrow ()
135
+ .getAmount ());
136
+ }),
130
137
// validate all network fees go to 0.0.801
131
138
validateRecordFees ("notFree" , List .of (3L , 801L )),
132
139
doWithStartupConfig (
@@ -185,8 +192,10 @@ final Stream<DynamicTest> paysAdjustedFeesToAllEligibleActiveAccountsAtStartOfNe
185
192
final Stream <DynamicTest > paysNonAdjustedFeesToAllEligibleActiveAccountsAtStartOfNewPeriod () {
186
193
final AtomicLong expectedNodeFees = new AtomicLong (0 );
187
194
final AtomicLong expectedNodeRewards = new AtomicLong (0 );
195
+ final AtomicReference <Instant > startConsensusTime = new AtomicReference <>();
188
196
return hapiTest (
189
197
overriding ("nodes.adjustNodeFees" , "false" ),
198
+ doingContextual (spec -> startConsensusTime .set (spec .consensusTime ())),
190
199
recordStreamMustIncludePassFrom (
191
200
selectedItems (
192
201
nodeRewardsValidator (expectedNodeRewards ::get ),
@@ -195,8 +204,11 @@ final Stream<DynamicTest> paysNonAdjustedFeesToAllEligibleActiveAccountsAtStartO
195
204
// So no synthetic node rewards payment is expected.
196
205
1 ,
197
206
(spec , item ) -> item .getRecord ().getTransferList ().getAccountAmountsList ().stream ()
198
- .anyMatch (aa ->
199
- aa .getAccountID ().getAccountNum () == 801L && aa .getAmount () < 0L )),
207
+ .anyMatch (
208
+ aa -> aa .getAccountID ().getAccountNum () == 801L
209
+ && aa .getAmount () < 0L )
210
+ && asInstant (toPbj (item .getRecord ().getConsensusTimestamp ()))
211
+ .isAfter (startConsensusTime .get ())),
200
212
Duration .ofSeconds (1 )),
201
213
cryptoTransfer (TokenMovement .movingHbar (100000 * ONE_HBAR ).between (GENESIS , NODE_REWARD )),
202
214
nodeUpdate ("0" ).declineReward (true ),
@@ -271,11 +283,13 @@ final Stream<DynamicTest> paysNonAdjustedFeesToAllEligibleActiveAccountsAtStartO
271
283
overrides = {"nodes.minPerPeriodNodeRewardUsd" })
272
284
@ Order (2 )
273
285
final Stream <DynamicTest > inactiveNodesPaidWhenMinRewardsGreaterThanZero () {
286
+ final AtomicReference <Instant > startConsensusTime = new AtomicReference <>();
274
287
final AtomicLong expectedNodeFees = new AtomicLong (0 );
275
288
final AtomicLong expectedNodeRewards = new AtomicLong (0 );
276
289
final AtomicLong expectedMinNodeReward = new AtomicLong (0 );
277
290
return hapiTest (
278
291
overriding ("nodes.minPerPeriodNodeRewardUsd" , "10" ),
292
+ doingContextual (spec -> startConsensusTime .set (spec .consensusTime ())),
279
293
recordStreamMustIncludePassFrom (
280
294
selectedItems (
281
295
nodeRewardsValidatorWithInactiveNodes (
@@ -285,8 +299,11 @@ final Stream<DynamicTest> inactiveNodesPaidWhenMinRewardsGreaterThanZero() {
285
299
// Second staking period, two nodes are active and one node is inactive
286
300
2 ,
287
301
(spec , item ) -> item .getRecord ().getTransferList ().getAccountAmountsList ().stream ()
288
- .anyMatch (aa ->
289
- aa .getAccountID ().getAccountNum () == 801L && aa .getAmount () < 0L )),
302
+ .anyMatch (
303
+ aa -> aa .getAccountID ().getAccountNum () == 801L
304
+ && aa .getAmount () < 0L )
305
+ && asInstant (toPbj (item .getRecord ().getConsensusTimestamp ()))
306
+ .isAfter (startConsensusTime .get ())),
290
307
Duration .ofSeconds (1 )),
291
308
nodeUpdate ("0" ).declineReward (true ),
292
309
cryptoTransfer (TokenMovement .movingHbar (10000000 * ONE_HBAR ).between (GENESIS , NODE_REWARD )),
@@ -349,10 +366,12 @@ final Stream<DynamicTest> inactiveNodesPaidWhenMinRewardsGreaterThanZero() {
349
366
overrides = {"nodes.preserveMinNodeRewardBalance" })
350
367
@ Order (3 )
351
368
final Stream <DynamicTest > preserveNodeRewardBalanceHasEffectWhenFeatureEnabled () {
369
+ final AtomicReference <Instant > startConsensusTime = new AtomicReference <>();
352
370
final AtomicLong expectedNodeFees = new AtomicLong (0 );
353
371
final AtomicLong expectedNodeRewards = new AtomicLong (0 );
354
372
return hapiTest (
355
373
overriding ("nodes.preserveMinNodeRewardBalance" , "false" ),
374
+ doingContextual (spec -> startConsensusTime .set (spec .consensusTime ())),
356
375
recordStreamMustIncludePassFrom (
357
376
selectedItems (
358
377
nodeRewardsValidator (expectedNodeRewards ::get ),
@@ -361,8 +380,11 @@ final Stream<DynamicTest> preserveNodeRewardBalanceHasEffectWhenFeatureEnabled()
361
380
// So no synthetic node rewards payment is expected.
362
381
1 ,
363
382
(spec , item ) -> item .getRecord ().getTransferList ().getAccountAmountsList ().stream ()
364
- .anyMatch (aa ->
365
- aa .getAccountID ().getAccountNum () == 801L && aa .getAmount () < 0L )),
383
+ .anyMatch (
384
+ aa -> aa .getAccountID ().getAccountNum () == 801L
385
+ && aa .getAmount () < 0L )
386
+ && asInstant (toPbj (item .getRecord ().getConsensusTimestamp ()))
387
+ .isAfter (startConsensusTime .get ())),
366
388
Duration .ofSeconds (1 )),
367
389
cryptoTransfer (TokenMovement .movingHbar (100000 * ONE_HBAR ).between (GENESIS , NODE_REWARD )),
368
390
nodeUpdate ("0" ).declineReward (true ),
0 commit comments