예제 #1
0
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))
예제 #2
0
    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
예제 #3
0
    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)
예제 #4
0
    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
예제 #5
0
    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
예제 #6
0
    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