def test_pop_deletes_file(self): tx = build_transaction(wallet=Wallet(), processor='b' * 64, stamps=123, nonce=0, contract='currency', function='transfer', kwargs={ 'amount': 123, 'to': 'jeff' }) self.q.append(tx) tx2 = build_transaction(wallet=Wallet(), processor='b' * 64, stamps=123, nonce=0, contract='currency', function='transfer', kwargs={ 'amount': 123, 'to': 'jeff2' }) self.q.append(tx2) self.q.pop(0) self.assertEqual(len(self.q), 1)
def test_push_two_transaction_pop_gets_oldest_first(self): tx = build_transaction(wallet=Wallet(), processor='b' * 64, stamps=123, nonce=0, contract='currency', function='transfer', kwargs={ 'amount': 123, 'to': 'jeff' }) self.q.append(tx) tx2 = build_transaction(wallet=Wallet(), processor='b' * 64, stamps=123, nonce=0, contract='currency', function='transfer', kwargs={ 'amount': 123, 'to': 'jeff2' }) self.q.append(tx2) tx_2 = self.q.pop(0) self.assertEqual(decode(tx), tx_2)
def test_init_valid_doesnt_assert(self): build_transaction(wallet=Wallet(), processor='b' * 64, stamps=123, nonce=0, contract='currency', function='transfer', kwargs={ 'amount': 123, 'to': 'jeff' })
def test_init_invalid_format_raises_assert(self): with self.assertRaises(AssertionError): build_transaction(wallet=Wallet(), processor='b' * 65, stamps=123, nonce=0, contract='currency', function='transfer', kwargs={ 'amount': 123.0, 'to': 'jeff' })
def test_sign_works_properly(self): w = Wallet() tx = build_transaction( wallet=w, processor='b' * 64, stamps=123, nonce=0, contract='currency', function='transfer', kwargs={ 'amount': 123, 'to': 'jeff' } ) decoded = decode(tx) res = verify( w.verifying_key, encode(decoded['payload']), decoded['metadata']['signature'] ) self.assertTrue(res)
def test_transaction_is_valid_complete_test_passes(self): w = Wallet() tx = build_transaction(wallet=w, processor='b' * 64, stamps=123, nonce=0, contract='currency', function='transfer', kwargs={ 'amount': 123, 'to': 'jeff' }) decoded = decode(tx) client = ContractingClient() client.flush() client.set_var(contract='currency', variable='balances', arguments=[w.verifying_key], value=1_000_000) client.set_var(contract='stamp_cost', variable='S', arguments=['value'], value=20_000) transaction.transaction_is_valid(transaction=decoded, expected_processor='b' * 64, client=client, nonces=self.driver)
def test_serialize_works_properly(self): w = Wallet() expected = { 'sender': w.verifying_key, 'processor': 'b' * 64, 'stamps_supplied': 123, 'nonce': 0, 'contract': 'currency', 'function': 'transfer', 'kwargs': { 'amount': 123, 'to': 'jeff' } } tx = build_transaction(wallet=w, processor='b' * 64, stamps=123, nonce=0, contract='currency', function='transfer', kwargs={ 'amount': 123, 'to': 'jeff' }) decoded = decode(tx) self.assertDictEqual(decoded['payload'], expected)
def test_fixed_objects_do_not_fail_signature(self): self.assertEqual(len(self.ws.queue), 0) w = Wallet() self.ws.client.set_var(contract='currency', variable='balances', arguments=[w.verifying_key], value=1_000_000) self.ws.client.set_var(contract='stamp_cost', variable='S', arguments=['value'], value=1_000_000) tx = build_transaction(wallet=w, processor=self.ws.wallet.verifying_key, stamps=6000, nonce=0, contract='currency', function='transfer', kwargs={ 'amount': { '__fixed__': '1.0' }, 'to': 'jeff' }) _, response = self.ws.app.test_client.post('/', data=tx) self.assertEqual(len(self.ws.queue), 1)
def test_good_transaction_is_put_into_queue(self): self.assertEqual(len(self.ws.queue), 0) w = Wallet() self.ws.client.set_var(contract='currency', variable='balances', arguments=[w.verifying_key], value=1_000_000) self.ws.client.set_var(contract='stamp_cost', variable='S', arguments=['value'], value=1_000_000) tx = build_transaction(wallet=w, processor=self.ws.wallet.verifying_key, stamps=6000, nonce=0, contract='currency', function='transfer', kwargs={ 'amount': 123, 'to': 'jeff' }) s, response = self.ws.app.test_client.post('/', data=tx) print('test') self.assertEqual(len(self.ws.queue), 1)
def test_bad_tx_returns_properly(self): class BadTX: def __init__(self, tx, err): self.tx = tx self.err = err stu = Wallet() tx = transaction.build_transaction(wallet=stu, contract='testing', function='eat_stamps', kwargs={}, stamps=10000, processor='0' * 64, nonce=0) exe = execution.SerialExecutor(executor=self.client.executor) result = exe.execute_tx_batch( batch={'transactions': [BadTX(decode(tx), Exception)]}, stamp_cost=200, timestamp=int(time.time()), input_hash='A' * 32, driver=self.client.raw_driver) self.assertEqual(result[0]['status'], 1) self.assertEqual(result[0]['result'], safe_repr(str(Exception))) self.assertEqual(result[0]['stamps_used'], 0)
async def test(): await asyncio.gather( m.start(), d.start() ) tx_1 = transaction.build_transaction( wallet=mocks.TEST_FOUNDATION_WALLET, contract='currency', function='transfer', kwargs={ 'amount': 1_000_000, 'to': sender.verifying_key }, stamps=10000, nonce=0, processor=m.wallet.verifying_key ) tx_2 = transaction.build_transaction( wallet=sender, contract='currency', function='transfer', kwargs={ 'amount': 1338, 'to': 'jeff' }, stamps=5000, nonce=0, processor=m.wallet.verifying_key ) async with httpx.AsyncClient() as client: await client.post('http://0.0.0.0:18081/', data=tx_1) await asyncio.sleep(2) await client.post('http://0.0.0.0:18081/', data=tx_2) await asyncio.sleep(2) await asyncio.sleep(2) m.stop() d.stop()
async def push_tx(self, node, wallet, contract, function, kwargs, stamps, nonce): tx = transaction.build_transaction( wallet=wallet, contract=contract, function=function, kwargs=kwargs, stamps=stamps, processor=node.wallet.verifying_key, nonce=nonce ) async with httpx.AsyncClient() as client: await client.post(f'{node.webserver_ip}/', data=tx)
def test_bad_transaction_returns_a_TransactionException(self): tx = build_transaction(wallet=Wallet(), processor='b' * 64, stamps=123, nonce=0, contract='currency', function='transfer', kwargs={ 'amount': 123, 'to': 'jeff' }) _, response = self.ws.app.test_client.post('/', data=tx) self.assertDictEqual(response.json, { 'error': 'Transaction processor does not match expected processor.' })
def test_transaction_is_not_expired_true_if_within_timeout(self): w = Wallet() tx = build_transaction(wallet=w, processor='b' * 64, stamps=123, nonce=0, contract='currency', function='transfer', kwargs={ 'amount': 123, 'to': 'jeff' }) decoded = decode(tx) transaction.transaction_is_not_expired(decoded)
def test_push_transaction_can_be_retrieved_with_pop(self): tx = build_transaction(wallet=Wallet(), processor='b' * 64, stamps=123, nonce=0, contract='currency', function='transfer', kwargs={ 'amount': 123, 'to': 'jeff' }) self.q.append(tx) tx_2 = self.q.pop(0) self.assertEqual(decode(tx), tx_2)
def test_future_transactions_fine_if_in_expiry(self): w = Wallet() tx = build_transaction(wallet=w, processor='b' * 64, stamps=123, nonce=0, contract='currency', function='transfer', kwargs={ 'amount': 123, 'to': 'jeff' }) decoded = decode(tx) decoded['metadata']['timestamp'] += 4 transaction.transaction_is_not_expired(decoded)
def test_check_tx_formatting_incorrect_processor_fails(self): w = Wallet() tx = build_transaction(wallet=w, processor='b' * 64, stamps=123, nonce=0, contract='currency', function='transfer', kwargs={ 'amount': 123.0, 'to': 'jeff' }) decoded = decode(tx) with self.assertRaises(transaction.TransactionProcessorInvalid): transaction.check_tx_formatting(decoded, 'c' * 64)
def tip(address: str): nonce = requests.get(f"{LAMDEN_URL}/nonce/{bot_wallet.verifying_key}") nonce = json.loads(nonce.text) # Build transaction tx_data = build_transaction(wallet=bot_wallet, processor=nonce["processor"], stamps=100, nonce=nonce["nonce"], contract="currency", function="transfer", kwargs={ "amount": AMOUNT_TAU, "to": address }) # Send transaction tx = requests.post(LAMDEN_URL, data=tx_data) logging.debug(f"Sent {AMOUNT_TAU} TAU to {address} - {tx.text}")
def test_check_tx_formatting_succeeds(self): w = Wallet() tx = build_transaction( wallet=w, processor='b' * 64, stamps=123, nonce=0, contract='currency', function='transfer', kwargs={ 'amount': decimal.Decimal('123.872345873452873459873459870'), 'to': 'jeff' }) decoded = decode(tx) error = transaction.check_tx_formatting(decoded, 'b' * 64) self.assertIsNone(error)
def test_check_tx_formatting_not_formatted_fails(self): w = Wallet() tx = build_transaction(wallet=w, processor='b' * 64, stamps=123, nonce=0, contract='currency', function='transfer', kwargs={ 'amount': 123, 'to': 'jeff' }) decoded = decode(tx) decoded['payload']['nonce'] = -123 with self.assertRaises(transaction.TransactionFormattingError): transaction.check_tx_formatting(decoded, 'b' * 64)
def test_future_transactions_raise_error_if_beyond_expiry(self): w = Wallet() tx = build_transaction(wallet=w, processor='b' * 64, stamps=123, nonce=0, contract='currency', function='transfer', kwargs={ 'amount': 123, 'to': 'jeff' }) decoded = decode(tx) decoded['metadata']['timestamp'] += 6 with self.assertRaises(transaction.TransactionInvalidTimestampError): transaction.transaction_is_not_expired(decoded)
def test_transaction_is_expired_false_if_outside_timeout(self): w = Wallet() tx = build_transaction(wallet=w, processor='b' * 64, stamps=123, nonce=0, contract='currency', function='transfer', kwargs={ 'amount': 123, 'to': 'jeff' }) decoded = decode(tx) decoded['metadata']['timestamp'] -= 1000 with self.assertRaises(transaction.TransactionStaleError): transaction.transaction_is_not_expired(decoded)
def test_check_tx_formatting_signature_fails(self): w = Wallet() tx = build_transaction(wallet=w, processor='b' * 64, stamps=123, nonce=0, contract='currency', function='transfer', kwargs={ 'amount': 123, 'to': 'jeff' }) decoded = decode(tx) decoded['payload']['sender'] = 'a' * 64 with self.assertRaises(transaction.TransactionSignatureInvalid): transaction.check_tx_formatting(decoded, 'b' * 64)
def test_execute_tx_returns_successful_output(self): test_contract = ''' v = Variable() @construct def seed(): v.set('hello') @export def set(var: str): v.set(var) @export def get(): return v.get() ''' self.client.submit(test_contract, name='testing') self.client.raw_driver.commit() self.client.raw_driver.clear_pending_state() stu = Wallet() tx = transaction.build_transaction( wallet=stu, contract='testing', function='set', kwargs={'var': 'jeff'}, stamps=100_000, processor='0' * 64, nonce=0 ) e = execution.SerialExecutor(executor=self.client.executor) result = e.execute_tx(decode(tx), stamp_cost=20_000) self.assertEqual(result['status'], 0) self.assertEqual(result['state'][0]['key'], 'testing.v') self.assertEqual(result['state'][0]['value'], 'jeff') self.assertEqual(result['stamps_used'], 1)
def test_submit_transaction_error_if_queue_full(self): self.ws.queue.extend(range(10_000)) tx = build_transaction(wallet=Wallet(), processor=self.ws.wallet.verifying_key, stamps=123, nonce=0, contract='currency', function='transfer', kwargs={ 'amount': 123, 'to': 'jeff' }) _, response = self.ws.app.test_client.post('/', data=tx) self.assertDictEqual(response.json, {'error': 'Queue full. Resubmit shortly.'}) self.ws.queue.clear()
def test_tx_with_error_returns_exception(self): tx = build_transaction(wallet=Wallet(), processor=self.ws.wallet.verifying_key, stamps=123, nonce=0, contract='currency', function='transfer', kwargs={ 'amount': 123, 'to': 'jeff' }) tx = decode(tx) tx['payload']['stamps_supplied'] = -123 tx = encode(tx) _, response = self.ws.app.test_client.post('/', data=tx) self.assertDictEqual( response.json, {'error': 'Transaction is not formatted properly.'})
def submit_transaction(wallet, contract, function, kwargs, nonce): fail = False while True: # TODO: Remove later, the check that used this is now depreceated tx = transaction.build_transaction( wallet=wallet, contract=contract, function=function, kwargs=kwargs, nonce=nonce, # Starts at zero, increments with every transaction # Masternode address processor= '89f67bb871351a1629d66676e4bd92bbacb23bd0649b890542ef98f1b664a497', stamps=1000) try: return_data = requests.post('https://testnet-master-1.lamden.io/', data=tx).content return_data = return_data.decode("UTF-8") return_data = ast.literal_eval(return_data) print(return_data['hash']) except KeyError: # Raises error on second try (so it doesn't continuously retry) try: print_color( f"Transaction failed, debug data: {str(return_data['error'])}", color.RED) print_color(f"Retrying...", color.RED) return_data = requests.post( 'https://testnet-master-1.lamden.io/', data=tx).content return_data = return_data.decode("UTF-8") return_data = ast.literal_eval(return_data) print(return_data['hash']) except KeyError: raise SubmissionError(str(return_data['error'])) continue return nonce + 1, return_data
def send_tx(self, sender: Wallet, contract: str, function: str, kwargs: dict = {}, stamps: int = 500_000): server = self._get_server() nonce_req = requests.get('{}/nonce/{}'.format(server, sender.verifying_key)) nonce = nonce_req.json()['nonce'] processor = nonce_req.json()['processor'] tx = build_transaction(wallet=sender, processor=processor, stamps=stamps, nonce=nonce, contract=contract, function=function, kwargs=kwargs) return requests.post(server, data=tx, verify=False)
def test_stamp_deduction_on_fail(self): test_contract = ''' @export def eat_stamps(): while True: pass ''' self.client.submit(test_contract, name='testing') self.client.raw_driver.commit() self.client.raw_driver.clear_pending_state() stu = Wallet() self.client.raw_driver.set(f'currency.balances:{stu.verifying_key}', 100000) tx = transaction.build_transaction( wallet=stu, contract='testing', function='eat_stamps', kwargs={}, stamps=10000, processor='0' * 64, nonce=0 ) e = execution.SerialExecutor(executor=self.client.executor) self.client.executor.metering = True result = e.execute_tx(decode(tx), stamp_cost=200) self.assertEqual(result['status'], 1) self.assertEqual(result['state'][0]['key'], f'currency.balances:{stu.verifying_key}') self.assertEqual(result['state'][0]['value'], Decimal('99950.0')) self.assertEqual(result['stamps_used'], 10000)
def submit_transaction(wallet, contract, function, kwargs, nonce): fail = False while True: # TODO: Remove later, the check that used this is now depreceated tx = transaction.build_transaction(wallet=wallet, contract=contract, function=function, kwargs=kwargs, nonce=nonce, # Starts at zero, increments with every transaction # Masternode address processor='5b09493df6c18d17cc883ebce54fcb1f5afbd507533417fe32c006009a9c3c4a', stamps=1000) try: return_data = requests.post( 'https://masternode-01.lamden.io/', data=tx).content return_data = return_data.decode("UTF-8") return_data = ast.literal_eval(return_data) print(return_data['hash']) except KeyError: # Raises error on second try (so it doesn't continuously retry) try: print_color( f"Transaction failed, debug data: {str(return_data['error'])}", color.RED) print_color( f"Retrying...", color.RED) return_data = requests.post( 'https://masternode-01.lamden.io/', data=tx).content return_data = return_data.decode("UTF-8") return_data = ast.literal_eval(return_data) print(return_data['hash']) except KeyError: raise SubmissionError(str(return_data['error'])) continue return nonce + 1, return_data