def run_test(self):
    self.log.info('Wait for DIP3 to activate')
    while (get_bip9_status(self.nodes[0], 'dip0003')['status'] != 'active'):
        self.bump_mocktime(10)
        self.nodes[0].generate(10)
    self.nodes[0].add_p2p_connection(P2PDataStore())
    network_thread_start()
    self.nodes[0].p2p.wait_for_verack()
    self.log.info('Mine all but one remaining block in the window')
    bi = self.nodes[0].getblockchaininfo()
    for i in range((498 - bi['blocks'])):
        self.bump_mocktime(1)
        self.nodes[0].generate(1)
    self.log.info('Initial state is DEFINED')
    bi = self.nodes[0].getblockchaininfo()
    assert_equal(bi['blocks'], 498)
    assert_equal(bi['bip9_softforks']['realloc']['status'], 'defined')
    self.log.info('Advance from DEFINED to STARTED at height = 499')
    self.nodes[0].generate(1)
    bi = self.nodes[0].getblockchaininfo()
    assert_equal(bi['blocks'], 499)
    assert_equal(bi['bip9_softforks']['realloc']['status'], 'started')
    assert_equal(bi['bip9_softforks']['realloc']['statistics']['threshold'], self.threshold(0))
    self.signal(399, False)
    self.log.info('Still STARTED but new threshold should be lower at height = 999')
    bi = self.nodes[0].getblockchaininfo()
    assert_equal(bi['blocks'], 999)
    assert_equal(bi['bip9_softforks']['realloc']['statistics']['threshold'], self.threshold(1))
    self.signal(398, False)
    self.log.info('Still STARTED but new threshold should be even lower at height = 1499')
    bi = self.nodes[0].getblockchaininfo()
    assert_equal(bi['blocks'], 1499)
    assert_equal(bi['bip9_softforks']['realloc']['statistics']['threshold'], self.threshold(2))
    pre_locked_in_blockhash = bi['bestblockhash']
    self.signal(396, True)
    self.log.info('Advanced to LOCKED_IN at height = 1999')
    for i in range(49):
        self.bump_mocktime(10)
        self.nodes[0].generate(10)
    self.nodes[0].generate(9)
    self.log.info('Still LOCKED_IN at height = 2498')
    bi = self.nodes[0].getblockchaininfo()
    assert_equal(bi['blocks'], 2498)
    assert_equal(bi['bip9_softforks']['realloc']['status'], 'locked_in')
    self.log.info('Advance from LOCKED_IN to ACTIVE at height = 2499')
    self.nodes[0].generate(1)
    bi = self.nodes[0].getblockchaininfo()
    assert_equal(bi['blocks'], 2499)
    assert_equal(bi['bip9_softforks']['realloc']['status'], 'active')
    assert_equal(bi['bip9_softforks']['realloc']['since'], 2500)
    self.log.info('Reward split should stay ~50/50 before the first superblock after activation')
    bt = self.nodes[0].getblocktemplate()
    assert_equal(bt['height'], 2500)
    assert_equal(bt['masternode'][0]['amount'], get_masternode_payment(bt['height'], bt['coinbasevalue'], 2500))
    self.nodes[0].generate(9)
    bt = self.nodes[0].getblocktemplate()
    assert_equal(bt['masternode'][0]['amount'], get_masternode_payment(bt['height'], bt['coinbasevalue'], 2500))
    assert_equal(bt['coinbasevalue'], 13748571607)
    assert_equal(bt['masternode'][0]['amount'], 6874285801)
    self.log.info('Reallocation should kick-in with the superblock mined at height = 2010')
    for period in range(19):
        for i in range(3):
            self.bump_mocktime(10)
            self.nodes[0].generate(10)
            bt = self.nodes[0].getblocktemplate()
            assert_equal(bt['masternode'][0]['amount'], get_masternode_payment(bt['height'], bt['coinbasevalue'], 2500))
    self.log.info('Reward split should reach ~60/40 after reallocation is done')
    assert_equal(bt['coinbasevalue'], 10221599170)
    assert_equal(bt['masternode'][0]['amount'], 6132959502)
    self.log.info('Reward split should stay ~60/40 after reallocation is done')
    for period in range(10):
        self.bump_mocktime(10)
        self.nodes[0].generate(10)
        bt = self.nodes[0].getblocktemplate()
        assert_equal(bt['masternode'][0]['amount'], get_masternode_payment(bt['height'], bt['coinbasevalue'], 2500))
    assert_equal(bt['coinbasevalue'], 9491484944)
    assert_equal(bt['masternode'][0]['amount'], 5694890966)
    self.sync_all()
    self.log.info('Rollback the chain back to the STARTED state')
    self.mocktime = self.nodes[0].getblock(pre_locked_in_blockhash, 1)['time']
    for node in self.nodes:
        node.invalidateblock(pre_locked_in_blockhash)
    test_block = self.create_test_block()
    self.nodes[0].submitblock(ToHex(test_block))
    bi = self.nodes[0].getblockchaininfo()
    assert_equal(bi['blocks'], 1499)
    assert_equal(bi['bip9_softforks']['realloc']['status'], 'started')
    assert_equal(bi['bip9_softforks']['realloc']['statistics']['threshold'], self.threshold(2))
    self.log.info('Check thresholds reach min level and stay there')
    for i in range(8):
        self.signal(0, False)
        bi = self.nodes[0].getblockchaininfo()
        assert_equal(bi['blocks'], (1999 + (i * 500)))
        assert_equal(bi['bip9_softforks']['realloc']['status'], 'started')
        assert_equal(bi['bip9_softforks']['realloc']['statistics']['threshold'], self.threshold((i + 3)))
    assert_equal(bi['bip9_softforks']['realloc']['statistics']['threshold'], 300)
