Skip to content

Commit 16c0fef

Browse files
committed
Functional test
1 parent 8edc005 commit 16c0fef

File tree

5 files changed

+181
-69
lines changed

5 files changed

+181
-69
lines changed

src/consensus/upgrades.cpp

+64-60
Original file line numberDiff line numberDiff line change
@@ -13,66 +13,70 @@
1313
* We are using it in the -nuparams startup arg and input it with spaces is just ugly.
1414
*/
1515
const struct NUInfo NetworkUpgradeInfo[Consensus::MAX_NETWORK_UPGRADES] = {
16-
{
17-
/*.strName =*/ "Base",
18-
/*.strInfo =*/ "PIVX network",
19-
},
20-
{
21-
/*.strName =*/ "PoS",
22-
/*.strInfo =*/ "Proof of Stake Consensus activation",
23-
},
24-
{
25-
/*.strName =*/ "PoS_v2",
26-
/*.strInfo =*/ "New selection for stake modifier",
27-
},
28-
{
29-
/*.strName =*/ "Zerocoin",
30-
/*.strInfo =*/ "ZeroCoin protocol activation - start block v4",
31-
},
32-
{
33-
/*.strName =*/ "Zerocoin_v2",
34-
/*.strInfo =*/ "New zerocoin serials and zPOS start",
35-
},
36-
{
37-
/*.strName =*/ "BIP65",
38-
/*.strInfo =*/ "CLTV (BIP65) activation - start block v5",
39-
},
40-
{
41-
/*.strName =*/ "Zerocoin_Public",
42-
/*.strInfo =*/ "Activation of zerocoin public spends (spend v3)",
43-
},
44-
{
45-
/*.strName =*/ "PIVX_v3.4",
46-
/*.strInfo =*/ "New 256-bit stake modifier - start block v6",
47-
},
48-
{
49-
/*.strName =*/ "PIVX_v4.0",
50-
/*.strInfo =*/ "New message sigs - start block v7 - time protocol - zc spend v4",
51-
},
52-
{
53-
/*.strName =*/ "v5_shield",
54-
/*.strInfo =*/ "Sapling Shield - start block v8 - start transaction v3",
55-
},
56-
{
57-
/*.strName =*/ "PIVX_v5.2",
58-
/*.strInfo =*/ "New cold-staking rules",
59-
},
60-
{
61-
/*.strName =*/ "PIVX_v5.3",
62-
/*.strInfo =*/ "New staking rules",
63-
},
64-
{
65-
/*.strName =*/ "PIVX_v5.5",
66-
/*.strInfo =*/ "New rewards structure",
67-
},
68-
{
69-
/*.strName =*/ "v6_evo",
70-
/*.strInfo =*/ "Deterministic Masternodes",
71-
},
72-
{
73-
/*.strName =*/ "Test_dummy",
74-
/*.strInfo =*/ "Test dummy info",
75-
},
16+
{
17+
/*.strName =*/"Base",
18+
/*.strInfo =*/"PIVX network",
19+
},
20+
{
21+
/*.strName =*/"PoS",
22+
/*.strInfo =*/"Proof of Stake Consensus activation",
23+
},
24+
{
25+
/*.strName =*/"PoS_v2",
26+
/*.strInfo =*/"New selection for stake modifier",
27+
},
28+
{
29+
/*.strName =*/"Zerocoin",
30+
/*.strInfo =*/"ZeroCoin protocol activation - start block v4",
31+
},
32+
{
33+
/*.strName =*/"Zerocoin_v2",
34+
/*.strInfo =*/"New zerocoin serials and zPOS start",
35+
},
36+
{
37+
/*.strName =*/"BIP65",
38+
/*.strInfo =*/"CLTV (BIP65) activation - start block v5",
39+
},
40+
{
41+
/*.strName =*/"Zerocoin_Public",
42+
/*.strInfo =*/"Activation of zerocoin public spends (spend v3)",
43+
},
44+
{
45+
/*.strName =*/"PIVX_v3.4",
46+
/*.strInfo =*/"New 256-bit stake modifier - start block v6",
47+
},
48+
{
49+
/*.strName =*/"PIVX_v4.0",
50+
/*.strInfo =*/"New message sigs - start block v7 - time protocol - zc spend v4",
51+
},
52+
{
53+
/*.strName =*/"v5_shield",
54+
/*.strInfo =*/"Sapling Shield - start block v8 - start transaction v3",
55+
},
56+
{
57+
/*.strName =*/"PIVX_v5.2",
58+
/*.strInfo =*/"New cold-staking rules",
59+
},
60+
{
61+
/*.strName =*/"PIVX_v5.3",
62+
/*.strInfo =*/"New staking rules",
63+
},
64+
{
65+
/*.strName =*/"PIVX_v5.5",
66+
/*.strInfo =*/"New rewards structure",
67+
},
68+
{
69+
/*.strName =*/"v6_evo",
70+
/*.strInfo =*/"Deterministic Masternodes",
71+
},
72+
{
73+
/*.strName =*/"shield_staking",
74+
/*.strInfo =*/"Shield Staking",
75+
},
76+
{
77+
/*.strName =*/"Test_dummy",
78+
/*.strInfo =*/"Test dummy info",
79+
},
7680
};
7781

