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)
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_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_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_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 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 test_masternode_delegate_single_loop_updates_block_num(self): ips = [ 'tcp://127.0.0.1:18001', 'tcp://127.0.0.1:18002' ] dw = Wallet() mw = Wallet() self.authenticator.add_verifying_key(mw.verifying_key) self.authenticator.add_verifying_key(dw.verifying_key) self.authenticator.configure() mnd = ContractDriver(driver=InMemDriver()) mn = masternode.Masternode( socket_base=ips[0], ctx=self.ctx, wallet=mw, constitution={ 'masternodes': [mw.verifying_key], 'delegates': [dw.verifying_key] }, driver=mnd ) sender = Wallet() mnd.set_var(contract='currency', variable='balances', arguments=[sender.verifying_key], value=1_000_000) dld = ContractDriver(driver=InMemDriver()) dld.set_var(contract='currency', variable='balances', arguments=[sender.verifying_key], value=1_000_000) dl = delegate.Delegate( socket_base=ips[1], ctx=self.ctx, wallet=dw, constitution={ 'masternodes': [mw.verifying_key], 'delegates': [dw.verifying_key] }, driver=dld ) tx = transaction.build_transaction( wallet=sender, contract='currency', function='transfer', kwargs={ 'amount': 1338, 'to': 'jeff' }, stamps=5000, nonce=0, processor=mw.verifying_key ) tx_decoded = decode(tx) mn.tx_batcher.queue.append(tx_decoded) peers = { mw.verifying_key: ips[0], dw.verifying_key: ips[1] } mn.network.peers = peers dl.network.peers = peers tasks = asyncio.gather( mn.router.serve(), dl.router.serve(), mn.loop(), dl.loop(), stop_server(mn.router, 1), stop_server(dl.router, 1), ) self.loop.run_until_complete(tasks) dh = storage.get_latest_block_height(dld) mh = storage.get_latest_block_height(mnd) self.assertEqual(dh, 1) self.assertEqual(mh, 1)
def test_execute_work_multiple_transaction_batches_works(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() tx1_1 = transaction.build_transaction( wallet=stu, contract='testing', function='set', kwargs={'var': 'howdy'}, stamps=100_000, processor='0' * 64, nonce=0 ) tx1_1 = decode(tx1_1) tx1_2 = transaction.build_transaction( wallet=stu, contract='testing', function='get', kwargs={}, stamps=100_000, processor='0' * 64, nonce=0 ) tx1_2 = decode(tx1_2) tx_batch_1 = { 'transactions': [tx1_1, tx1_2], 'timestamp': time.time(), 'input_hash': 'C' * 64 } tx2_1 = transaction.build_transaction( wallet=stu, contract='testing', function='set', kwargs={'var': '123'}, stamps=100_000, processor='0' * 64, nonce=0 ) tx2_1 = decode(tx2_1) jeff = Wallet() tx2_2 = transaction.build_transaction( wallet=jeff, contract='testing', function='set', kwargs={'var': 'poo'}, stamps=100_000, processor='0' * 64, nonce=0 ) tx2_2 = decode(tx2_2) tx_batch_2 = { 'transactions': [tx2_1, tx2_2], 'timestamp': time.time(), 'input_hash': 'A' * 64 } work = [tx_batch_1, tx_batch_2] exe = execution.SerialExecutor(executor=self.client.executor) results = exe.execute_work( driver=self.client.raw_driver, work=work, previous_block_hash='B' * 64, wallet=Wallet(), stamp_cost=20_000 ) sb1, sb2 = results td1, td2 = sb1['transactions'] self.assertEqual(td1['status'], 0) self.assertEqual(td1['state'][0]['key'], 'testing.v') self.assertEqual(td1['state'][0]['value'], 'howdy') self.assertEqual(td1['stamps_used'], 1) self.assertEqual(td2['status'], 0) self.assertEqual(len(td2['state']), 0) self.assertEqual(td2['stamps_used'], 1) self.assertEqual(sb1['input_hash'], tx_batch_1['input_hash']) self.assertEqual(sb1['subblock'], 0) self.assertEqual(sb1['previous'], 'B' * 64) td1, td2 = sb2['transactions'] self.assertEqual(td1['status'], 0) self.assertEqual(td1['state'][0]['key'], 'testing.v') self.assertEqual(td1['state'][0]['value'], '123') self.assertEqual(td1['stamps_used'], 1) self.assertEqual(td2['status'], 0) self.assertEqual(td2['state'][0]['key'], 'testing.v') self.assertEqual(td2['state'][0]['value'], 'poo') self.assertEqual(td2['stamps_used'], 1) self.assertEqual(sb2['input_hash'], tx_batch_2['input_hash']) self.assertEqual(sb2['subblock'], 1) self.assertEqual(sb2['previous'], 'B' * 64)
def test_execute_tx_batch_returns_all_transactions_4_in_order(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': 'howdy'}, stamps=100_000, processor='0' * 64, nonce=0 ) tx = decode(tx) tx2 = transaction.build_transaction( wallet=stu, contract='testing', function='get', kwargs={}, stamps=100_000, processor='0' * 64, nonce=0 ) tx2 = decode(tx2) tx3 = transaction.build_transaction( wallet=stu, contract='testing', function='set', kwargs={'var': 'something'}, stamps=100_000, processor='0' * 64, nonce=0 ) tx3 = decode(tx3) tx4 = transaction.build_transaction( wallet=stu, contract='testing', function='set', kwargs={'var': 'something2'}, stamps=100_000, processor='0' * 64, nonce=0 ) tx4 = decode(tx4) tx_batch = { 'transactions': [tx, tx2, tx3, tx4] } e = execution.SerialExecutor(executor=self.client.executor) results = e.execute_tx_batch( driver=self.client.raw_driver, batch=tx_batch, timestamp=time.time(), input_hash='A' * 64, stamp_cost=20_000 ) td1, td2, td3, td4 = results self.assertEqual(td1['status'], 0) self.assertEqual(td1['state'][0]['key'], 'testing.v') self.assertEqual(td1['state'][0]['value'], 'howdy') self.assertEqual(td1['stamps_used'], 1) self.assertEqual(td2['status'], 0) self.assertEqual(len(td2['state']), 0) self.assertEqual(td2['stamps_used'], 1) self.assertEqual(td3['status'], 0) self.assertEqual(td3['state'][0]['key'], 'testing.v') self.assertEqual(td3['state'][0]['value'], 'something') self.assertEqual(td3['stamps_used'], 1) self.assertEqual(td4['status'], 0) self.assertEqual(td4['state'][0]['key'], 'testing.v') self.assertEqual(td4['state'][0]['value'], 'something2') self.assertEqual(td4['stamps_used'], 1)