def run_test(self):
    self.log.info('Wait for DIP3 to activate')
    while (get_bip9_status(self.nodes[0], 'dip0003')['status'] != 'active'):
        self.bump_mocktime(10)
        self.nodes[0].generate(10)
    self.nodes[0].add_p2p_connection(P2PDataStore())
    network_thread_start()
    self.nodes[0].p2p.wait_for_verack()
    self.log.info('Mine all but one remaining block in the window')
    bi = self.nodes[0].getblockchaininfo()
    for i in range((498 - bi['blocks'])):
        self.bump_mocktime(1)
        self.nodes[0].generate(1)
    self.log.info('Initial state is DEFINED')
    bi = self.nodes[0].getblockchaininfo()
    assert_equal(bi['blocks'], 498)
    assert_equal(bi['bip9_softforks']['realloc']['status'], 'defined')
    self.log.info('Advance from DEFINED to STARTED at height = 499')
    self.nodes[0].generate(1)
    bi = self.nodes[0].getblockchaininfo()
    assert_equal(bi['blocks'], 499)
    assert_equal(bi['bip9_softforks']['realloc']['status'], 'started')
    assert_equal(bi['bip9_softforks']['realloc']['statistics']['threshold'], self.threshold(0))
    self.signal(399, False)
    self.log.info('Still STARTED but new threshold should be lower at height = 999')
    bi = self.nodes[0].getblockchaininfo()
    assert_equal(bi['blocks'], 999)
    assert_equal(bi['bip9_softforks']['realloc']['statistics']['threshold'], self.threshold(1))
    self.signal(398, False)
    self.log.info('Still STARTED but new threshold should be even lower at height = 1499')
    bi = self.nodes[0].getblockchaininfo()
    assert_equal(bi['blocks'], 1499)
    assert_equal(bi['bip9_softforks']['realloc']['statistics']['threshold'], self.threshold(2))
    pre_locked_in_blockhash = bi['bestblockhash']
    self.signal(396, True)
    self.log.info('Advanced to LOCKED_IN at height = 1999')
    for i in range(49):
        self.bump_mocktime(10)
        self.nodes[0].generate(10)
    self.nodes[0].generate(9)
    self.log.info('Still LOCKED_IN at height = 2498')
    bi = self.nodes[0].getblockchaininfo()
    assert_equal(bi['blocks'], 2498)
    assert_equal(bi['bip9_softforks']['realloc']['status'], 'locked_in')
    self.log.info('Advance from LOCKED_IN to ACTIVE at height = 2499')
    self.nodes[0].generate(1)
    bi = self.nodes[0].getblockchaininfo()
    assert_equal(bi['blocks'], 2499)
    assert_equal(bi['bip9_softforks']['realloc']['status'], 'active')
    assert_equal(bi['bip9_softforks']['realloc']['since'], 2500)
    self.log.info('Reward split should stay ~50/50 before the first superblock after activation')
    bt = self.nodes[0].getblocktemplate()
    assert_equal(bt['height'], 2500)
    assert_equal(bt['masternode'][0]['amount'], get_masternode_payment(bt['height'], bt['coinbasevalue'], 2500))
    self.nodes[0].generate(9)
    bt = self.nodes[0].getblocktemplate()
    assert_equal(bt['masternode'][0]['amount'], get_masternode_payment(bt['height'], bt['coinbasevalue'], 2500))
    assert_equal(bt['coinbasevalue'], 13748571607)
    assert_equal(bt['masternode'][0]['amount'], 6874285801)
    self.log.info('Reallocation should kick-in with the superblock mined at height = 2010')
    for period in range(19):
        for i in range(3):
            self.bump_mocktime(10)
            self.nodes[0].generate(10)
            bt = self.nodes[0].getblocktemplate()
            assert_equal(bt['masternode'][0]['amount'], get_masternode_payment(bt['height'], bt['coinbasevalue'], 2500))
    self.log.info('Reward split should reach ~60/40 after reallocation is done')
    assert_equal(bt['coinbasevalue'], 10221599170)
    assert_equal(bt['masternode'][0]['amount'], 6132959502)
    self.log.info('Reward split should stay ~60/40 after reallocation is done')
    for period in range(10):
        self.bump_mocktime(10)
        self.nodes[0].generate(10)
        bt = self.nodes[0].getblocktemplate()
        assert_equal(bt['masternode'][0]['amount'], get_masternode_payment(bt['height'], bt['coinbasevalue'], 2500))
    assert_equal(bt['coinbasevalue'], 9491484944)
    assert_equal(bt['masternode'][0]['amount'], 5694890966)
    self.sync_all()
    self.log.info('Rollback the chain back to the STARTED state')
    self.mocktime = self.nodes[0].getblock(pre_locked_in_blockhash, 1)['time']
    for node in self.nodes:
        node.invalidateblock(pre_locked_in_blockhash)
    test_block = self.create_test_block()
    self.nodes[0].submitblock(ToHex(test_block))
    bi = self.nodes[0].getblockchaininfo()
    assert_equal(bi['blocks'], 1499)
    assert_equal(bi['bip9_softforks']['realloc']['status'], 'started')
    assert_equal(bi['bip9_softforks']['realloc']['statistics']['threshold'], self.threshold(2))
    self.log.info('Check thresholds reach min level and stay there')
    for i in range(8):
        self.signal(0, False)
        bi = self.nodes[0].getblockchaininfo()
        assert_equal(bi['blocks'], (1999 + (i * 500)))
        assert_equal(bi['bip9_softforks']['realloc']['status'], 'started')
        assert_equal(bi['bip9_softforks']['realloc']['statistics']['threshold'], self.threshold((i + 3)))
    assert_equal(bi['bip9_softforks']['realloc']['statistics']['threshold'], 300)