7882
UpgradeState NetworkUpgradeState(

test/functional/mining_pos_coldStaking.py

+6-6
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ def run_test(self):
9292
assert self.nodes[1].lockunspent(False, True, [{"txid": x['txid'], "vout": x['vout']}])
9393
# check that it cannot stake
9494
sleep(1)
95-
assert_equal(self.nodes[1].getstakingstatus()["stakeablecoins"], 0)
95+
assert_equal(self.nodes[1].getstakingstatus()["transparent_stakeable_coins"], 0)
9696
# create shielded balance for node 0
9797
self.log.info("Shielding some coins for node0...")
9898
self.nodes[0].shieldsendmany("from_transparent", [{"address": self.nodes[0].getnewshieldaddress(),
@@ -205,7 +205,7 @@ def run_test(self):
205205
# -----------------------------------------------------------
206206
print("*** 7 ***")
207207
self.log.info("Trying to generate a cold-stake block before whitelisting the owner...")
208-
assert_equal(self.nodes[1].getstakingstatus()["stakeablecoins"], 0)
208+
assert_equal(self.nodes[1].getstakingstatus()["transparent_stakeable_coins"], 0)
209209
assert_equal(self.nodes[1].listdelegators(), [])
210210
self.log.info("Nice. Cold staker was NOT able to create the block yet.")
211211

@@ -232,7 +232,7 @@ def run_test(self):
232232
# 9) check that the staker can use the coins to stake a block with internal miner.
233233
# --------------------------------------------------------------------------------
234234
print("*** 9 ***")
235-
assert_equal(self.nodes[1].getstakingstatus()["stakeablecoins"], NUM_OF_INPUTS-1)
235+
assert_equal(self.nodes[1].getstakingstatus()["transparent_stakeable_coins"], NUM_OF_INPUTS-1)
236236
self.log.info("Generating one valid cold-stake block...")
237237
self.mocktime = self.generate_pos(1, self.mocktime)
238238
self.log.info("New block created by cold-staking. Trying to submit...")
@@ -338,12 +338,12 @@ def run_test(self):
338338
assert ret
339339
assert_equal(self.nodes[1].listdelegators(), [])
340340
assert_equal(self.nodes[1].listdelegators(True)[0]["address"], owner_address)
341-
assert_equal(self.nodes[1].getstakingstatus()["stakeablecoins"], 0)
341+
assert_equal(self.nodes[1].getstakingstatus()["transparent_stakeable_coins"], 0)
342342
self.log.info("Re-enable delegation")
343343
ret = self.nodes[1].delegatoradd(owner_address)
344344
assert ret
345345
assert_equal(self.nodes[1].listdelegators()[0]["address"], owner_address)
346-
assert_equal(self.nodes[1].getstakingstatus()["stakeablecoins"], len(stakeable_coins))
346+
assert_equal(self.nodes[1].getstakingstatus()["transparent_stakeable_coins"], len(stakeable_coins))
347347
self.log.info("Cancel the stake delegation spending the delegated utxos...")
348348
delegated_utxos = getDelegatedUtxos(self.nodes[0].listunspent())
349349
# remove one utxo to spend later
@@ -379,7 +379,7 @@ def run_test(self):
379379
# -----------------------------------------------------------
380380
print("*** 14 ***")
381381
self.log.info("Trying to generate one cold-stake block again...")
382-
assert_equal(self.nodes[1].getstakingstatus()["stakeablecoins"], 0)
382+
assert_equal(self.nodes[1].getstakingstatus()["transparent_stakeable_coins"], 0)
383383
self.log.info("Good. Cold staker was NOT able to create any more blocks.")
384384

385385
# 15) check balances when mature.

test/functional/mining_shield_pos.py

+106
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
#!/usr/bin/env python3
2+
# Copyright (c) 2023 The PIVX Core developers
3+
# Distributed under the MIT software license, see the accompanying
4+
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
5+
6+
from test_framework.test_framework import PivxTestFramework
7+
from test_framework.authproxy import JSONRPCException
8+
from test_framework.util import (
9+
assert_equal,
10+
assert_greater_than,
11+
assert_raises_rpc_error,
12+
disconnect_nodes,
13+
)
14+
import time
15+
16+
17+
class PIVX_ShieldStakingTest(PivxTestFramework):
18+
19+
def generate_shield_pos(self, node_id):
20+
assert_greater_than(len(self.nodes), node_id)
21+
rpc_conn = self.nodes[node_id]
22+
ss = rpc_conn.getstakingstatus()
23+
assert ss["walletunlocked"]
24+
assert ss["shield_stakeables_notes"] > 0
25+
assert ss["shield_staking_balance"] > 0.0
26+
fStaked = False
27+
failures = 0
28+
while not fStaked:
29+
try:
30+
res = rpc_conn.generate(1)
31+
fStaked = True
32+
return res
33+
except JSONRPCException as e:
34+
if ("Couldn't create new block" in str(e)):
35+
failures += 1
36+
# couldn't generate block. check that this node can still stake (after 60 failures)
37+
if failures > 60:
38+
ss = rpc_conn.getstakingstatus()
39+
if not (ss["walletunlocked"] and ss["shield_stakeables_notes"] > 0 and ss["shield_staking_balance"] > 0.0):
40+
raise AssertionError("Node %d unable to stake!" % node_id)
41+
# try to stake one sec in the future
42+
time.sleep(1)
43+
else:
44+
raise e
45+
46+
def set_test_params(self):
47+
self.num_nodes = 3
48+
self.setup_clean_chain = True
49+
50+
def run_test(self):
51+
self.log.info("Shield stake functional tests")
52+
53+
# Mine enough blocks to activate shield staking" + a bonus so node0 has enough pivs to mine the final block
54+
self.nodes[0].generate(800)
55+
self.sync_all()
56+
57+
# Send some shielded notes to node1
58+
saplingAddr1 = self.nodes[1].getnewshieldaddress()
59+
txid = self.nodes[0].sendtoaddress(saplingAddr1, 40000, "", "", True)
60+
61+
# Generate more blocks so the shield notes becomes stakeable
62+
self.nodes[0].generate(20)
63+
self.sync_all()
64+
65+
# Sanity check, shield staking is activated
66+
assert_equal(self.nodes[0].getblockchaininfo()['upgrades']['v5 shield']['status'], 'active')
67+
assert_equal(self.nodes[0].getblockchaininfo()['upgrades']['v6 evo']['status'], 'active')
68+
assert_equal(self.nodes[0].getblockchaininfo()['upgrades']['shield staking']['status'], 'active')
69+
70+
# Node1 has exactly one shield stakeable note
71+
assert_equal(self.nodes[1].getstakingstatus()['shield_stakeables_notes'], 1)
72+
assert_equal(self.nodes[1].getstakingstatus()['transparent_stakeable_coins'], 0)
73+
74+
# Before generating the shield stake block isolate node 2:
75+
disconnect_nodes(self.nodes[0], 2)
76+
disconnect_nodes(self.nodes[2], 0)
77+
disconnect_nodes(self.nodes[1], 2)
78+
disconnect_nodes(self.nodes[2], 1)
79+
80+
# Generate the block and check that reward is 4 shield PIVs
81+
initialBalance = self.nodes[1].getshieldbalance()
82+
shieldStakeBlockHash = self.generate_shield_pos(1)[0]
83+
assert_equal(self.nodes[1].getshieldbalance()-initialBalance, 4)
84+
85+
# Check that a loose coinShieldStakeTx cannot go in mempool
86+
coinShieldStakeTxHash = self.nodes[1].getblock(shieldStakeBlockHash)['tx'][1]
87+
coinShieldStakeTxHex = self.nodes[1].gettransaction(coinShieldStakeTxHash)['hex']
88+
assert_raises_rpc_error(-26, "coinshieldstake", self.nodes[2].sendrawtransaction, coinShieldStakeTxHex)
89+
90+
# Check that node0 accepted the block:
91+
self.sync_all(self.nodes[0:2])
92+
assert_equal(self.nodes[1].getblockhash(821), shieldStakeBlockHash)
93+
assert_equal(self.nodes[0].getblockhash(821), shieldStakeBlockHash)
94+
95+
# Finally verify that the reward can be spent:
96+
recipient = [{"address": self.nodes[0].getnewshieldaddress(), "amount": (initialBalance+2)}]
97+
txid = self.nodes[1].shieldsendmany("from_shield", recipient)
98+
self.sync_all(self.nodes[0:2])
99+
blockHash = self.nodes[0].generate(1)[0]
100+
self.sync_all(self.nodes[0:2])
101+
assert (txid in self.nodes[0].getblock(blockHash)['tx'])
102+
assert_equal(self.nodes[1].getblockhash(822), blockHash)
103+
104+
105+
if __name__ == '__main__':
106+
PIVX_ShieldStakingTest().main()

test/functional/test_framework/test_framework.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -886,8 +886,8 @@ def generate_pos(self, node_id, btime=None):
886886
rpc_conn = self.nodes[node_id]
887887
ss = rpc_conn.getstakingstatus()
888888
assert ss["walletunlocked"]
889-
assert ss["stakeablecoins"] > 0
890-
assert ss["stakingbalance"] > 0.0
889+
assert ss["transparent_stakeable_coins"] > 0
890+
assert ss["transparent_staking_balance"] > 0.0
891891
if btime is not None:
892892
next_btime = btime + 60
893893
fStaked = False
@@ -902,7 +902,7 @@ def generate_pos(self, node_id, btime=None):
902902
# couldn't generate block. check that this node can still stake (after 60 failures)
903903
if failures > 60:
904904
ss = rpc_conn.getstakingstatus()
905-
if not (ss["walletunlocked"] and ss["stakeablecoins"] > 0 and ss["stakingbalance"] > 0.0):
905+
if not (ss["walletunlocked"] and ss["transparent_stakeable_coins"] > 0 and ss["transparent_staking_balance"] > 0.0):
906906
raise AssertionError("Node %d unable to stake!" % node_id)
907907
# try to stake one sec in the future
908908
if btime is not None:

test/functional/test_runner.py

+2
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@
9494
'rpc_bind.py --nonloopback', # ~ 126 sec
9595
'feature_uacomment.py', # ~ 125 sec
9696
'interface_rest.py', # ~ 120 sec
97+
'mining_shield_pos.py', # ~ 120 sec
9798

9899
# vv Tests less than 2m vv
99100
'wallet_upgrade.py', # ~ 119 sec
@@ -220,6 +221,7 @@
220221
'mempool_reorg.py',
221222
'mempool_resurrect.py',
222223
'mempool_spend_coinbase.py',
224+
'mining_shield_pos.py',
223225
'p2p_disconnect_ban.py',
224226
'p2p_time_offset.py',
225227
'rpc_bip38.py',

0 commit comments

Comments
 (0)