Example #1
0
    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)
Example #2
0
    async def submit_transaction(self, request):
        log.debug(f'New request: {request}')
        # Reject TX if the queue is too large
        if len(self.queue) >= self.max_queue_len:
            return response.json({'error': "Queue full. Resubmit shortly."},
                                 status=503,
                                 headers={'Access-Control-Allow-Origin': '*'})

        tx_raw = _json.loads(request.body)
        log.error(tx_raw)
        # Check that the payload is valid JSON
        tx = decode(request.body)
        if tx is None:
            return response.json({'error': 'Malformed request body.'},
                                 headers={'Access-Control-Allow-Origin': '*'})

        # Check that the TX is correctly formatted
        try:
            transaction.check_tx_formatting(tx, self.wallet.verifying_key)

            transaction.transaction_is_valid(
                transaction=tx,
                expected_processor=self.wallet.verifying_key,
                client=self.client,
                nonces=self.nonces)

            nonce, pending_nonce = transaction.get_nonces(
                sender=tx['payload']['sender'],
                processor=tx['payload']['processor'],
                driver=self.nonces)

            pending_nonce = transaction.get_new_pending_nonce(
                tx_nonce=tx['payload']['nonce'],
                nonce=nonce,
                pending_nonce=pending_nonce)

            self.nonces.set_pending_nonce(sender=tx['payload']['sender'],
                                          processor=tx['payload']['processor'],
                                          value=pending_nonce)
        except TransactionException as e:
            log.error(f'Tx has error: {type(e)}')
            log.error(tx)
            return response.json(transaction.EXCEPTION_MAP[type(e)],
                                 headers={'Access-Control-Allow-Origin': '*'})

        # Add TX to the processing queue
        self.queue.append(request.body)
        log.error('Added to q')

        # Return the TX hash to the user so they can track it
        tx_hash = tx_hash_from_tx(tx)

        return response.json(
            {
                'success':
                'Transaction successfully submitted to the network.',
                'hash': tx_hash
            },
            headers={'Access-Control-Allow-Origin': '*'})
Example #3
0
    async def process_message(self, msg):
        self.log.info(f'Received work from {msg["sender"][:8]}')
        if msg['sender'] not in self.masters:
            self.log.error(
                f'TX Batch received from non-master {msg["sender"][:8]}')
            return

        shim = {
            'transactions': [],
            'timestamp': int(time.time()),
            'signature': '0' * 128,
            'input_hash': msg["sender"],
            'sender': msg["sender"]
        }

        if not verify(vk=msg['sender'],
                      msg=msg['input_hash'],
                      signature=msg['signature']):
            self.log.error(
                f'Invalidly signed TX Batch received from master {msg["sender"][:8]}'
            )
            return self.new_work[msg['sender']].append(shim)

        if int(time.time()) - msg['timestamp'] > self.expired_batch:
            self.log.error(
                f'Expired TX Batch received from master {msg["sender"][:8]}')
            return self.new_work[msg['sender']].append(shim)

        # Add padded!
        # Iterate and delete transactions from list that fail
        good_transactions = []
        for tx in msg['transactions']:
            try:
                transaction.transaction_is_valid(
                    transaction=tx,
                    expected_processor=msg['sender'],
                    client=self.client,
                    nonces=self.nonces,
                    strict=False,
                    timeout=self.expired_batch + self.tx_timeout)
                good_transactions.append(tx)
            except transaction.TransactionException as e:
                self.log.error(f'TX in batch has error: {type(e)}')

        # Replace transactions with ones that do not pass.
        msg['transactions'] = good_transactions

        self.new_work[msg['sender']].append(msg)
        self.log.info(
            f'{msg["sender"][:8]} has {len(self.new_work[msg["sender"]])} batches of work to do.'
        )