6
6
"math/big"
7
7
"math/rand"
8
8
"os"
9
+ "slices"
9
10
"strconv"
10
11
"sync"
11
12
"testing"
@@ -26,8 +27,10 @@ import (
26
27
"github.com/iotexproject/iotex-core/v2/action/protocol"
27
28
accountutil "github.com/iotexproject/iotex-core/v2/action/protocol/account/util"
28
29
"github.com/iotexproject/iotex-core/v2/action/protocol/rewarding"
30
+ "github.com/iotexproject/iotex-core/v2/action/protocol/rewarding/rewardingpb"
29
31
"github.com/iotexproject/iotex-core/v2/api"
30
32
"github.com/iotexproject/iotex-core/v2/blockchain"
33
+ "github.com/iotexproject/iotex-core/v2/blockchain/block"
31
34
"github.com/iotexproject/iotex-core/v2/blockchain/genesis"
32
35
"github.com/iotexproject/iotex-core/v2/config"
33
36
"github.com/iotexproject/iotex-core/v2/pkg/log"
@@ -81,9 +84,23 @@ func TestBlockReward(t *testing.T) {
81
84
cfg .Consensus .RollDPoS .FSM .AcceptProposalEndorsementTTL = 300 * time .Millisecond
82
85
cfg .Consensus .RollDPoS .FSM .AcceptLockEndorsementTTL = 300 * time .Millisecond
83
86
cfg .Consensus .RollDPoS .FSM .CommitTTL = 100 * time .Millisecond
87
+ cfg .DardanellesUpgrade .AcceptBlockTTL = 300 * time .Millisecond
88
+ cfg .DardanellesUpgrade .AcceptProposalEndorsementTTL = 300 * time .Millisecond
89
+ cfg .DardanellesUpgrade .AcceptLockEndorsementTTL = 300 * time .Millisecond
90
+ cfg .DardanellesUpgrade .CommitTTL = 100 * time .Millisecond
91
+ cfg .DardanellesUpgrade .BlockInterval = time .Second
92
+ cfg .Chain .MintTimeout = 100 * time .Millisecond
84
93
cfg .Chain .ProducerPrivKey = identityset .PrivateKey (0 ).HexString ()
85
94
cfg .Network .Port = testutil .RandomPort ()
86
95
cfg .Genesis .PollMode = "lifeLong"
96
+ cfg .Genesis .AleutianBlockHeight = 0
97
+ cfg .Genesis .DardanellesBlockHeight = 1 // enable block reward
98
+ cfg .Genesis .GreenlandBlockHeight = 6
99
+ cfg .Genesis .KamchatkaBlockHeight = 7
100
+ cfg .Genesis .VanuatuBlockHeight = 8 // enable dynamic fee
101
+ cfg .Genesis .ToBeEnabledBlockHeight = 10 // enable wake block reward
102
+ testutil .NormalizeGenesisHeights (& cfg .Genesis .Blockchain )
103
+ block .LoadGenesisHash (& cfg .Genesis )
87
104
88
105
svr , err := itx .NewServer (cfg )
89
106
require .NoError (t , err )
@@ -92,6 +109,35 @@ func TestBlockReward(t *testing.T) {
92
109
require .NoError (t , svr .Stop (context .Background ()))
93
110
}()
94
111
112
+ inject := func (ctx context.Context , tps int ) {
113
+ actpool := svr .ChainService (cfg .Chain .ID ).ActionPool ()
114
+ senderSK := identityset .PrivateKey (1 )
115
+ amount := big .NewInt (100 )
116
+ gasLimit := uint64 (100000 )
117
+ gasPrice := big .NewInt (unit .Qev * 2 )
118
+ nonce , err := actpool .GetPendingNonce (senderSK .PublicKey ().Address ().String ())
119
+ require .NoError (t , err )
120
+ ticker := time .NewTicker (time .Second / time .Duration (tps ))
121
+ defer ticker .Stop ()
122
+ for {
123
+ select {
124
+ case <- ticker .C :
125
+ tx , err := action .SignedTransfer (identityset .Address (10 ).String (), senderSK , nonce , amount , nil , gasLimit , gasPrice , action .WithChainID (cfg .Chain .ID ))
126
+ require .NoError (t , err )
127
+ if err = actpool .Add (ctx , tx ); err != nil {
128
+ t .Log ("failed to add action to actpool" , zap .Error (err ))
129
+ } else {
130
+ nonce ++
131
+ }
132
+ case <- ctx .Done ():
133
+ return
134
+ }
135
+ }
136
+ }
137
+ ctxInject , cancel := context .WithCancel (context .Background ())
138
+ defer cancel ()
139
+ go inject (ctxInject , 10 )
140
+
95
141
require .NoError (t , testutil .WaitUntil (100 * time .Millisecond , 20 * time .Second , func () (b bool , e error ) {
96
142
return svr .ChainService (1 ).Blockchain ().TipHeight () >= 5 , nil
97
143
}))
@@ -120,19 +166,63 @@ func TestBlockReward(t *testing.T) {
120
166
require .NoError (t , err )
121
167
assert .True (t , balance .Cmp (big .NewInt (0 ).Mul (blockReward , big .NewInt (5 ))) <= 0 )
122
168
123
- for i := 1 ; i <= 5 ; i ++ {
124
- blk , err := svr .ChainService (1 ).BlockDAO ().GetBlockByHeight (uint64 (i ))
169
+ checkBlockReward := func ( blockHeight uint64 ) {
170
+ blk , err := svr .ChainService (1 ).BlockDAO ().GetBlockByHeight (uint64 (blockHeight ))
125
171
require .NoError (t , err )
126
172
ok := false
127
- var gr * action.GrantReward
128
- for _ , act := range blk .Body .Actions {
173
+ var (
174
+ gr * action.GrantReward
175
+ idx int
176
+ )
177
+ for k , act := range blk .Body .Actions {
129
178
gr , ok = act .Action ().(* action.GrantReward )
130
179
if ok {
131
- assert .Equal (t , uint64 (i ), gr .Height ())
180
+ idx = k
181
+ require .NoError (t , err )
182
+ assert .Equal (t , uint64 (blockHeight ), gr .Height ())
132
183
break
133
184
}
134
185
}
135
186
assert .True (t , ok )
187
+ receipts , err := svr .ChainService (1 ).BlockDAO ().GetReceipts (uint64 (blockHeight ))
188
+ require .NoError (t , err )
189
+ require .Len (t , receipts [idx ].Logs (), 1 )
190
+ rewardLogs , err := rewarding .UnmarshalRewardLog (receipts [idx ].Logs ()[0 ].Data )
191
+ require .NoError (t , err )
192
+
193
+ rewards := make (map [rewardingpb.RewardLog_RewardType ]* big.Int )
194
+ rewards [rewardingpb .RewardLog_BLOCK_REWARD ] = big .NewInt (0 )
195
+ rewards [rewardingpb .RewardLog_PRIORITY_BONUS ] = big .NewInt (0 )
196
+ for _ , txLog := range rewardLogs .Logs {
197
+ amount , ok := big .NewInt (0 ).SetString (txLog .Amount , 10 )
198
+ require .True (t , ok )
199
+ rewards [txLog .Type ] = amount
200
+ }
201
+
202
+ switch {
203
+ case blockHeight < cfg .Genesis .VanuatuBlockHeight :
204
+ // fixed block reward
205
+ assert .Equal (t , cfg .Genesis .DardanellesBlockReward ().String (), rewards [rewardingpb .RewardLog_BLOCK_REWARD ].String ())
206
+ assert .Equal (t , big .NewInt (0 ).String (), rewards [rewardingpb .RewardLog_PRIORITY_BONUS ].String ())
207
+ case blockHeight < cfg .Genesis .ToBeEnabledBlockHeight :
208
+ // fixed block reward + priority bonus
209
+ require .True (t , rewards [rewardingpb .RewardLog_PRIORITY_BONUS ].Sign () > 0 , "blockHeight %d" , blockHeight )
210
+ assert .Equal (t , cfg .Genesis .DardanellesBlockReward ().String (), rewards [rewardingpb .RewardLog_BLOCK_REWARD ].String ())
211
+ assert .Equal (t , slices .ContainsFunc (blk .Actions , func (e * action.SealedEnvelope ) bool { return ! action .IsSystemAction (e ) }), rewards [rewardingpb .RewardLog_PRIORITY_BONUS ].Sign () > 0 )
212
+ default :
213
+ // dynamic block reward + priority bonus
214
+ require .True (t , rewards [rewardingpb .RewardLog_PRIORITY_BONUS ].Sign () > 0 )
215
+ assert .Equal (t , slices .ContainsFunc (blk .Actions , func (e * action.SealedEnvelope ) bool { return ! action .IsSystemAction (e ) }), rewards [rewardingpb .RewardLog_PRIORITY_BONUS ].Sign () > 0 )
216
+ total := new (big.Int ).Add (rewards [rewardingpb .RewardLog_BLOCK_REWARD ], rewards [rewardingpb .RewardLog_PRIORITY_BONUS ])
217
+ assert .Equal (t , true , total .Cmp (cfg .Genesis .WakeBlockReward ()) >= 0 )
218
+ }
219
+ }
220
+
221
+ require .NoError (t , testutil .WaitUntil (100 * time .Millisecond , 20 * time .Second , func () (b bool , e error ) {
222
+ return svr .ChainService (1 ).Blockchain ().TipHeight () >= 11 , nil
223
+ }))
224
+ for i := 1 ; i <= 11 ; i ++ {
225
+ checkBlockReward (uint64 (i ))
136
226
}
137
227
}
138
228
0 commit comments