@@ -1117,13 +1117,13 @@ def setupDMN(self,
1117
1117
break
1118
1118
assert_greater_than (collateralTxId_n , - 1 )
1119
1119
assert_greater_than (json_tx ["confirmations" ], 0 )
1120
- proTxId = mnOwner .protx_register (collateralTxId , collateralTxId_n , ipport , ownerAdd ,
1120
+ proTxId = mnOwner .protx_register (collateralTxId , collateralTxId_n , True , ipport , ownerAdd ,
1121
1121
bls_keypair ["public" ], votingAdd , collateralAdd )
1122
1122
elif strType == "external" :
1123
1123
self .log .info ("Setting up ProRegTx with collateral externally-signed..." )
1124
1124
# send the tx from the miner
1125
1125
payoutAdd = mnOwner .getnewaddress ("payout" )
1126
- register_res = miner .protx_register_prepare (outpoint .hash , outpoint .n , ipport , ownerAdd ,
1126
+ register_res = miner .protx_register_prepare (outpoint .hash , outpoint .n , True , ipport , ownerAdd ,
1127
1127
bls_keypair ["public" ], votingAdd , payoutAdd )
1128
1128
self .log .info ("ProTx prepared" )
1129
1129
message_to_sign = register_res ["signMessage" ]
@@ -1218,19 +1218,20 @@ def protx_register_fund(self, miner, controller, dmn, collateral_addr, op_rew=No
1218
1218
Create a ProReg tx, which references an 100 PIV UTXO as collateral.
1219
1219
The controller node owns the collateral and creates the ProReg tx.
1220
1220
"""
1221
- def protx_register (self , miner , controller , dmn , collateral_addr ):
1221
+ def protx_register (self , miner , controller , dmn , collateral_addr , transparent ):
1222
1222
# send to the owner the exact collateral tx amount
1223
1223
funding_txid = miner .sendtoaddress (collateral_addr , Decimal ('100' ))
1224
1224
# send another output to be used for the fee of the proReg tx
1225
- miner .sendtoaddress (collateral_addr , Decimal ('1' ))
1225
+ feeAddr = collateral_addr if transparent else controller .getnewaddress ("feeAddr" )
1226
+ miner .sendtoaddress (feeAddr , Decimal ('1' ))
1226
1227
# confirm and verify reception
1227
1228
miner .generate (1 )
1228
1229
self .sync_blocks ([miner , controller ])
1229
1230
json_tx = controller .getrawtransaction (funding_txid , True )
1230
1231
assert_greater_than (json_tx ["confirmations" ], 0 )
1231
- # create and send the ProRegTx
1232
- dmn .collateral = COutPoint (int (funding_txid , 16 ), get_collateral_vout (json_tx ))
1233
- dmn .proTx = controller .protx_register (funding_txid , dmn .collateral .n , dmn .ipport , dmn .owner ,
1232
+ # create and send the ProRegTx, FOR SHIELD DMNS THIS IS NOT THE COLLATERAL CONTAINED IN THE PROREGTX (which is instead the null COutPoint (0,-1))
1233
+ dmn .collateral = COutPoint (int (funding_txid , 16 ), get_collateral_vout (json_tx )) if transparent else COutPoint ( int ( funding_txid , 16 ), 0 , transparent )
1234
+ dmn .proTx = controller .protx_register (funding_txid , dmn .collateral .n , transparent , dmn .ipport , dmn .owner ,
1234
1235
dmn .operator_pk , dmn .voting , dmn .payee )
1235
1236
1236
1237
"""
@@ -1249,7 +1250,7 @@ def protx_register_ext(self, miner, controller, dmn, outpoint, fSubmit):
1249
1250
outpoint = COutPoint (int (funding_txid , 16 ), get_collateral_vout (json_tx ))
1250
1251
dmn .collateral = outpoint
1251
1252
# Prepare the message to be signed externally by the owner of the collateral (the controller)
1252
- reg_tx = miner .protx_register_prepare ("%064x" % outpoint .hash , outpoint .n , dmn .ipport , dmn .owner ,
1253
+ reg_tx = miner .protx_register_prepare ("%064x" % outpoint .hash , outpoint .n , True , dmn .ipport , dmn .owner ,
1253
1254
dmn .operator_pk , dmn .voting , dmn .payee )
1254
1255
sig = controller .signmessage (reg_tx ["collateralAddress" ], reg_tx ["signMessage" ])
1255
1256
if fSubmit :
@@ -1270,7 +1271,7 @@ def protx_register_ext(self, miner, controller, dmn, outpoint, fSubmit):
1270
1271
If not provided, a new address-key pair is generated.
1271
1272
:return: dmn: (Masternode) the deterministic masternode object
1272
1273
"""
1273
- def register_new_dmn (self , idx , miner_idx , controller_idx , strType ,
1274
+ def register_new_dmn (self , idx , miner_idx , controller_idx , strType , transparent ,
1274
1275
payout_addr = None , outpoint = None , op_blskeys = None ):
1275
1276
# Prepare remote node
1276
1277
assert idx != miner_idx
@@ -1280,19 +1281,21 @@ def register_new_dmn(self, idx, miner_idx, controller_idx, strType,
1280
1281
mn_node = self .nodes [idx ]
1281
1282
1282
1283
# Generate ip and addresses/keys
1283
- collateral_addr = controller_node .getnewaddress ("mncollateral-%d" % idx )
1284
+ collateral_addr = controller_node .getnewaddress ("mncollateral-%d" % idx ) if transparent else controller_node . getnewshieldaddress ( "shieldmncollateral-%d" % idx )
1284
1285
if payout_addr is None :
1285
- payout_addr = collateral_addr
1286
- dmn = create_new_dmn (idx , controller_node , payout_addr , op_blskeys )
1286
+ payout_addr = collateral_addr if transparent else controller_node . getnewaddress ( "mncollateral-%d" % idx )
1287
+ dmn = create_new_dmn (idx , controller_node , payout_addr , op_blskeys , transparent )
1287
1288
1288
1289
# Create ProRegTx
1289
1290
self .log .info ("Creating%s proRegTx for deterministic masternode idx=%d..." % (
1290
1291
" and funding" if strType == "fund" else "" , idx ))
1291
1292
if strType == "fund" :
1293
+ assert (transparent )
1292
1294
self .protx_register_fund (miner_node , controller_node , dmn , collateral_addr )
1293
1295
elif strType == "internal" :
1294
- self .protx_register (miner_node , controller_node , dmn , collateral_addr )
1296
+ self .protx_register (miner_node , controller_node , dmn , collateral_addr , transparent )
1295
1297
elif strType == "external" :
1298
+ assert (transparent )
1296
1299
self .protx_register_ext (miner_node , controller_node , dmn , outpoint , True )
1297
1300
else :
1298
1301
raise Exception ("Type %s not available" % strType )
@@ -1307,7 +1310,7 @@ def register_new_dmn(self, idx, miner_idx, controller_idx, strType,
1307
1310
assert dmn .proTx in mn_node .protx_list (False )
1308
1311
1309
1312
# check coin locking
1310
- assert is_coin_locked_by (controller_node , dmn .collateral )
1313
+ assert is_coin_locked_by (controller_node , dmn .collateral , dmn . transparent )
1311
1314
1312
1315
# check json payload against local dmn object
1313
1316
self .check_proreg_payload (dmn , json_tx )
@@ -1337,23 +1340,38 @@ def check_mn_list_on_node(self, idx, mns):
1337
1340
assert_equal (mn .voting , mn2 ["dmnstate" ]["votingAddress" ])
1338
1341
assert_equal (mn .ipport , mn2 ["dmnstate" ]["service" ])
1339
1342
assert_equal (mn .payee , mn2 ["dmnstate" ]["payoutAddress" ])
1340
- assert_equal (collateral ["txid" ], mn2 ["collateralHash" ])
1341
- assert_equal (collateral ["vout" ], mn2 ["collateralIndex" ])
1343
+ assert_equal (mn .nullifier , mn2 ["nullifier" ])
1344
+ # Usual story, For shield Dmns the value we store in collateral (i.e. the sapling outpoint referring to the note)
1345
+ # Is different from the default null collateral in the ProRegTx
1346
+ if mn .transparent :
1347
+ assert_equal (collateral ["txid" ], mn2 ["collateralHash" ])
1348
+ assert_equal (collateral ["vout" ], mn2 ["collateralIndex" ])
1349
+ else :
1350
+ assert_equal ("%064x" % 0 , mn2 ["collateralHash" ])
1351
+ assert_equal (- 1 , mn2 ["collateralIndex" ])
1342
1352
1343
1353
def check_proreg_payload (self , dmn , json_tx ):
1344
1354
assert "payload" in json_tx
1345
1355
# null hash if funding collateral
1346
1356
collateral_hash = 0 if int (json_tx ["txid" ], 16 ) == dmn .collateral .hash \
1347
1357
else dmn .collateral .hash
1358
+ collateral_n = dmn .collateral .n
1359
+ # null Outpoint if dmn is shielded
1360
+ if not dmn .transparent :
1361
+ collateral_hash = 0
1362
+ collateral_n = - 1
1348
1363
pl = json_tx ["payload" ]
1349
- assert_equal (pl ["version" ], 1 )
1364
+ assert_equal (pl ["version" ], 2 )
1350
1365
assert_equal (pl ["collateralHash" ], "%064x" % collateral_hash )
1351
- assert_equal (pl ["collateralIndex" ], dmn . collateral . n )
1366
+ assert_equal (pl ["collateralIndex" ], collateral_n )
1352
1367
assert_equal (pl ["service" ], dmn .ipport )
1353
1368
assert_equal (pl ["ownerAddress" ], dmn .owner )
1354
1369
assert_equal (pl ["votingAddress" ], dmn .voting )
1355
1370
assert_equal (pl ["operatorPubKey" ], dmn .operator_pk )
1356
1371
assert_equal (pl ["payoutAddress" ], dmn .payee )
1372
+ # fix the nullifier
1373
+ dmn .nullifier = pl ["nullifier" ]
1374
+
1357
1375
1358
1376
# ------------------------------------------------------
1359
1377
@@ -1383,17 +1401,18 @@ def __init__(self,
1383
1401
class PivxDMNTestFramework (PivxTestFramework ):
1384
1402
1385
1403
def set_base_test_params (self ):
1386
- # 1 miner, 1 controller, 6 remote mns
1404
+ # 1 miner, 1 controller, 6 remote mns 2 of which shielded
1387
1405
self .num_nodes = 8
1388
1406
self .minerPos = 0
1389
1407
self .controllerPos = 1
1390
1408
self .setup_clean_chain = True
1391
1409
1392
- def add_new_dmn (self , strType , op_keys = None , from_out = None ):
1410
+ def add_new_dmn (self , strType , transparent = True , op_keys = None , from_out = None ):
1393
1411
self .mns .append (self .register_new_dmn (2 + len (self .mns ),
1394
1412
self .minerPos ,
1395
1413
self .controllerPos ,
1396
1414
strType ,
1415
+ transparent ,
1397
1416
outpoint = from_out ,
1398
1417
op_blskeys = op_keys ))
1399
1418
@@ -1453,10 +1472,14 @@ def setup_test(self):
1453
1472
# Create 6 DMNs and init the remote nodes
1454
1473
self .log .info ("Initializing masternodes..." )
1455
1474
for _ in range (2 ):
1456
- self .add_new_dmn ("internal" )
1475
+ self .add_new_dmn ("internal" , False )
1457
1476
self .add_new_dmn ("external" )
1458
1477
self .add_new_dmn ("fund" )
1459
1478
assert_equal (len (self .mns ), 6 )
1479
+ # Sanity check that we have 2 shielded masternodes
1480
+ assert_equal (len (self .nodes [self .controllerPos ].listlockunspent ()["shielded" ]), 2 )
1481
+ assert_equal (self .mns [0 ].transparent , False )
1482
+ assert_equal (self .mns [3 ].transparent , False )
1460
1483
for mn in self .mns :
1461
1484
self .nodes [mn .idx ].initmasternode (mn .operator_sk )
1462
1485
time .sleep (1 )
0 commit comments