def build_transaction(wallet, contract: str, function: str, kwargs: dict, nonce: int, processor: str, stamps: int): payload = { 'contract': contract, 'function': function, 'kwargs': kwargs, 'nonce': nonce, 'processor': processor, 'sender': wallet.verifying_key, 'stamps_supplied': stamps, } payload = format_dictionary( payload) # Sort payload in case kwargs unsorted assert check_format( payload, rules.TRANSACTION_PAYLOAD_RULES), 'Invalid payload provided!' true_payload = encode(decode(encode(payload))) signature = wallet.sign(true_payload) metadata = {'signature': signature, 'timestamp': int(time.time())} tx = {'payload': payload, 'metadata': metadata} return encode(format_dictionary(tx))
def execute_tx(self, transaction, stamp_cost, environment: dict = {}, tx_number=0): #global PoolExecutor #executor = PoolExecutor output = self.executor.execute( sender=transaction['payload']['sender'], contract_name=transaction['payload']['contract'], function_name=transaction['payload']['function'], stamps=transaction['payload']['stamps_supplied'], stamp_cost=stamp_cost, kwargs=transaction['payload']['kwargs'], environment=environment, auto_commit=False ) log.debug(output) tx_hash = tx_hash_from_tx(transaction) writes = [{'key': k, 'value': v} for k, v in output['writes'].items()] tx_output = { 'hash': tx_hash, 'transaction': transaction, 'status': output['status_code'], 'state': writes, 'stamps_used': output['stamps_used'], 'result': safe_repr(output['result']), 'tx_number': tx_number } tx_output = format_dictionary(tx_output) self.executor.driver.pending_writes.clear() # add return tx_output
def test_recursive_dictionary_sort_works(self): unsorted = { 'z': 123, 'a': { 'z': 123, 'a': 532, 'x': { 'a': 123, 'vvv': 54 } } } sorted_dict = { 'a': { 'a': 532, 'x': { 'a': 123, 'vvv': 54 }, 'z': 123, }, 'z': 123 } s = canonical.format_dictionary(unsorted) self.assertDictEqual(s, sorted_dict)
def generate_tx_error(self, transaction, error): tx_hash = tx_hash_from_tx(transaction) tx_output = { 'hash': tx_hash, 'transaction': transaction, 'status': 1, 'state': {}, 'stamps_used': 0, 'result': safe_repr(error) } tx_output = format_dictionary(tx_output) return tx_output
def execute_work(self, driver, work, wallet, previous_block_hash, current_height=0, stamp_cost=20000, parallelism=4): # Assume single threaded, single process for now. subblocks = [] i = 0 for tx_batch in work: results = self.execute_tx_batch(driver=driver, batch=tx_batch, timestamp=tx_batch['timestamp'], input_hash=tx_batch['input_hash'], stamp_cost=stamp_cost, bhash=previous_block_hash, num=current_height) if len(results) > 0: merkle = merklize([encode(r).encode() for r in results]) proof = wallet.sign(merkle[0]) else: merkle = merklize([bytes.fromhex(tx_batch['input_hash'])]) proof = wallet.sign(tx_batch['input_hash']) merkle_tree = {'leaves': merkle, 'signature': proof} sbc = { 'input_hash': tx_batch['input_hash'], 'transactions': results, 'merkle_tree': merkle_tree, 'signer': wallet.verifying_key, 'subblock': i % parallelism, 'previous': previous_block_hash } sbc = format_dictionary(sbc) subblocks.append(sbc) i += 1 return subblocks
def execute_tx(self, transaction, stamp_cost, environment: dict = {}): # Deserialize Kwargs. Kwargs should be serialized JSON moving into the future for DX. # Add AUXILIARY_SALT for more randomness environment['AUXILIARY_SALT'] = transaction['metadata']['signature'] balance = self.executor.driver.get_var( contract='currency', variable='balances', arguments=[transaction['payload']['sender']], mark=False ) output = self.executor.execute( sender=transaction['payload']['sender'], contract_name=transaction['payload']['contract'], function_name=transaction['payload']['function'], stamps=transaction['payload']['stamps_supplied'], stamp_cost=stamp_cost, kwargs=transaction['payload']['kwargs'], environment=environment, auto_commit=False ) self.executor.driver.pending_writes.clear() if output['status_code'] == 0: log.info(f'TX executed successfully. ' f'{output["stamps_used"]} stamps used. ' f'{len(output["writes"])} writes. ' f'Result = {output["result"]}') else: log.error(f'TX executed unsuccessfully. ' f'{output["stamps_used"]} stamps used. ' f'{len(output["writes"])} writes.' f' Result = {output["result"]}') log.debug(output['writes']) tx_hash = tx_hash_from_tx(transaction) # Only apply the writes if the tx passes if output['status_code'] == 0: writes = [{'key': k, 'value': v} for k, v in output['writes'].items()] else: # Calculate only stamp deductions to_deduct = output['stamps_used'] / stamp_cost writes = [{ 'key': 'currency.balances:{}'.format(transaction['payload']['sender']), 'value': balance - to_deduct }] tx_output = { 'hash': tx_hash, 'transaction': transaction, 'status': output['status_code'], 'state': writes, 'stamps_used': output['stamps_used'], 'result': safe_repr(output['result']) } tx_output = format_dictionary(tx_output) return tx_output