@@ -59,15 +59,15 @@ def check_budget_finalization_sync(self, votesCount, status):
5959 for i in range (0 , len (self .nodes )):
6060 node = self .nodes [i ]
6161 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 ))
6363 budget = budFin [next (iter (budFin ))]
6464 assert_equal (budget ["VoteCount" ], votesCount )
6565 assert_equal (budget ["Status" ], status )
6666
6767 def broadcastbudgetfinalization (self , node , with_ping_mns = []):
6868 self .log .info ("suggesting the budget finalization.." )
6969 assert (node .mnfinalbudgetsuggest () is not None )
70-
70+
7171 self .log .info ("confirming the budget finalization.." )
7272 time .sleep (1 )
7373 self .stake (4 , with_ping_mns )
@@ -176,6 +176,15 @@ def submit_proposals(self, props):
176176 self .log .info ("proposal %s broadcast successful!" % entry .name )
177177 return props
178178
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+
179188 def run_test (self ):
180189 self .enable_mocktime ()
181190 self .setup_3_masternodes_network ()
@@ -208,6 +217,18 @@ def run_test(self):
208217 )
209218 self .submit_proposals ([firstProposal ])
210219
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+
211232 # Create 15 more proposals to have a higher tier two net gossip movement
212233 props = []
213234 for i in range (15 ):
@@ -223,17 +244,21 @@ def run_test(self):
223244 self .stake (7 , [self .remoteOne , self .remoteTwo ])
224245 # Check proposals existence
225246 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 )
227248
228249 # now let's vote for the proposal with the first MN
229250 self .log .info ("Voting with MN1..." )
230251 voteResult = self .ownerOne .mnbudgetvote ("alias" , firstProposal .proposalHash , "yes" , self .masternodeOneAlias , True )
231252 assert_equal (voteResult ["detail" ][0 ]["result" ], "success" )
232253
254+ multisigVoteResult = self .ownerOne .mnbudgetvote ("alias" , multisigProposal .proposalHash , "yes" , self .masternodeOneAlias , True )
255+ assert_equal (multisigVoteResult ["detail" ][0 ]["result" ], "success" )
256+
233257 # check that the vote was accepted everywhere
234258 self .stake (1 , [self .remoteOne , self .remoteTwo ])
235259 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!" )
237262
238263 # before broadcast the second vote, let's drop the budget data of ownerOne.
239264 # 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):
247272 voteResult = self .ownerTwo .mnbudgetvote ("alias" , firstProposal .proposalHash , "yes" , self .masternodeTwoAlias , True )
248273 assert_equal (voteResult ["detail" ][0 ]["result" ], "success" )
249274
275+ multisigVoteResult = self .ownerTwo .mnbudgetvote ("alias" , multisigProposal .proposalHash , "yes" , self .masternodeTwoAlias , True )
276+ assert_equal (multisigVoteResult ["detail" ][0 ]["result" ], "success" )
250277 # check orphan vote proposal re-sync
251278 self .log .info ("checking orphan vote based proposal re-sync..." )
252279 time .sleep (5 ) # wait a bit before check it
253280 self .check_proposal_existence (firstProposal .name , firstProposal .proposalHash )
254281 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 )
255284 self .log .info ("all good, orphan vote based proposal re-sync succeeded" )
256285
257286 # check that the vote was accepted everywhere
@@ -275,19 +304,28 @@ def run_test(self):
275304 TotalPayment = firstProposal .amountPerCycle * firstProposal .cycles
276305 Allotted = firstProposal .amountPerCycle
277306 RemainingPaymentCount = firstProposal .cycles
307+
308+ multisigBlockEnd = blockStart + multisigProposal .cycles * 145
309+ multisigTotalPayment = multisigProposal .amountPerCycle * multisigProposal .cycles
310+ multisigAllotted = multisigProposal .amountPerCycle
311+ multisigRemainingPaymentCount = multisigProposal .cycles
278312 expected_budget = [
279313 self .get_proposal_obj (firstProposal .name , firstProposal .link , firstProposal .proposalHash , firstProposal .feeTxId , blockStart ,
280314 blockEnd , firstProposal .cycles , RemainingPaymentCount , firstProposal .paymentAddr , 1 ,
281315 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 )),
283321 ]
284322 self .check_budgetprojection (expected_budget )
285323
286324 # Quick block count check.
287- assert_equal (self .ownerOne .getblockcount (), 279 )
325+ assert_equal (self .ownerOne .getblockcount (), 282 )
288326
289327 self .log .info ("starting budget finalization sync test.." )
290- self .stake (2 , [self .remoteOne , self .remoteTwo ])
328+ self .stake (1 , [self .remoteOne , self .remoteTwo ])
291329
292330 # assert that there is no budget finalization first.
293331 assert_equal (len (self .ownerOne .mnfinalbudget ("show" )), 0 )
@@ -337,10 +375,14 @@ def run_test(self):
337375 addrInfo = self .miner .listreceivedbyaddress (0 , False , False , firstProposal .paymentAddr )
338376 assert_equal (addrInfo [0 ]["amount" ], firstProposal .amountPerCycle )
339377
378+ addrInfo = self .miner .listreceivedbyaddress (0 , False , False , multisigProposal .paymentAddr )
379+ assert_equal (addrInfo [0 ]["amount" ], multisigProposal .amountPerCycle )
380+
340381 self .log .info ("budget proposal paid!, all good" )
341382
342383 # Check that the proposal info returns updated payment count
343384 expected_budget [0 ]["RemainingPaymentCount" ] -= 1
385+ expected_budget [1 ]["RemainingPaymentCount" ] -= 1
344386 self .check_budgetprojection (expected_budget )
345387
346388 self .stake (1 , [self .remoteOne , self .remoteTwo ])
@@ -356,7 +398,7 @@ def run_test(self):
356398 self .wait_until_mnsync_finished ()
357399 self .check_budgetprojection (expected_budget )
358400 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 )
360402
361403 self .log .info ("resync (1): budget data resynchronized successfully!" )
362404
@@ -377,7 +419,7 @@ def run_test(self):
377419 self .log .info ("syncing node.." )
378420 self .wait_until_mnsync_finished ()
379421 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 )
381423 self .log .info ("resync (2): budget data resynchronized successfully!" )
382424
383425 # Let's now verify the remote budget data relay.
@@ -392,7 +434,7 @@ def run_test(self):
392434 time .sleep (5 ) # wait a little bit
393435 self .log .info ("Checking budget sync.." )
394436 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 )
396438 self .check_vote_existence (firstProposal .name , self .mnOneCollateral .hash , "YES" , True )
397439 self .check_vote_existence (firstProposal .name , self .mnTwoCollateral .hash , "YES" , True )
398440 self .check_vote_existence (firstProposal .name , self .proRegTx1 , "YES" , True )
@@ -424,7 +466,7 @@ def run_test(self):
424466 assert_equal (len (self .miner .mnfinalbudget ("show" )), 1 )
425467 blocks_to_mine = nextSuperBlockHeight + 200 - self .miner .getblockcount ()
426468 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 ])
428470 # finalized budget must still be there
429471 self .miner .checkbudgets ()
430472 assert_equal (len (self .miner .mnfinalbudget ("show" )), 1 )
0 commit comments