@@ -1104,13 +1104,13 @@ def setupDMN(self,
1104
1104
break
1105
1105
assert_greater_than (collateralTxId_n , - 1 )
1106
1106
assert_greater_than (json_tx ["confirmations" ], 0 )
1107
- proTxId = mnOwner .protx_register (collateralTxId , collateralTxId_n , ipport , ownerAdd ,
1107
+ proTxId = mnOwner .protx_register (collateralTxId , collateralTxId_n , True , ipport , ownerAdd ,
1108
1108
bls_keypair ["public" ], votingAdd , collateralAdd )
1109
1109
elif strType == "external" :
1110
1110
self .log .info ("Setting up ProRegTx with collateral externally-signed..." )
1111
1111
# send the tx from the miner
1112
1112
payoutAdd = mnOwner .getnewaddress ("payout" )
1113
- register_res = miner .protx_register_prepare (outpoint .hash , outpoint .n , ipport , ownerAdd ,
1113
+ register_res = miner .protx_register_prepare (outpoint .hash , outpoint .n , True , ipport , ownerAdd ,
1114
1114
bls_keypair ["public" ], votingAdd , payoutAdd )
1115
1115
self .log .info ("ProTx prepared" )
1116
1116
message_to_sign = register_res ["signMessage" ]
@@ -1205,19 +1205,20 @@ def protx_register_fund(self, miner, controller, dmn, collateral_addr, op_rew=No
1205
1205
Create a ProReg tx, which references an 100 PIV UTXO as collateral.
1206
1206
The controller node owns the collateral and creates the ProReg tx.
1207
1207
"""
1208
- def protx_register (self , miner , controller , dmn , collateral_addr ):
1208
+ def protx_register (self , miner , controller , dmn , collateral_addr , transparent ):
1209
1209
# send to the owner the exact collateral tx amount
1210
1210
funding_txid = miner .sendtoaddress (collateral_addr , Decimal ('100' ))
1211
1211
# send another output to be used for the fee of the proReg tx
1212
- miner .sendtoaddress (collateral_addr , Decimal ('1' ))
1212
+ feeAddr = collateral_addr if transparent else controller .getnewaddress ("feeAddr" )
1213
+ miner .sendtoaddress (feeAddr , Decimal ('1' ))
1213
1214
# confirm and verify reception
1214
1215
miner .generate (1 )
1215
1216
self .sync_blocks ([miner , controller ])
1216
1217
json_tx = controller .getrawtransaction (funding_txid , True )
1217
1218
assert_greater_than (json_tx ["confirmations" ], 0 )
1218
- # create and send the ProRegTx
1219
- dmn .collateral = COutPoint (int (funding_txid , 16 ), get_collateral_vout (json_tx ))
1220
- dmn .proTx = controller .protx_register (funding_txid , dmn .collateral .n , dmn .ipport , dmn .owner ,
1219
+ # 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))
1220
+ dmn .collateral = COutPoint (int (funding_txid , 16 ), get_collateral_vout (json_tx )) if transparent else COutPoint ( int ( funding_txid , 16 ), 0 , transparent )
1221
+ dmn .proTx = controller .protx_register (funding_txid , dmn .collateral .n , transparent , dmn .ipport , dmn .owner ,
1221
1222
dmn .operator_pk , dmn .voting , dmn .payee )
1222
1223
1223
1224
"""
@@ -1236,7 +1237,7 @@ def protx_register_ext(self, miner, controller, dmn, outpoint, fSubmit):
1236
1237
outpoint = COutPoint (int (funding_txid , 16 ), get_collateral_vout (json_tx ))
1237
1238
dmn .collateral = outpoint
1238
1239
# Prepare the message to be signed externally by the owner of the collateral (the controller)
1239
- reg_tx = miner .protx_register_prepare ("%064x" % outpoint .hash , outpoint .n , dmn .ipport , dmn .owner ,
1240
+ reg_tx = miner .protx_register_prepare ("%064x" % outpoint .hash , outpoint .n , True , dmn .ipport , dmn .owner ,
1240
1241
dmn .operator_pk , dmn .voting , dmn .payee )
1241
1242
sig = controller .signmessage (reg_tx ["collateralAddress" ], reg_tx ["signMessage" ])
1242
1243
if fSubmit :
@@ -1257,7 +1258,7 @@ def protx_register_ext(self, miner, controller, dmn, outpoint, fSubmit):
1257
1258
If not provided, a new address-key pair is generated.
1258
1259
:return: dmn: (Masternode) the deterministic masternode object
1259
1260
"""
1260
- def register_new_dmn (self , idx , miner_idx , controller_idx , strType ,
1261
+ def register_new_dmn (self , idx , miner_idx , controller_idx , strType , transparent ,
1261
1262
payout_addr = None , outpoint = None , op_blskeys = None ):
1262
1263
# Prepare remote node
1263
1264
assert idx != miner_idx
@@ -1267,19 +1268,21 @@ def register_new_dmn(self, idx, miner_idx, controller_idx, strType,
1267
1268
mn_node = self .nodes [idx ]
1268
1269
1269
1270
# Generate ip and addresses/keys
1270
- collateral_addr = controller_node .getnewaddress ("mncollateral-%d" % idx )
1271
+ collateral_addr = controller_node .getnewaddress ("mncollateral-%d" % idx ) if transparent else controller_node . getnewshieldaddress ( "shieldmncollateral-%d" % idx )
1271
1272
if payout_addr is None :
1272
- payout_addr = collateral_addr
1273
- dmn = create_new_dmn (idx , controller_node , payout_addr , op_blskeys )
1273
+ payout_addr = collateral_addr if transparent else controller_node . getnewaddress ( "mncollateral-%d" % idx )
1274
+ dmn = create_new_dmn (idx , controller_node , payout_addr , op_blskeys , transparent )
1274
1275
1275
1276
# Create ProRegTx
1276
1277
self .log .info ("Creating%s proRegTx for deterministic masternode idx=%d..." % (
1277
1278
" and funding" if strType == "fund" else "" , idx ))
1278
1279
if strType == "fund" :
1280
+ assert (transparent )
1279
1281
self .protx_register_fund (miner_node , controller_node , dmn , collateral_addr )
1280
1282
elif strType == "internal" :
1281
- self .protx_register (miner_node , controller_node , dmn , collateral_addr )
1283
+ self .protx_register (miner_node , controller_node , dmn , collateral_addr , transparent )
1282
1284
elif strType == "external" :
1285
+ assert (transparent )
1283
1286
self .protx_register_ext (miner_node , controller_node , dmn , outpoint , True )
1284
1287
else :
1285
1288
raise Exception ("Type %s not available" % strType )
@@ -1294,7 +1297,7 @@ def register_new_dmn(self, idx, miner_idx, controller_idx, strType,
1294
1297
assert dmn .proTx in mn_node .protx_list (False )
1295
1298
1296
1299
# check coin locking
1297
- assert is_coin_locked_by (controller_node , dmn .collateral )
1300
+ assert is_coin_locked_by (controller_node , dmn .collateral , dmn . transparent )
1298
1301
1299
1302
# check json payload against local dmn object
1300
1303
self .check_proreg_payload (dmn , json_tx )
@@ -1324,23 +1327,38 @@ def check_mn_list_on_node(self, idx, mns):
1324
1327
assert_equal (mn .voting , mn2 ["dmnstate" ]["votingAddress" ])
1325
1328
assert_equal (mn .ipport , mn2 ["dmnstate" ]["service" ])
1326
1329
assert_equal (mn .payee , mn2 ["dmnstate" ]["payoutAddress" ])
1327
- assert_equal (collateral ["txid" ], mn2 ["collateralHash" ])
1328
- assert_equal (collateral ["vout" ], mn2 ["collateralIndex" ])
1330
+ assert_equal (mn .nullifier , mn2 ["nullifier" ])
1331
+ # Usual story, For shield Dmns the value we store in collateral (i.e. the sapling outpoint referring to the note)
1332
+ # Is different from the default null collateral in the ProRegTx
1333
+ if mn .transparent :
1334
+ assert_equal (collateral ["txid" ], mn2 ["collateralHash" ])
1335
+ assert_equal (collateral ["vout" ], mn2 ["collateralIndex" ])
1336
+ else :
1337
+ assert_equal ("%064x" % 0 , mn2 ["collateralHash" ])
1338
+ assert_equal (- 1 , mn2 ["collateralIndex" ])
1329
1339
1330
1340
def check_proreg_payload (self , dmn , json_tx ):
1331
1341
assert "payload" in json_tx
1332
1342
# null hash if funding collateral
1333
1343
collateral_hash = 0 if int (json_tx ["txid" ], 16 ) == dmn .collateral .hash \
1334
1344
else dmn .collateral .hash
1345
+ collateral_n = dmn .collateral .n
1346
+ # null Outpoint if dmn is shielded
1347
+ if not dmn .transparent :
1348
+ collateral_hash = 0
1349
+ collateral_n = - 1
1335
1350
pl = json_tx ["payload" ]
1336
- assert_equal (pl ["version" ], 1 )
1351
+ assert_equal (pl ["version" ], 2 )
1337
1352
assert_equal (pl ["collateralHash" ], "%064x" % collateral_hash )
1338
- assert_equal (pl ["collateralIndex" ], dmn . collateral . n )
1353
+ assert_equal (pl ["collateralIndex" ], collateral_n )
1339
1354
assert_equal (pl ["service" ], dmn .ipport )
1340
1355
assert_equal (pl ["ownerAddress" ], dmn .owner )
1341
1356
assert_equal (pl ["votingAddress" ], dmn .voting )
1342
1357
assert_equal (pl ["operatorPubKey" ], dmn .operator_pk )
1343
1358
assert_equal (pl ["payoutAddress" ], dmn .payee )
1359
+ # fix the nullifier
1360
+ dmn .nullifier = pl ["nullifier" ]
1361
+
1344
1362
1345
1363
# ------------------------------------------------------
1346
1364
@@ -1370,17 +1388,18 @@ def __init__(self,
1370
1388
class PivxDMNTestFramework (PivxTestFramework ):
1371
1389
1372
1390
def set_base_test_params (self ):
1373
- # 1 miner, 1 controller, 6 remote mns
1391
+ # 1 miner, 1 controller, 6 remote mns 2 of which shielded
1374
1392
self .num_nodes = 8
1375
1393
self .minerPos = 0
1376
1394
self .controllerPos = 1
1377
1395
self .setup_clean_chain = True
1378
1396
1379
- def add_new_dmn (self , strType , op_keys = None , from_out = None ):
1397
+ def add_new_dmn (self , strType , transparent = True , op_keys = None , from_out = None ):
1380
1398
self .mns .append (self .register_new_dmn (2 + len (self .mns ),
1381
1399
self .minerPos ,
1382
1400
self .controllerPos ,
1383
1401
strType ,
1402
+ transparent ,
1384
1403
outpoint = from_out ,
1385
1404
op_blskeys = op_keys ))
1386
1405
@@ -1440,10 +1459,14 @@ def setup_test(self):
1440
1459
# Create 6 DMNs and init the remote nodes
1441
1460
self .log .info ("Initializing masternodes..." )
1442
1461
for _ in range (2 ):
1443
- self .add_new_dmn ("internal" )
1462
+ self .add_new_dmn ("internal" , False )
1444
1463
self .add_new_dmn ("external" )
1445
1464
self .add_new_dmn ("fund" )
1446
1465
assert_equal (len (self .mns ), 6 )
1466
+ # Sanity check that we have 2 shielded masternodes
1467
+ assert_equal (len (self .nodes [self .controllerPos ].listlockunspent ()["shielded" ]), 2 )
1468
+ assert_equal (self .mns [0 ].transparent , False )
1469
+ assert_equal (self .mns [3 ].transparent , False )
1447
1470
for mn in self .mns :
1448
1471
self .nodes [mn .idx ].initmasternode (mn .operator_sk )
1449
1472
time .sleep (1 )
0 commit comments