def test_no_txs_merklizes_and_signs_input_hash(self): tx_batch_1 = { 'transactions': [], 'timestamp': time.time(), 'input_hash': 'A' * 64 } work = [tx_batch_1] w = Wallet() exe = execution.SerialExecutor(executor=self.client.executor) results = exe.execute_work( driver=self.client.raw_driver, work=work, previous_block_hash='B' * 64, wallet=w, stamp_cost=20_000 ) self.assertTrue(verify(w.verifying_key, results[0]['input_hash'], results[0]['merkle_tree']['signature'])) h = hashlib.sha3_256() h.update(bytes.fromhex(results[0]['input_hash'])) self.assertEqual(h.hexdigest(), results[0]['merkle_tree']['leaves'][0])
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_generate_environment_creates_block_num(self): timestamp = time.time() exe = execution.SerialExecutor(executor=self.client.executor) e = exe.generate_environment(self.client.raw_driver, timestamp, 'A' * 64) self.assertEqual(e['block_num'], storage.get_latest_block_height(self.client.raw_driver) + 1)
def test_generate_environment_creates_input_hash(self): timestamp = time.time() exe = execution.SerialExecutor(executor=self.client.executor) e = exe.generate_environment(self.client.raw_driver, timestamp, 'A' * 64) self.assertEqual(e['__input_hash'], 'A' * 64)
def __init__(self, parallelism=4, *args, **kwargs): super().__init__(*args, **kwargs) # Number of core / processes we push to self.parallelism = parallelism self.executor = Executor(driver=self.driver) self.transaction_executor = execution.SerialExecutor(executor=self.executor) self.work_processor = WorkProcessor(client=self.client, nonces=self.nonces) self.router.add_service(WORK_SERVICE, self.work_processor) self.upgrade_manager.node_type = 'delegate' self.log = get_logger(f'Delegate {self.wallet.vk_pretty[4:12]}')
def test_generate_environment_creates_datetime_wrapped_object(self): timestamp = int(time.time()) exe = execution.SerialExecutor(executor=self.client.executor) e = exe.generate_environment(self.client.raw_driver, timestamp, 'A' * 64) t = datetime.utcfromtimestamp(timestamp) #self.assertEqual(type(e['now']), Datetime) self.assertEqual(e['now'].year, t.year) self.assertEqual(e['now'].month, t.month) self.assertEqual(e['now'].day, t.day) self.assertEqual(e['now'].hour, t.hour) self.assertEqual(e['now'].minute, t.minute) self.assertEqual(e['now'].second, t.second)
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_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_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)