Skip to content

Commit

Permalink
Add OCG voting scenarios
Browse files Browse the repository at this point in the history
  • Loading branch information
Jouzo committed Jan 26, 2023
1 parent 314cf76 commit a342fc9
Show file tree
Hide file tree
Showing 2 changed files with 169 additions and 0 deletions.
168 changes: 168 additions & 0 deletions test/functional/feature_on_chain_government_voting_scenarios.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
#!/usr/bin/env python3
# Copyright (c) 2014-2019 The Bitcoin Core developers
# Copyright (c) DeFi Blockchain Developers
# Distributed under the MIT software license, see the accompanying
# file LICENSE or http://www.opensource.org/licenses/mit-license.php.
"""Test OCG voting scenarios"""

from test_framework.test_framework import DefiTestFramework
from test_framework.util import (
assert_equal,
)

APPROVAL_THRESHOLD=50
QUORUM=50
VOTING_PERIOD = 30

class OCGVotingScenarionTest(DefiTestFramework):
def set_test_params(self):
self.num_nodes = 1
self.setup_clean_chain = True
self.extra_args = [
['-jellyfish_regtest=1', '-dummypos=0', '-txnotokens=0', '-amkheight=50', '-bayfrontheight=51', '-eunosheight=80', '-fortcanningheight=82', '-fortcanninghillheight=84', '-fortcanningroadheight=86', '-fortcanningcrunchheight=88', '-fortcanningspringheight=90', '-fortcanninggreatworldheight=94', '-grandcentralheight=101'],
]

def setup_masternodes(self, nMasternodes = 19):
self.nodes[0].mns = []

for _ in range(nMasternodes):
address = self.nodes[0].getnewaddress('', 'legacy')
mnId = self.nodes[0].createmasternode(address)
self.nodes[0].generate(1)
self.nodes[0].mns.append([mnId, self.nodes[0].getmasternode(mnId)[mnId]])

self.nodes[0].generate(20) # Enables all MNs
self.sync_blocks(timeout=120)

# restart node with masternode_operator addresses to be able to mint with every MNs
self.restart_node(0, self.nodes[0].extra_args + ['-masternode_operator={}'.format(mnData['operatorAuthAddress']) for [_, mnData] in self.nodes[0].mns])

def setup(self):
# Generate chain
self.nodes[0].generate(100)
self.sync_blocks(timeout=120)

self.setup_masternodes()

# activate on-chain governance
self.nodes[0].setgov({"ATTRIBUTES":{
'v0/params/feature/gov':'true',
'v0/gov/proposals/voting_period': '{}'.format(VOTING_PERIOD),
}})
self.nodes[0].generate(1)

def test_vote_on_cfp(self, yesVote, noVote, neutralVote, expectedStatus):
height = self.nodes[0].getblockcount()

# Create address for CFP
address = self.nodes[0].getnewaddress()
context = "<Git issue url>"
title = "Create test community fund proposal"
amount = 100

# Create CFP
propId = self.nodes[0].creategovcfp({"title": title, "context": context, "amount": amount, "cycles": 1, "payoutAddress": address})
self.nodes[0].generate(1)

mnIterator = iter(self.nodes[0].mns)

for _ in range(yesVote):
[mnId, data] = next(mnIterator)
self.nodes[0].generatetoaddress(1, data['operatorAuthAddress'])
self.nodes[0].votegov(propId, mnId, 'yes')

for _ in range(noVote):
[mnId, data] = next(mnIterator)
self.nodes[0].generatetoaddress(1, data['operatorAuthAddress'])
self.nodes[0].votegov(propId, mnId, 'no')

for _ in range(neutralVote):
[mnId, data] = next(mnIterator)
self.nodes[0].generatetoaddress(1, data['operatorAuthAddress'])
self.nodes[0].votegov(propId, mnId, 'neutral')

# Mint with every remaining MNs lest their vote are not counted in quorum
for [mnId, data] in mnIterator:
self.nodes[0].generatetoaddress(1, data['operatorAuthAddress'])

