def test_prepare_testnet_observer(self): testargs = ['coldstakepool-prepare', '--datadir=~/csp_testnet_obs', '--testnet', '--mode=observer', '--configurl=file://' + os.path.expanduser('~/csp_testnet/stakepool/stakepool.json')] with patch.object(sys, 'argv', testargs): prepareSystem.main() with open(os.path.expanduser('~/csp_testnet_obs/stakepool/stakepool.json')) as fp: settings = json.load(fp) assert(settings['mode'] == 'observer')
def test_mode_no_url(self): testargs = ['coldstakepool-prepare', '--mode=observer'] with patch('sys.stderr', new=StringIO()) as fake_stderr: with patch.object(sys, 'argv', testargs): with self.assertRaises(SystemExit) as cm: prepareSystem.main() self.assertEqual(cm.exception.code, 1) self.assertTrue('observer mode requires configurl' in fake_stderr.getvalue())
def test_prepare(self): testargs = ['coldstakepool-prepare', '--datadir=~/csp_mainnet', '--mainnet'] with patch.object(sys, 'argv', testargs): prepareSystem.main() # Should fail when run on existing dir with patch('sys.stderr', new=StringIO()) as fake_stderr: with patch.object(sys, 'argv', testargs): with self.assertRaises(SystemExit) as cm: prepareSystem.main() self.assertEqual(cm.exception.code, 1) self.assertTrue('particl.conf exists' in fake_stderr.getvalue())
def test_prepare_regtest(self): testargs = ['coldstakepool-prepare', '--datadir=~/csp_regtest', '--regtest'] with patch.object(sys, 'argv', testargs): prepareSystem.main()
def test_regtest(self): testargs = [ 'coldstakepool-prepare', '--datadir={}/csp_regtest'.format(TEST_DIR), '--regtest' ] with patch.object(sys, 'argv', testargs): prepareSystem.main() settings_path = os.path.join(TEST_DIR, 'csp_regtest', 'stakepool', 'stakepool.json') with open(settings_path) as fs: pool_settings = json.load(fs) pool_settings['startheight'] = 0 pool_settings['parameters'][0]['payoutthreshold'] = 0.005 pool_settings['parameters'][0]['minblocksbetweenpayments'] = 10 with open(settings_path, 'w') as fp: json.dump(pool_settings, fp, indent=4) for i in range(NUM_NODES - 1): prepareDataDir(TEST_DIR, i, 'particl.conf') with open(os.path.join(TEST_DIR, 'csp_regtest', 'particl.conf'), 'a') as fp: fp.write('addnode=127.0.0.1:{}\n'.format(BASE_PORT + i)) self.daemons.append( startDaemon(os.path.join(TEST_DIR, str(i)), PARTICL_BINDIR, PARTICLD)) logging.info('Started %s %d', PARTICLD, self.daemons[-1].pid) waitForRPC(make_rpc_func(i)) callnoderpc(i, 'reservebalance', [True, 1000000]) callnoderpc(i, 'walletsettings', [ 'stakingoptions', { 'stakecombinethreshold': 100, 'stakesplitthreshold': 200 } ]) # Start pool daemon self.daemons.append( startDaemon( os.path.join(TEST_DIR, 'csp_regtest'), PARTICL_BINDIR, PARTICLD, opts=['-noprinttoconsole', '-stakethreadconddelayms=1000'])) logging.info('Started %s %d', PARTICLD, self.daemons[-1].pid) self.processes.append( multiprocessing.Process(target=self.run_pool, args=(testargs, ))) self.processes[-1].start() callnoderpc(0, 'extkeyimportmaster', [ 'abandon baby cabbage dad eager fabric gadget habit ice kangaroo lab absorb' ]) assert (callnoderpc(0, 'getwalletinfo')['total_balance'] == 100000) callnoderpc(1, 'extkeyimportmaster', [ 'pact mammal barrel matrix local final lecture chunk wasp survey bid various book strong spread fall ozone daring like topple door fatigue limb olympic', '', 'true' ]) callnoderpc(1, 'getnewextaddress', ['lblExtTest']) callnoderpc(1, 'rescanblockchain') assert (callnoderpc(1, 'getwalletinfo')['total_balance'] == 25000) # Wait for pool daemon to start authcookiepath = os.path.join(TEST_DIR, 'csp_regtest', 'regtest', '.cookie') for i in range(10): if not os.path.exists(authcookiepath): time.sleep(0.5) with open(authcookiepath) as fp: pool_rpc_auth = fp.read() pool_rpc_port = 51936 for i in range(5): try: staking_options = callrpc(pool_rpc_port, pool_rpc_auth, 'walletsettings', ['stakingoptions'], wallet='pool_stake') break except Exception as e: logging.info('Waiting for stakepool to start %s', str(e)) time.sleep(1) staking_options = staking_options['stakingoptions'] staking_options['stakecombinethreshold'] = 100 staking_options['stakesplitthreshold'] = 200 staking_options['enabled'] = False staking_options = callrpc(pool_rpc_port, pool_rpc_auth, 'walletsettings', ['stakingoptions', staking_options], wallet='pool_stake') staking_options = callrpc(pool_rpc_port, pool_rpc_auth, 'walletsettings', ['stakingoptions'], wallet='pool_stake')['stakingoptions'] assert (staking_options['stakecombinethreshold'] == 100) for i in range(5): try: with urllib.request.urlopen( 'http://localhost:9001/config') as conn: page = conn.read().decode('utf8') except Exception as e: logging.info('Waiting for stakepool http server to start %s', str(e)) time.sleep(1) pool_config = json.loads(page) addr_pool_stake = pool_config['pooladdress'] callnoderpc(0, 'createwallet', ['pool']) callnoderpc(0, 'createwallet', ['pool_reward']) callnoderpc(0, 'createwallet', ['MS Wallet']) # Wallet name containing spaces callnoderpc(1, 'createwallet', ['pool']) callnoderpc(0, 'extkeyimportmaster', [callnoderpc(0, 'mnemonic', ['new'])['mnemonic']], wallet='pool') callnoderpc(0, 'extkeyimportmaster', [callnoderpc(0, 'mnemonic', ['new'])['mnemonic']], wallet='pool_reward') callnoderpc(0, 'extkeyimportmaster', [callnoderpc(0, 'mnemonic', ['new'])['mnemonic']], wallet='MS Wallet') callnoderpc(1, 'extkeyimportmaster', [callnoderpc(1, 'mnemonic', ['new'])['mnemonic']], wallet='pool') callnoderpc(0, 'walletsettings', ['stakingoptions', { 'enabled': 'false' }], wallet='pool') callnoderpc(0, 'walletsettings', ['stakingoptions', { 'enabled': 'false' }], wallet='pool_reward') callnoderpc(0, 'walletsettings', ['stakingoptions', { 'enabled': 'false' }], wallet='MS Wallet') callnoderpc(1, 'walletsettings', ['stakingoptions', { 'enabled': 'false' }], wallet='pool') sxaddrnode0 = callnoderpc(0, 'getnewstealthaddress', wallet='pool_reward') ms_addrs = [] ms_pubkeys = [] ms_addrs.append(callnoderpc(0, 'getnewaddress', wallet='pool')) ms_addrs.append(callnoderpc(0, 'getnewaddress', wallet='MS Wallet')) ms_addrs.append(callnoderpc(1, 'getnewaddress', wallet='pool')) ms_pubkeys.append( callnoderpc(0, 'getaddressinfo', [ms_addrs[0]], wallet='pool')['pubkey']) ms_pubkeys.append( callnoderpc(0, 'getaddressinfo', [ms_addrs[1]], wallet='MS Wallet')['pubkey']) ms_pubkeys.append( callnoderpc(1, 'getaddressinfo', [ms_addrs[2]], wallet='pool')['pubkey']) ms_addr = callnoderpc(0, 'addmultisigaddress', [2, ms_pubkeys], wallet='MS Wallet') callnoderpc(0, 'importaddress', [ ms_addr['redeemScript'], ], wallet='MS Wallet') logging.info('ms_addr %s', ms_addr['address']) pool_addrs_1 = [] pool_addrs_1.append( callnoderpc(1, 'getnewaddress', ['pooled_spend', False, False, True], wallet='pool')) pool_addrs_1.append( callnoderpc(1, 'getnewaddress', ['pooled_spend', False, False, True], wallet='pool')) pool_addrs_1.append( callnoderpc(1, 'getnewaddress', ['pooled_spend', False, False, True], wallet='pool')) recipe = { 'recipe': 'ifcoinstake', 'addrstake': addr_pool_stake, 'addrspend': pool_addrs_1[0] } toScript1 = callnoderpc(0, 'buildscript', [recipe]) recipe = { 'recipe': 'ifcoinstake', 'addrstake': addr_pool_stake, 'addrspend': pool_addrs_1[1] } toScript2 = callnoderpc(1, 'buildscript', [recipe]) recipe = { 'recipe': 'ifcoinstake', 'addrstake': addr_pool_stake, 'addrspend': pool_addrs_1[2] } toScript3 = callnoderpc(1, 'buildscript', [recipe]) recipe = { 'recipe': 'ifcoinstake', 'addrstake': addr_pool_stake, 'addrspend': ms_addr['address'] } toScript4 = callnoderpc(1, 'buildscript', [recipe]) outputs_node1 = [ { 'address': 'script', 'amount': 5000, 'script': toScript1['hex'], }, { 'address': 'script', 'amount': 5000, 'script': toScript2['hex'], }, { 'address': 'script', 'amount': 20, 'script': toScript3['hex'], }, { 'address': 'script', 'amount': 10000, 'script': toScript4['hex'], }, ] pool_addrs_0 = [] txids = [] outputs = [] for i in range(2): pool_addrs_0.append( callnoderpc(0, 'getnewaddress', ['pool', False, False, True], wallet='pool')) recipe = { 'recipe': 'ifcoinstake', 'addrstake': addr_pool_stake, 'addrspend': pool_addrs_0[-1] } toScript = callnoderpc(0, 'buildscript', [recipe]) outputs.append({ 'address': 'script', 'amount': 10000, 'script': toScript['hex'], }) txids.append( callnoderpc(0, 'sendtypeto', ['part', 'part', outputs], wallet='')) outputs = [] for i in range(600): pool_addrs_0.append( callnoderpc(0, 'getnewaddress', ['pool', False, False, True], wallet='pool')) recipe = { 'recipe': 'ifcoinstake', 'addrstake': addr_pool_stake, 'addrspend': pool_addrs_0[-1] } toScript = callnoderpc(0, 'buildscript', [recipe]) outputs.append({ 'address': 'script', 'amount': 100, 'script': toScript['hex'], }) txids.append( callnoderpc(0, 'sendtypeto', ['part', 'part', outputs], wallet='')) # Faster than waiting for mempool for txid in txids: txhex = callnoderpc(0, 'getrawtransaction', [txid], wallet='') callrpc(pool_rpc_port, pool_rpc_auth, 'sendrawtransaction', [txhex]) callnoderpc(1, 'sendrawtransaction', [txhex]) logging.info( 'Staking a block from node1 to confirm txns from node0 to pool') callnoderpc(1, 'reservebalance', [False], wallet='') callnoderpc(1, 'walletsettings', ['stakelimit', { 'height': 1 }], wallet='') for i in range(10): r = callnoderpc(0, 'getblockchaininfo') print('btc1', r['blocks']) if r['blocks'] > 0: break time.sleep(1) assert (r['blocks'] > 0) # Send coin from node1 to pool txid = callnoderpc(1, 'sendtypeto', ['part', 'part', outputs_node1], wallet='') callrpc(pool_rpc_port, pool_rpc_auth, 'sendrawtransaction', [callnoderpc(1, 'getrawtransaction', [txid], wallet='')]) staking_options['enabled'] = True rv = callrpc(pool_rpc_port, pool_rpc_auth, 'walletsettings', ['stakingoptions', staking_options], wallet='pool_stake') stake_blocks = 150 rv = callrpc(pool_rpc_port, pool_rpc_auth, 'walletsettings', ['stakelimit', { 'height': stake_blocks }], wallet='pool_stake') logging.info('Pool staking to block %d', stake_blocks) addr_node_1 = callnoderpc(1, 'getnewaddress', wallet='') for i in range(600): r = callrpc(pool_rpc_port, pool_rpc_auth, 'getblockchaininfo') logging.info('blocks: %d', r['blocks']) if r['blocks'] >= stake_blocks: break # Add some fees if i < 20: rv = callnoderpc(0, 'sendtoaddress', [addr_node_1, 0.1], wallet='') time.sleep(1) # Wait for pool to be synced to chain for i in range(30): with urllib.request.urlopen('http://localhost:9001/json') as conn: pool_end = json.loads(conn.read().decode('utf8')) logging.info('poolheight: %d', pool_end['poolheight']) if stake_blocks - 100 == pool_end['poolheight']: break time.sleep(1) accum_block_rewards = 0 for i in range(2, pool_end['poolheight'] + 1): rv = callrpc(pool_rpc_port, pool_rpc_auth, 'getblockreward', [i]) accum_block_rewards += make_int(rv['blockreward']) logging.info('accum_block_rewards: %d', accum_block_rewards) total_addr_accum = 0 total_addr_pending = 0 total_addr_paid = 0 for addr in pool_addrs_0 + pool_addrs_1 + [ ms_addr['address'], ]: with urllib.request.urlopen('http://localhost:9001/json/address/' + addr) as conn: r = json.loads(conn.read().decode('utf8')) if 'accumulated' in r: total_addr_accum += r['accumulated'] if 'rewardpending' in r: total_addr_pending += r['rewardpending'] if 'rewardpaidout' in r: total_addr_paid += r['rewardpaidout'] logging.info('total_addr_accum: %d', total_addr_accum) logging.info('total_addr_pending: %d', total_addr_pending) logging.info('total_addr_paid: %d', total_addr_paid) total_pool_users = total_addr_accum // COIN + total_addr_pending + total_addr_paid logging.info('accum_block_rewards: %d', accum_block_rewards) logging.info('poolrewardtotal: %d', pool_end['poolrewardtotal']) total_pool_users = total_pool_users total_pool = total_pool_users + pool_end['poolrewardtotal'] logging.info('total_pool_users + pool_reward: %d', total_pool) assert (abs(accum_block_rewards - total_pool) < 10) changeaddress = { 'coldstakingaddress': addr_pool_stake, 'address_standard': ms_addr['address'] } callnoderpc(0, 'walletsettings', ['changeaddress', changeaddress], wallet='MS Wallet') addr_out = callnoderpc(1, 'getnewaddress', wallet='') rawtx = callnoderpc(0, 'createrawtransaction', [[], { addr_out: 1.0 }], wallet='MS Wallet') funded_tx = callnoderpc(0, 'fundrawtransaction', [rawtx, { 'includeWatching': True }], wallet='MS Wallet') callnoderpc(0, 'importaddress', [ ms_addr['redeemScript'], ], wallet='pool') stx1 = callnoderpc(0, 'signrawtransactionwithwallet', [funded_tx['hex']], wallet='pool') stx2 = callnoderpc(0, 'signrawtransactionwithwallet', [stx1['hex']], wallet='MS Wallet') tx = callnoderpc(0, 'decoderawtransaction', [stx2['hex']], wallet='MS Wallet') change_n = 1 if tx['vout'][0]['scriptPubKey']['addresses'][ 0] == addr_out else 0 assert (tx['vout'][change_n]['scriptPubKey']['addresses'][0] == ms_addr['address']) addr_pool_stake_plain = callnoderpc( 0, 'validateaddress', [addr_pool_stake, True])['base58_address'] assert (tx['vout'][change_n]['scriptPubKey']['stakeaddresses'][0] == addr_pool_stake_plain) txid = callnoderpc(0, 'sendrawtransaction', [stx2['hex']]) logging.info('Spent from ms addr in tx: %s', txid)