def scheduler(): Alarm = get_contract('Alarm') CallerPool = get_contract('CallerPool') alarm = Alarm(alarm_address, rpc_client) caller_pool = CallerPool(alarm.getCallerPoolAddress.call(), rpc_client) block_sage = BlockSage(rpc_client) pool_manager = PoolManager(caller_pool, block_sage=block_sage) pool_manager.monitor_async() scheduler = Scheduler(alarm, pool_manager, block_sage=block_sage) scheduler.monitor_async() try: while scheduler._thread.is_alive(): time.sleep(1) except KeyboardInterrupt: scheduler.stop() scheduler.block_sage.stop() scheduler.pool_manager.stop() for scheduled_call in scheduler.active_calls.values(): scheduled_call.stop() scheduler._thread.join(5)
def scheduler(address): """ Run the call scheduler. """ Alarm = get_contract('Alarm') alarm = Alarm(address, rpc_client) block_sage = BlockSage(rpc_client) pool_manager = PoolManager(alarm, block_sage=block_sage) pool_manager.monitor_async() scheduler = Scheduler(alarm, pool_manager, block_sage=block_sage) scheduler.monitor_async() try: while scheduler._thread.is_alive(): time.sleep(1) except KeyboardInterrupt: scheduler.stop() scheduler.block_sage.stop() scheduler.pool_manager.stop() for scheduled_call in scheduler.active_calls.values(): scheduled_call.stop() scheduler._thread.join(5)
def scheduler(address): """ Run the call scheduler. """ Alarm = get_contract('Scheduler') alarm = Alarm(address, rpc_client) block_sage = BlockSage(rpc_client) pool_manager = PoolManager(alarm, block_sage=block_sage) pool_manager.monitor_async() scheduler = Scheduler(alarm, pool_manager, block_sage=block_sage) scheduler.monitor_async() try: while scheduler._thread.is_alive(): time.sleep(1) except KeyboardInterrupt: scheduler.stop() scheduler.block_sage.stop() scheduler.pool_manager.stop() for scheduled_call in scheduler.active_calls.values(): scheduled_call.stop() scheduler._thread.join(5)
def pool_minimum(denomination, address): """ Check the current minimum bond balance. """ Alarm = get_contract('Alarm') alarm = Alarm(address, rpc_client) pool_manager = PoolManager(alarm) minimum_bond = pool_manager.minimum_bond click.echo("Minimum Bond: {0}".format( convert_wei_to_denomination(minimum_bond, denomination), ))
def pool_balance(denomination, address): """ Check your bond balance with the caller pool. """ Alarm = get_contract('Alarm') alarm = Alarm(address, rpc_client) pool_manager = PoolManager(alarm) balance = pool_manager.bond_balance click.echo("Balance: {0}".format( convert_wei_to_denomination(balance, denomination), ))
def pool_status(address): """ Display some status information about the caller pools. """ Alarm = get_contract('Scheduler') alarm = Alarm(address, rpc_client) pool_manager = PoolManager(alarm) status_msg = ( "Current Block : {b}\n" "Current Generation : {ap} - {ap_m} - ({ap_s})\n" "Next Generation : {np} - {np_m} - ({np_s})" ).format( b=pool_manager.block_sage.current_block_number, ap=(pool_manager.current_generation_id or "N/A"), ap_m=pool_manager.get_generation_size(pool_manager.current_generation_id), ap_s="member" if pool_manager.in_current_generation else "not member", np=(pool_manager.next_generation_id or "N/A"), np_m=pool_manager.get_generation_size(pool_manager.next_generation_id), np_s="member" if pool_manager.in_next_generation else "not member", ) click.echo(status_msg)
def pool_status(): Alarm = get_contract('Alarm') alarm = Alarm(alarm_address, rpc_client) CallerPool = get_contract('CallerPool') caller_pool = CallerPool(alarm.getCallerPoolAddress.call(), rpc_client) pool_manager = PoolManager(caller_pool) status_msg = ( "Current Block: {b}\n" "Active Pool: {ap} - {ap_m} - ({ap_s})\n" "Next Pool : {np} - {np_m} - ({np_s})" ).format( b=pool_manager.block_sage.current_block_number, ap=(pool_manager.active_pool or "N/A"), ap_m=pool_manager.get_pool_size(pool_manager.active_pool), ap_s="member" if pool_manager.in_active_pool else "not member", np=(pool_manager.next_pool or "N/A"), np_m=pool_manager.get_pool_size(pool_manager.next_pool), np_s="member" if pool_manager.in_next_pool else "not member", ) click.echo(status_msg)
def pool_status(address): """ Display some status information about the caller pools. """ Alarm = get_contract('Alarm') alarm = Alarm(address, rpc_client) pool_manager = PoolManager(alarm) status_msg = ("Current Block : {b}\n" "Current Generation : {ap} - {ap_m} - ({ap_s})\n" "Next Generation : {np} - {np_m} - ({np_s})").format( b=pool_manager.block_sage.current_block_number, ap=(pool_manager.current_generation_id or "N/A"), ap_m=pool_manager.get_generation_size( pool_manager.current_generation_id), ap_s="member" if pool_manager.in_current_generation else "not member", np=(pool_manager.next_generation_id or "N/A"), np_m=pool_manager.get_generation_size( pool_manager.next_generation_id), np_s="member" if pool_manager.in_next_generation else "not member", ) click.echo(status_msg)
def test_scheduled_call_execution_without_pool(geth_node, geth_node_config, deploy_client, deployed_contracts, contracts): alarm = deployed_contracts.Alarm client_contract = deployed_contracts.SpecifyBlock deposit_amount = get_max_gas(deploy_client) * deploy_client.get_gas_price() * 20 alarm.deposit.sendTransaction(client_contract._meta.address, value=deposit_amount) target_block = deploy_client.get_block_number() + 45 txn_hash = client_contract.scheduleIt.sendTransaction(alarm._meta.address, target_block) wait_for_transaction(deploy_client, txn_hash) call_key = alarm.getLastCallKey() assert call_key is not None scheduled_call = ScheduledCall(alarm, call_key) block_sage = scheduled_call.block_sage pool_manager = PoolManager(alarm, block_sage=block_sage) time.sleep(1) assert pool_manager.in_any_pool is False scheduled_call.execute_async() # let the scheduled call do it's thing. assert block_sage.current_block_number < target_block wait_till = scheduled_call.target_block + 10 wait_for_block( deploy_client, wait_till, 2 * block_sage.estimated_time_to_block(wait_till), ) for i in range(5): if scheduled_call.txn_hash: break time.sleep(block_sage.block_time) assert scheduled_call.txn_hash assert scheduled_call.txn_receipt assert scheduled_call.txn assert alarm.checkIfCalled(scheduled_call.call_key) assert scheduled_call.was_called assert scheduled_call.target_block <= scheduled_call.called_at_block assert scheduled_call.called_at_block <= scheduled_call.target_block + scheduled_call.grace_period
def test_scheduler(geth_node, geth_node_config, deploy_client, deployed_contracts, contracts): block_sage = BlockSage(deploy_client) alarm = deployed_contracts.Alarm client_contract = deployed_contracts.SpecifyBlock deposit_amount = get_max_gas( deploy_client) * deploy_client.get_gas_price() * 20 alarm.deposit.sendTransaction(client_contract._meta.address, value=deposit_amount) anchor_block = deploy_client.get_block_number() blocks = (1, 4, 4, 8, 30, 40, 50, 60) call_keys = [] for n in blocks: wait_for_transaction( deploy_client, client_contract.scheduleIt.sendTransaction(alarm._meta.address, anchor_block + 100 + n)) last_call_key = alarm.getLastCallKey() assert last_call_key is not None call_keys.append(last_call_key) pool_manager = PoolManager(alarm, block_sage) scheduler = Scheduler(alarm, pool_manager, block_sage=block_sage) scheduler.monitor_async() final_block = anchor_block + 100 + 70 wait_for_block( deploy_client, final_block, 2 * block_sage.estimated_time_to_block(final_block), ) scheduler.stop() block_sage.stop() results = [alarm.checkIfCalled(k) for k in call_keys] assert all(results)
def test_scheduled_call_execution_with_pool(geth_node, geth_coinbase, geth_node_config, deploy_client, deployed_contracts, contracts): alarm = deployed_contracts.Alarm joiner = deployed_contracts.JoinsPool client_contract = deployed_contracts.SpecifyBlock coinbase = geth_coinbase block_sage = BlockSage(deploy_client) # Put in our deposit with the alarm contract. deposit_amount = get_max_gas( deploy_client) * deploy_client.get_gas_price() * 20 alarm.deposit.sendTransaction(client_contract._meta.address, value=deposit_amount) wait_for_transaction( deploy_client, joiner.setCallerPool.sendTransaction(alarm._meta.address)) assert alarm.getBondBalance(coinbase) == 0 bond_amount = alarm.getMinimumBond() * 10 # Put in our bond wait_for_transaction(deploy_client, alarm.depositBond.sendTransaction(value=bond_amount)) # Put the contract's bond in wait_for_transaction( deploy_client, deploy_client.send_transaction(to=joiner._meta.address, value=bond_amount)) wait_for_transaction(deploy_client, joiner.deposit.sendTransaction(bond_amount)) # Both join the pool wait_for_transaction(deploy_client, joiner.enter.sendTransaction()) wait_for_transaction(deploy_client, alarm.enterPool.sendTransaction()) # New pool is formed but not active first_generation_id = alarm.getNextGenerationId() assert first_generation_id > 0 # Go ahead and schedule the call. generation_start_at = alarm.getGenerationStartAt(first_generation_id) target_block = generation_start_at + 5 txn_hash = client_contract.scheduleIt.sendTransaction( alarm._meta.address, target_block) wait_for_transaction(deploy_client, txn_hash) # Wait for the pool to become active wait_for_block( deploy_client, generation_start_at, 2 * block_sage.estimated_time_to_block(generation_start_at), ) # We should both be in the pool assert alarm.getCurrentGenerationId() == first_generation_id assert alarm.isInGeneration(joiner._meta.address, first_generation_id) is True assert alarm.isInGeneration(coinbase, first_generation_id) is True call_key = alarm.getLastCallKey() assert call_key is not None scheduled_call = ScheduledCall(alarm, call_key, block_sage=block_sage) pool_manager = PoolManager(alarm, block_sage=block_sage) scheduled_call.execute_async() wait_for_block( deploy_client, scheduled_call.target_block, 2 * block_sage.estimated_time_to_block(scheduled_call.target_block), ) for i in range(alarm.getCallWindowSize() * 2): if scheduled_call.txn_hash: break time.sleep(block_sage.block_time) assert scheduled_call.txn_hash assert scheduled_call.txn_receipt assert scheduled_call.txn assert scheduled_call.was_called assert alarm.checkIfCalled(scheduled_call.call_key) assert scheduled_call.target_block <= scheduled_call.called_at_block assert scheduled_call.called_at_block <= scheduled_call.target_block + scheduled_call.grace_period
help="Deposit the bond amount in wei into the CallerPool", ) @click.option( '--address', '-a', default=DEFAULT_ADDRESS, help="Return the current bond balance from the caller pool.", ) @click.argument('value', type=click.INT) def pool_deposit(async, address, value): """ Deposit an amount in wei into your caller pool bond balance. """ Alarm = get_contract('Alarm') alarm = Alarm(address, rpc_client) pool_manager = PoolManager(alarm) msg = ( "Do you want to deposit {0} into the bond balance for the CallerPool " "contract at `{1}` for the address `{2}`").format( value, alarm._meta.address, pool_manager.coinbase) if click.confirm(msg): txn_hash = alarm.depositBond.sendTransaction(value=value) else: click.echo("Deposit cancelled") click.exit(1) if async: wait_for_transaction(rpc_client, txn_hash) click.echo(
def test_pool_manager(deploy_client, deployed_contracts): scheduler = deployed_contracts.Scheduler deposit_amount = scheduler.getMinimumBond.call() * 10 # Put in our bond deploy_client.wait_for_transaction( scheduler.depositBond.sendTransaction(value=deposit_amount) ) pool_manager = PoolManager(scheduler) block_sage = pool_manager.block_sage # should be no pools, nor anyone in them. assert pool_manager.current_generation_id == 0 assert pool_manager.next_generation_id == 0 assert pool_manager.in_any_pool is False assert pool_manager.in_next_generation is False assert pool_manager.in_current_generation is False # check permissions assert pool_manager.can_enter_pool is True assert pool_manager.can_exit_pool is False pool_manager.monitor_async() # Wait a few blocks for the pool manager to spin up. for _ in range(5): deploy_client.evm.mine() time.sleep(1) first_generation_id = pool_manager.next_generation_id # should have initiated joining the next pool but won't be in it yet. assert pool_manager.current_generation_id == 0 assert first_generation_id > 0 assert pool_manager.in_any_pool is True assert pool_manager.in_next_generation is True assert pool_manager.in_current_generation is False # check permissions assert pool_manager.can_enter_pool is False assert pool_manager.can_exit_pool is False # Wait for the pool to become active. deploy_client.wait_for_block(pool_manager.next_generation_start_at) # we should now be in the active pool. assert pool_manager.current_generation_id == first_generation_id assert pool_manager.next_generation_id == 0 assert pool_manager.in_any_pool is True assert pool_manager.in_next_generation is False assert pool_manager.in_current_generation is True # check permissions assert pool_manager.can_enter_pool is False assert pool_manager.can_exit_pool is True # Now we manually remove ourselves. deploy_client.wait_for_transaction(scheduler.exitPool.sendTransaction()) second_generation_id = pool_manager.next_generation_id # New pool should have been formed. assert second_generation_id > first_generation_id # Current status should not have changed except that the next pool has now # been formed but we aren't in it. assert pool_manager.in_any_pool is True assert pool_manager.in_next_generation is False assert pool_manager.in_current_generation is True # Wait for the next pool to become active plus a little. first_generation_end = scheduler.getGenerationEndAt(first_generation_id) deploy_client.wait_for_block( first_generation_end, block_sage.estimated_time_to_block(first_generation_end) * 2, ) # The manager should have rejoined. assert pool_manager.current_generation_id == second_generation_id
def test_pool_manager(deploy_client, deployed_contracts): alarm = deployed_contracts.Alarm coinbase = deploy_client.get_coinbase() deposit_amount = alarm.getMinimumBond.call() * 10 # Put in our bond wait_for_transaction( deploy_client, alarm.depositBond.sendTransaction(value=deposit_amount)) pool_manager = PoolManager(alarm) block_sage = pool_manager.block_sage # should be no pools, nor anyone in them. assert pool_manager.current_generation_id == 0 assert pool_manager.next_generation_id == 0 assert pool_manager.in_any_pool is False assert pool_manager.in_next_generation is False assert pool_manager.in_current_generation is False # check permissions assert pool_manager.can_enter_pool is True assert pool_manager.can_exit_pool is False pool_manager.monitor_async() # Wait a few blocks for the pool manager to spin up. for _ in range(5): deploy_client.evm.mine() time.sleep(5) first_generation_id = pool_manager.next_generation_id # should have initiated joining the next pool but won't be in it yet. assert pool_manager.current_generation_id == 0 assert first_generation_id > 0 assert pool_manager.in_any_pool is True assert pool_manager.in_next_generation is True assert pool_manager.in_current_generation is False # check permissions assert pool_manager.can_enter_pool is False assert pool_manager.can_exit_pool is False # Wait for the pool to become active. for _ in range(deploy_client.get_block_number(), pool_manager.next_generation_start_at): deploy_client.evm.mine() # we should now be in the active pool. assert pool_manager.current_generation_id == first_generation_id assert pool_manager.next_generation_id == 0 assert pool_manager.in_any_pool is True assert pool_manager.in_next_generation is False assert pool_manager.in_current_generation is True # check permissions assert pool_manager.can_enter_pool is False assert pool_manager.can_exit_pool is True # Now we manually remove ourselves. wait_for_transaction(deploy_client, alarm.exitPool.sendTransaction()) second_generation_id = pool_manager.next_generation_id # New pool should have been formed. assert second_generation_id > first_generation_id # Current status should not have changed except that the next pool has now # been formed but we aren't in it. assert pool_manager.in_any_pool is True assert pool_manager.in_next_generation is False assert pool_manager.in_current_generation is True # Wait for the next pool to become active plus a little. first_generation_end = alarm.getGenerationEndAt(first_generation_id) deploy_client.wait_for_block( first_generation_end, block_sage.estimated_time_to_block(first_generation_end) * 2, ) # The manager should have rejoined. assert pool_manager.current_generation_id == second_generation_id