self.nodes[0].generate(1)

self.nodes[0].generate(VOTING_PERIOD)
proposal = self.nodes[0].getgovproposal(propId)

assert_equal(proposal['status'], expectedStatus)

self.rollback_to(height)

def test_scenario_below_approval_threshold(self):
self.test_vote_on_cfp(yesVote=8, noVote=6, neutralVote=2, expectedStatus='Rejected')

# Currently marked as Rejected as neutral votes are incorrectly counted as no
# Should assert that it's Completed once https://github.com/DeFiCh/ain/issues/1704 is fixed
def test_scenario_at_approval_threshold(self):
self.test_vote_on_cfp(yesVote=8, noVote=6, neutralVote=2, expectedStatus='Rejected')

def test_scenario_above_approval_threshold(self):
self.test_vote_on_cfp(yesVote=10, noVote=6, neutralVote=2, expectedStatus='Completed')

def test_scenario_below_quorum(self):
self.test_vote_on_cfp(yesVote=6, noVote=2, neutralVote=1, expectedStatus='Rejected')

def test_scenario_at_quorum(self):
self.test_vote_on_cfp(yesVote=6, noVote=2, neutralVote=2, expectedStatus='Rejected')

def test_scenario_above_quorum(self):
self.test_vote_on_cfp(yesVote=6, noVote=3, neutralVote=2, expectedStatus='Completed')

# Currently marked as Rejected as neutral votes are incorrectly counted as no
# Should assert that it's Completed once https://github.com/DeFiCh/ain/issues/1704 is fixed
def test_scenario_high_neutral_vote(self):
self.test_vote_on_cfp(yesVote=8, noVote=3, neutralVote=5, expectedStatus='Rejected')

def test_scenario_66_6_percent_approval_full_yes_votes(self):
self.test_vote_on_cfp(yesVote=len(self.nodes[0].mns), noVote=0, neutralVote=0, expectedStatus='Completed')

def test_scenario_66_6_percent_approval_full_no_votes(self):
self.test_vote_on_cfp(yesVote=0, noVote=len(self.nodes[0].mns), neutralVote=0, expectedStatus='Rejected')

def test_scenario_66_6_percent_approval_full_neutral_votes(self):
self.test_vote_on_cfp(yesVote=0, noVote=0, neutralVote=len(self.nodes[0].mns), expectedStatus='Rejected')

def scenarios_test(self):
self.nodes[0].setgov({"ATTRIBUTES":{
'v0/gov/proposals/cfp_approval_threshold':'{}%'.format(APPROVAL_THRESHOLD),
}})
self.nodes[0].generate(1)

self.test_scenario_below_approval_threshold()
self.test_scenario_at_approval_threshold()
self.test_scenario_above_approval_threshold()

self.nodes[0].setgov({"ATTRIBUTES":{
'v0/gov/proposals/quorum':'{}%'.format(QUORUM),
}})
self.nodes[0].generate(1)

self.test_scenario_below_quorum()
self.test_scenario_at_quorum()
self.test_scenario_above_quorum()

self.test_scenario_high_neutral_vote()

self.nodes[0].setgov({"ATTRIBUTES":{
'v0/gov/proposals/cfp_approval_threshold':'{}%'.format(66.6),
}})
self.nodes[0].generate(1)

self.test_scenario_66_6_percent_approval_full_yes_votes()
self.test_scenario_66_6_percent_approval_full_no_votes()
self.test_scenario_66_6_percent_approval_full_neutral_votes()

def run_test(self):

self.setup()

self.scenarios_test()

if __name__ == '__main__':
OCGVotingScenarionTest().main ()
1 change: 1 addition & 0 deletions test/functional/test_runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,7 @@
'feature_on_chain_government.py',
'feature_on_chain_government_voting_period_alignment.py',
'feature_on_chain_government_fee_distribution.py',
'feature_on_chain_government_voting_scenarios.py',
'rpc_listgovproposals.py',
'rpc_help.py',
'feature_help.py',
Expand Down

0 comments on commit a342fc9

Please sign in to comment.