@@ -59,7 +59,7 @@ def check_budget_finalization_sync(self, votesCount, status):
59
59
for i in range (0 , len (self .nodes )):
60
60
node = self .nodes [i ]
61
61
budFin = node .mnfinalbudget ("show" )
62
- assert_true (len (budFin ) == 1 , "MN budget finalization not synced in node" + str (i ))
62
+ assert_true (len (budFin ) == 1 , "MN budget finalization not synced in node " + str (i ))
63
63
budget = budFin [next (iter (budFin ))]
64
64
assert_equal (budget ["VoteCount" ], votesCount )
65
65
assert_equal (budget ["Status" ], status )
@@ -176,6 +176,15 @@ def submit_proposals(self, props):
176
176
self .log .info ("proposal %s broadcast successful!" % entry .name )
177
177
return props
178
178
179
+ def create_multisig_addr (self , node ):
180
+ addr1 = node .getnewaddress ()
181
+ addr2 = node .getnewaddress ()
182
+ addr3 = node .getnewaddress ()
183
+ sig_address_1 = node .validateaddress (addr1 )
184
+ sig_address_2 = node .validateaddress (addr2 )
185
+ sig_address_3 = node .validateaddress (addr3 )
186
+ return node .addmultisigaddress (2 , [sig_address_1 ['pubkey' ], sig_address_2 ['pubkey' ], sig_address_3 ['pubkey' ]])
187
+
179
188
def run_test (self ):
180
189
self .enable_mocktime ()
181
190
self .setup_3_masternodes_network ()
@@ -208,6 +217,18 @@ def run_test(self):
208
217
)
209
218
self .submit_proposals ([firstProposal ])
210
219
220
+ multisigAddr = self .create_multisig_addr (self .miner )
221
+ # Submit multisig proposal
222
+ self .log .info ("preparing budget proposal.." )
223
+ multisigProposal = Proposal (
224
+ "we-like-multisig" ,
225
+ "https://forum.pivx.org/t/test-multisig" ,
226
+ 2 ,
227
+ multisigAddr ,
228
+ 600
229
+ )
230
+ self .submit_proposals ([multisigProposal ])
231
+
211
232
# Create 15 more proposals to have a higher tier two net gossip movement
212
233
props = []
213
234
for i in range (15 ):
@@ -223,17 +244,21 @@ def run_test(self):
223
244
self .stake (7 , [self .remoteOne , self .remoteTwo ])
224
245
# Check proposals existence
225
246
for i in range (self .num_nodes ):
226
- assert_equal (len (self .nodes [i ].getbudgetinfo ()), 16 )
247
+ assert_equal (len (self .nodes [i ].getbudgetinfo ()), 17 )
227
248
228
249
# now let's vote for the proposal with the first MN
229
250
self .log .info ("Voting with MN1..." )
230
251
voteResult = self .ownerOne .mnbudgetvote ("alias" , firstProposal .proposalHash , "yes" , self .masternodeOneAlias , True )
231
252
assert_equal (voteResult ["detail" ][0 ]["result" ], "success" )
232
253
254
+ multisigVoteResult = self .ownerOne .mnbudgetvote ("alias" , multisigProposal .proposalHash , "yes" , self .masternodeOneAlias , True )
255
+ assert_equal (multisigVoteResult ["detail" ][0 ]["result" ], "success" )
256
+
233
257
# check that the vote was accepted everywhere
234
258
self .stake (1 , [self .remoteOne , self .remoteTwo ])
235
259
self .check_vote_existence (firstProposal .name , self .mnOneCollateral .hash , "YES" , True )
236
- self .log .info ("all good, MN1 vote accepted everywhere!" )
260
+ self .check_vote_existence (multisigProposal .name , self .mnOneCollateral .hash , "YES" , True )
261
+ self .log .info ("all good, MN1 votes accepted everywhere!" )
237
262
238
263
# before broadcast the second vote, let's drop the budget data of ownerOne.
239
264
# so the node is forced to send a single proposal sync when the, now orphan, proposal vote is received.
@@ -247,11 +272,15 @@ def run_test(self):
247
272
voteResult = self .ownerTwo .mnbudgetvote ("alias" , firstProposal .proposalHash , "yes" , self .masternodeTwoAlias , True )
248
273
assert_equal (voteResult ["detail" ][0 ]["result" ], "success" )
249
274
275
+ multisigVoteResult = self .ownerTwo .mnbudgetvote ("alias" , multisigProposal .proposalHash , "yes" , self .masternodeTwoAlias , True )
276
+ assert_equal (multisigVoteResult ["detail" ][0 ]["result" ], "success" )
250
277
# check orphan vote proposal re-sync
251
278
self .log .info ("checking orphan vote based proposal re-sync..." )
252
279
time .sleep (5 ) # wait a bit before check it
253
280
self .check_proposal_existence (firstProposal .name , firstProposal .proposalHash )
254
281
self .check_vote_existence (firstProposal .name , self .mnOneCollateral .hash , "YES" , True )
282
+ self .check_proposal_existence (multisigProposal .name , multisigProposal .proposalHash )
283
+ self .check_vote_existence (multisigProposal .name , self .mnOneCollateral .hash , "YES" , True )
255
284
self .log .info ("all good, orphan vote based proposal re-sync succeeded" )
256
285
257
286
# check that the vote was accepted everywhere
@@ -275,19 +304,28 @@ def run_test(self):
275
304
TotalPayment = firstProposal .amountPerCycle * firstProposal .cycles
276
305
Allotted = firstProposal .amountPerCycle
277
306
RemainingPaymentCount = firstProposal .cycles
307
+
308
+ multisigBlockEnd = blockStart + multisigProposal .cycles * 145
309
+ multisigTotalPayment = multisigProposal .amountPerCycle * multisigProposal .cycles
310
+ multisigAllotted = multisigProposal .amountPerCycle
311
+ multisigRemainingPaymentCount = multisigProposal .cycles
278
312
expected_budget = [
279
313
self .get_proposal_obj (firstProposal .name , firstProposal .link , firstProposal .proposalHash , firstProposal .feeTxId , blockStart ,
280
314
blockEnd , firstProposal .cycles , RemainingPaymentCount , firstProposal .paymentAddr , 1 ,
281
315
3 , 0 , 0 , satoshi_round (TotalPayment ), satoshi_round (firstProposal .amountPerCycle ),
282
- True , True , satoshi_round (Allotted ), satoshi_round (Allotted ))
316
+ True , True , satoshi_round (Allotted ), satoshi_round (Allotted )),
317
+ self .get_proposal_obj (multisigProposal .name , multisigProposal .link , multisigProposal .proposalHash , multisigProposal .feeTxId , blockStart ,
318
+ multisigBlockEnd , multisigProposal .cycles , multisigRemainingPaymentCount , multisigProposal .paymentAddr , 1 ,
319
+ 2 , 0 , 0 , satoshi_round (multisigTotalPayment ), satoshi_round (multisigProposal .amountPerCycle ),
320
+ True , True , satoshi_round (multisigAllotted ), satoshi_round (multisigAllotted + Allotted )),
283
321
]
284
322
self .check_budgetprojection (expected_budget )
285
323
286
324
# Quick block count check.
287
- assert_equal (self .ownerOne .getblockcount (), 279 )
325
+ assert_equal (self .ownerOne .getblockcount (), 282 )
288
326
289
327
self .log .info ("starting budget finalization sync test.." )
290
- self .stake (2 , [self .remoteOne , self .remoteTwo ])
328
+ self .stake (1 , [self .remoteOne , self .remoteTwo ])
291
329
292
330
# assert that there is no budget finalization first.
293
331
assert_equal (len (self .ownerOne .mnfinalbudget ("show" )), 0 )
@@ -337,10 +375,14 @@ def run_test(self):
337
375
addrInfo = self .miner .listreceivedbyaddress (0 , False , False , firstProposal .paymentAddr )
338
376
assert_equal (addrInfo [0 ]["amount" ], firstProposal .amountPerCycle )
339
377
378
+ addrInfo = self .miner .listreceivedbyaddress (0 , False , False , multisigProposal .paymentAddr )
379
+ assert_equal (addrInfo [0 ]["amount" ], multisigProposal .amountPerCycle )
380
+
340
381
self .log .info ("budget proposal paid!, all good" )
341
382
342
383
# Check that the proposal info returns updated payment count
343
384
expected_budget [0 ]["RemainingPaymentCount" ] -= 1
385
+ expected_budget [1 ]["RemainingPaymentCount" ] -= 1
344
386
self .check_budgetprojection (expected_budget )
345
387
346
388
self .stake (1 , [self .remoteOne , self .remoteTwo ])
@@ -356,7 +398,7 @@ def run_test(self):
356
398
self .wait_until_mnsync_finished ()
357
399
self .check_budgetprojection (expected_budget )
358
400
for i in range (self .num_nodes ):
359
- assert_equal (len (self .nodes [i ].getbudgetinfo ()), 16 )
401
+ assert_equal (len (self .nodes [i ].getbudgetinfo ()), 17 )
360
402
361
403
self .log .info ("resync (1): budget data resynchronized successfully!" )
362
404
@@ -377,7 +419,7 @@ def run_test(self):
377
419
self .log .info ("syncing node.." )
378
420
self .wait_until_mnsync_finished ()
379
421
for i in range (self .num_nodes ):
380
- assert_equal (len (self .nodes [i ].getbudgetinfo ()), 16 )
422
+ assert_equal (len (self .nodes [i ].getbudgetinfo ()), 17 )
381
423
self .log .info ("resync (2): budget data resynchronized successfully!" )
382
424
383
425
# Let's now verify the remote budget data relay.
@@ -392,7 +434,7 @@ def run_test(self):
392
434
time .sleep (5 ) # wait a little bit
393
435
self .log .info ("Checking budget sync.." )
394
436
for i in range (self .num_nodes ):
395
- assert_equal (len (self .nodes [i ].getbudgetinfo ()), 16 )
437
+ assert_equal (len (self .nodes [i ].getbudgetinfo ()), 17 )
396
438
self .check_vote_existence (firstProposal .name , self .mnOneCollateral .hash , "YES" , True )
397
439
self .check_vote_existence (firstProposal .name , self .mnTwoCollateral .hash , "YES" , True )
398
440
self .check_vote_existence (firstProposal .name , self .proRegTx1 , "YES" , True )
@@ -424,7 +466,7 @@ def run_test(self):
424
466
assert_equal (len (self .miner .mnfinalbudget ("show" )), 1 )
425
467
blocks_to_mine = nextSuperBlockHeight + 200 - self .miner .getblockcount ()
426
468
self .log .info ("Mining %d more blocks to check expired budget removal..." % blocks_to_mine )
427
- self .stake (blocks_to_mine - 1 , [self .remoteTwo ])
469
+ self .stake (blocks_to_mine , [self .remoteTwo ])
428
470
# finalized budget must still be there
429
471
self .miner .checkbudgets ()
430
472
assert_equal (len (self .miner .mnfinalbudget ("show" )), 1 )
0 commit comments