def test_disaster_recovery(web3, prepared_contracts, transactions, signed, airdrops): """ Assuming transactions got sent partially, are we able to resume with confidence? """ _, omg_token = prepared_contracts unsent, unsent_unsigned = Sender(web3).recover_unsent(signed, transactions) assert unsent == signed assert unsent_unsigned == transactions Sender(web3).send_transactions(signed[:1], transactions[:1]) # airdrop partially done by now check_entirely_airdropped(airdrops[0:BATCH_SIZE], omg_token) # recovery unsent, unsent_unsigned = Sender(web3).recover_unsent(signed, transactions) assert len(unsent) == 1 assert len(unsent_unsigned) == 1 assert unsent[0] == signed[1] assert unsent_unsigned[0] == transactions[1] Sender(web3).send_transactions(unsent, unsent_unsigned) check_entirely_airdropped(airdrops, omg_token)
def test_logging(web3, prepared_contracts, transactions, signed, mocker): _, omg_token = prepared_contracts mocker.patch('logging.info') Sender(web3).send_transactions(signed, transactions) assert len(logging.info.call_args_list) == 4 * len(signed)
def reply_mail(account_id, mail_id): if request.method == 'POST': response_object = {'status': 'reply mail success'} Login.log('replying mail...') vertification = {} # find vertification of the account for account in ACCOUNTS: if account['id'] == account_id: vertification = account Login.log('find account: {}'.format((str)(vertification))) break # the posted data is in form of jsonified mail as sent to client, so do the reverse post_data = request.get_json() Sender.send_mail(vertification, post_data, account_id, mail_id) Login.log('Mail replied!') response_object.update({'message': 'Mail replied!'}) return jsonify(response_object)
def test_small_flow(web3, prepared_contracts, creator, airdrops): _, omg_token = prepared_contracts transactions = creator.create_txs(airdrops, BATCH_SIZE) signed = Signer(web3).sign_transactions(transactions) Sender(web3).send_transactions(signed, transactions) check_entirely_airdropped(airdrops, omg_token)
def test_check_amount_before_send(web3, creator, airdrops, signed): """ as above """ airdrops[0][1] += 1 different_transactions = creator.create_txs(airdrops, BATCH_SIZE) with pytest.raises(AirdropException): Sender(web3).send_transactions(signed, different_transactions)
def test_check_address_before_send(web3, creator, airdrops, signed): """ Tests whether the final check throws, in case local data differs from signed transactions """ airdrops[0][0] = web3.eth.accounts[0] different_transactions = creator.create_txs(airdrops, BATCH_SIZE) with pytest.raises(AirdropException): Sender(web3).send_transactions(signed, different_transactions)
def send_txs(ipc_path, rpc_host, rpc_port, recovery_mode, final_check_unsigned_file, signed_file): if ipc_path and (rpc_host or rpc_port): raise Exception("both ipc and rpc cannot be specified") if ipc_path: web3 = Web3(IPCProvider(ipc_path)) else: web3 = Web3(RPCProvider(host=rpc_host, port=rpc_port)) sender = Sender(web3) signed = json.loads(signed_file.read()) final_check_local_transactions = json.loads( final_check_unsigned_file.read()) if recovery_mode: signed, final_check_local_transactions = sender.recover_unsent( signed, final_check_local_transactions) sender.send_transactions(signed, final_check_local_transactions)
def test_oog_handling(web3, prepared_contracts, transactions, airdrops): """ Do we halt the sending when an oog occurs? """ _, omg_token = prepared_contracts transactions[0]['tx']['gas'] = web3.toHex(transactions[0]['gasEstimate'] - 1) signed = Signer(web3).sign_transactions(transactions) with pytest.raises(AirdropOOGException): Sender(web3).send_transactions(signed, transactions) check_none_airdropped(airdrops, omg_token) # check recovery works with OOG unsent, unsent_unsigned = Sender(web3).recover_unsent(signed, transactions) assert unsent == signed assert unsent_unsigned == transactions
def test_logging_failed_wait(web3, prepared_contracts, transactions, signed, mocker): _, omg_token = prepared_contracts mocker.patch('logging.info') mocker.patch('populus.wait.Wait.for_receipt') populus.wait.Wait.for_receipt.side_effect = [Exception] with pytest.raises(Exception): Sender(web3).send_transactions(signed, transactions) assert len(logging.info.call_args_list) == 2
def test_logging_failed_send(web3, prepared_contracts, transactions, signed, mocker): _, omg_token = prepared_contracts mocker.patch('logging.info') mocker.patch('web3.eth.Eth.sendRawTransaction') web3module.eth.Eth.sendRawTransaction.side_effect = [Exception] with pytest.raises(Exception): Sender(web3).send_transactions(signed, transactions) assert len(logging.info.call_args_list) == 1
def test_entire_flow(web3, prepared_contracts, creator, input_file): airdropper, omg_token = prepared_contracts airdrops = process(input_file.read()) transactions = creator.create_txs(airdrops, BATCH_SIZE) # this being a long-running test, the unlocking from web3 fixture might have expired web3.personal.unlockAccount(web3.eth.accounts[0], "") signed = Signer(web3).sign_transactions(transactions) Sender(web3).send_transactions(signed, transactions) check_entirely_airdropped(airdrops, omg_token)
def test_recover_sent_airdrops(web3, prepared_contracts, transactions, signed, airdrops, creator): """ Assuming partially sent airdrops, when there's need to sign transactions again e.g. when it turned out that too little gas was allowed (unlikely) """ airdropper, omg_token = prepared_contracts Sender(web3).send_transactions(signed[:1], transactions[:1]) # airdrop partially done by now check_entirely_airdropped(airdrops[0:BATCH_SIZE], omg_token) not_airdropped = Sender(web3).recover_unsent_airdrops( airdrops, signed, airdropper, omg_token) assert not_airdropped == airdrops[BATCH_SIZE:] unsigned = creator.create_txs(not_airdropped, BATCH_SIZE) new_signed = Signer(web3).sign_transactions(unsigned) Sender(web3).send_transactions(new_signed, unsigned) check_entirely_airdropped(airdrops, omg_token)
def test_secondary_oog_protection(web3, transactions, mocker): """ "Do we halt the sending when an oog occurs?" - continued. Check the secondary, double-checking protection """ transactions[0]['tx']['gas'] = web3.toHex(transactions[0]['gasEstimate'] - 1) signed = Signer(web3).sign_transactions(transactions) # check the secondary OOG-detection measure, by tricking the primary mocker.patch('utils.Sender._did_oog') Sender._did_oog.side_effect = [False, False] with pytest.raises(AirdropOOGException): Sender(web3).send_transactions(signed, transactions)
def test_throw_in_contract_handling(web3, prepared_contracts, transactions, airdrops): _, omg_token = prepared_contracts # whoops, omg_token got paused! omg_token should throw now pause_tx_hash = omg_token.transact().pause() Wait(web3).for_receipt(pause_tx_hash) # need to bump nonce in the pre-prepared transactions for transaction in transactions: transaction['tx']['nonce'] = web3.toHex( web3.toDecimal(transaction['tx']['nonce']) + 1) signed = Signer(web3).sign_transactions(transactions) with pytest.raises(AirdropOOGException): Sender(web3).send_transactions(signed, transactions) check_none_airdropped(airdrops, omg_token)
def test_sender(): Sender.__test()
def send_mail(account_id): if request.method == 'POST': response_object = {'status': 'send mail success'} Login.log('sending mail...') vertification = {} # find vertification of the account for account in ACCOUNTS: if account['id'] == account_id: vertification = account Login.log('find account: {}'.format((str)(vertification))) break # the posted data is in form of jsonified mail as sent to client, so do the reverse post_data = request.get_json() Sender.send_mail(vertification, post_data) Login.log('Mail sent!') response_object.update({'message': 'Mail sent!'}) return jsonify(response_object) else: # GET, when getting mails # print('get_mails: {}'.format(account_id)) response_object = {'status': 'get mail success'} account = {} mails = [] for single_account in ACCOUNTS: if single_account['id'] == account_id: account = single_account break #### if there are mails of the account, clear them #### this step appears only removes mails on the odd position #### temporarily, the function cannot work properly, thus I choose to reset the MAILS every time client logins # for mail in MAILS: # print(mail['Subject']) # print(mail['account_id']) # for mail in MAILS: # if (str)(mail['account_id']) == (str)(account_id): # # print('remove duplicated mail {}'.format(mail['Subject'])) # MAILS.remove(mail) MAILS.clear() #### get mails of the account mail_link = Login.login(account, True) # raw_mails = Mails.retrMail(mail_link, end_retr_num=60, start_retr_num=10) # retrieve all the mails raw_mails = Mails.retrMail(mail_link) account_mails = Mails.contentSeparator(account_id, raw_mails) for raw_mail, account_mail in zip(raw_mails, account_mails): mail_id = uuid.uuid4().hex Mails.__save_raw_mails(raw_mail, account_id, mail_id) account_mail['id'] = mail_id account_mail['account_id'] = account_id MAILS.append(account_mail) #### return mails #### NOTICE: the function is designed to dynamically send mail to client at 100 a time #### and in reverse for mail in MAILS: if mail['account_id'] == account_id: if 'Subject' in mail.keys(): Login.log('find mail! {}'.format(mail['Subject'])) else: Login.log('find mail without Subject!\n{}'.format( (str)(mail))) mails.append(mail) mails.reverse() response_object['mails'] = mails return jsonify(response_object)