def recycle_accounts(nonce: int): logging.debug('Recycling Accounts') dynamodb = boto3.resource('dynamodb') recycle_table = dynamodb.Table(os.environ['RECYCLE_TABLE_NAME']) response = recycle_table.scan() for item in response['Items']: funder = item['funder'] signer = item['signer'] unlock = item.get('unlock', 0) logging.debug(f'Processing item: Funder: {funder} Signer: {signer} Unlock: {unlock}') amount, escrow, actual_unlock = look(funder, signer) latest_block = get_latest_block() logging.debug(f'Actual Unlock: {actual_unlock}') if unlock != actual_unlock: logging.debug(f'Updating unlock from {unlock} to {actual_unlock}') store_account(funder, signer, actual_unlock) if actual_unlock == 0: logging.debug('Account is still locked') warn(signer, nonce) nonce += 1 elif actual_unlock - 1 < latest_block['timestamp']: logging.debug( f'Account ({signer}) is unlocked ({unlock - 1} < {latest_block["timestamp"]}). ' 'Initiating pull()' ) pull( signer=signer, target=funder, autolock=True, amount=amount, escrow=escrow, nonce=nonce, ) nonce += 1 # kill( # signer=signer, # nonce=nonce, # ) # nonce += 1 delete_account(signer=signer) else: logging.debug(f'Account ({signer}) is still in the process of unlocking.')
def main(event, context): stage = os.environ['STAGE'] body = json.loads(event.get('body', {})) if is_true(body.get('debug', '')): configure_logging(level="DEBUG") logging.debug(f'recycle() stage:{stage}') logging.debug(f'event: {event}') logging.debug(f'context: {context}') logging.debug(f'body: {body}') funder = toChecksumAddress(address=body.get('funder', '')) signer = toChecksumAddress(address=body.get('signer', '')) password = body.get('password', '') if password != get_secret(key=os.environ['RECYCLE_KEY']): return incorrect_password() pac_funder = get_secret(key=os.environ['PAC_FUNDER_PUBKEY_SECRET']) if funder != pac_funder: return invalid_funder(funder, pac_funder) funder_keys = keys(funder) if signer == '' or signer not in funder_keys: return invalid_signer(signer) amount, escrow, unlock = look(funder, signer) amount_threshold = float("inf") escrow_threshold = float("inf") if amount > amount_threshold: return amount_too_high(amount, amount_threshold) if escrow > escrow_threshold: return escrow_too_high(escrow, escrow_threshold) store_account(funder, signer, unlock) return account_queued_response()
def get_account_( price: float, blocknum: int) -> Tuple[Optional[str], Optional[str], Optional[str]]: logging.debug(f'get_account_ price:{price}') dynamodb = boto3.resource('dynamodb') table = dynamodb.Table(os.environ['TABLE_NAME']) response = random_scan(table, price) ret = None signer_pubkey = '0xTODO' epoch_time = int(time.time()) for item in response['Items']: if float(price) == float(item['price']): signer_pubkey = item['signer'] config = item['config'] push_txn_hash = item['push_txn_hash'] creation_etime = item.get('creation_etime', 0) age = epoch_time - creation_etime if is_true(os.environ['DOUBLE_CHECK_ACCOUNTS']): old_status = item['status'] status = get_transaction_status(push_txn_hash, blocknum) if old_status != status: logging.warning( f'DynamoDB status of {old_status} for {push_txn_hash} ' f'does not match new status of {status}!') else: status = item['status'] if ((status != 'confirmed') and (age < 10 * 60 * 60)): # 10 hour grace period logging.debug( f'Skipping account ({push_txn_hash}) with status: {status} age: {age}' ) continue logging.debug( f'Found potential account ({push_txn_hash}) status: {status} age:{age} config: {config}' ) key = { 'price': item['price'], 'signer': signer_pubkey, } delete_response = table.delete_item(Key=key, ReturnValues='ALL_OLD') if (delete_response['Attributes'] is not None and len(delete_response['Attributes']) > 0): balance, escrow, _ = look( funder=get_secret( key=os.environ['PAC_FUNDER_PUBKEY_SECRET']), signer=signer_pubkey, ) # update succeeded if ((status == 'confirmed') and (escrow > get_min_escrow())): ret = push_txn_hash, config, signer_pubkey break else: logging.debug( f'broken account: {push_txn_hash} status: {status} age: {age} ' f'balance: {balance} deleted and skipped') else: logging.debug('Account was already deleted!') if ret: return ret return None, None, None