Beispiel #1
0
    def prepare_confirmation_transaction(self, transfer_event):
        nonce = self.get_next_nonce()
        self.logger.debug(
            f"Preparing confirmation transaction for address "
            f"{transfer_event.args['from']} for {transfer_event.args.value} "
            f"coins (nonce {nonce}, chain {self.w3.eth.chainId})")

        # hard code gas limit to avoid executing the transaction (which would fail as the sender
        # address is not defined before signing the transaction, but the contract asserts that
        # it's a validator)
        transaction = self.home_bridge_contract.functions.confirmTransfer(
            compute_transfer_hash(transfer_event),
            transfer_event.transactionHash,
            transfer_event.args.value,
            transfer_event.args["from"],
        ).buildTransaction({
            "gasPrice": self.gas_price,
            "nonce": nonce,
            "gas": CONFIRMATION_TRANSACTION_GAS_LIMIT,
        })

        # The signing step should not fail, but we want to exit this execution path early,
        # therefore it's inside the try block
        signed_transaction = self.w3.eth.account.sign_transaction(
            transaction, self.private_key)

        return signed_transaction
Beispiel #2
0
def test_transaction_sending(
    confirmation_sender,
    w3_home,
    tester_home,
    home_bridge_contract,
    transfer_event,
    validator_address,
):
    transaction = confirmation_sender.prepare_confirmation_transaction(
        transfer_event,
        nonce=confirmation_sender.get_next_nonce(),
        chain_id=int(w3_home.eth.chainId),
    )
    confirmation_sender.send_confirmation_transaction(transaction)
    assert transaction == confirmation_sender.pending_transaction_queue.peek()
    tester_home.mine_block()
    receipt = w3_home.eth.getTransactionReceipt(transaction.hash)
    assert receipt is not None
    events = home_bridge_contract.events.Confirmation.getLogs(
        fromBlock=receipt.blockNumber, toBlock=receipt.blockNumber)
    assert len(events) == 1
    event_args = events[0].args
    assert event_args.transferHash == compute_transfer_hash(transfer_event)
    assert event_args.transactionHash == transfer_event.transactionHash
    assert event_args.amount == transfer_event.args.value
    assert event_args.recipient == transfer_event.args["from"]
    assert event_args.validator == validator_address
    def prepare_confirmation_transaction(self, transfer_event, nonce: int,
                                         chain_id: int):
        transfer_hash = compute_transfer_hash(transfer_event)
        transaction_hash = transfer_event.transactionHash
        amount = transfer_event.args.value
        recipient = transfer_event.args["from"]

        logger.info(
            "confirmTransfer(transferHash=%s transactionHash=%s amount=%s recipient=%s) with nonce=%s, chain_id=%s",
            transfer_hash.hex(),
            transaction_hash.hex(),
            amount,
            recipient,
            nonce,
            chain_id,
        )
        # hard code gas limit to avoid executing the transaction (which would fail as the sender
        # address is not defined before signing the transaction, but the contract asserts that
        # it's a validator)
        transaction = self.home_bridge_contract.functions.confirmTransfer(
            transferHash=transfer_hash,
            transactionHash=transaction_hash,
            amount=amount,
            recipient=recipient,
        ).buildTransaction({
            "gasPrice": self.gas_price,
            "nonce": nonce,
            "gas": CONFIRMATION_TRANSACTION_GAS_LIMIT,
            "chainId": chain_id,
        })
        signed_transaction = self.w3.eth.account.sign_transaction(
            transaction, self.private_key)

        return signed_transaction
def test_recorder_does_not_plan_completed_transfer(recorder, hashes):
    transfer_event = make_transfer_event(transaction_hash=next(hashes))
    completion_event = make_transfer_hash_event(
        COMPLETION_EVENT_NAME, compute_transfer_hash(transfer_event),
        next(hashes))
    recorder.apply_event(transfer_event)
    recorder.apply_event(completion_event)
    assert len(recorder.pull_transfers_to_confirm()) == 0
Beispiel #5
0
def test_recorder_does_not_plan_completed_transfer(recorder, transfer_hash, hashes):
    transfer_event = get_transfer_hash_event(
        TRANSFER_EVENT_NAME, transfer_hash, next(hashes)
    )
    completion_event = get_transfer_hash_event(
        COMPLETION_EVENT_NAME, compute_transfer_hash(transfer_event), next(hashes)
    )
    recorder.apply_proper_event(transfer_event)
    recorder.apply_proper_event(completion_event)
    assert len(recorder.pull_transfers_to_confirm()) == 0
    def apply_proper_event(self, event: AttributeDict) -> None:
        event_name = event.event

        if event_name == TRANSFER_EVENT_NAME:
            transfer_hash = compute_transfer_hash(event)
            self.transfer_hashes.add(transfer_hash)
            self.transfer_events[transfer_hash] = event
        elif event_name == CONFIRMATION_EVENT_NAME:
            transfer_hash = Hash32(bytes(event.args.transferHash))
            assert len(transfer_hash) == 32
            self.confirmation_hashes.add(transfer_hash)
        elif event_name == COMPLETION_EVENT_NAME:
            transfer_hash = Hash32(bytes(event.args.transferHash))
            assert len(transfer_hash) == 32
            self.completion_hashes.add(transfer_hash)
        else:
            raise ValueError(f"Got unknown event {event}")
Beispiel #7
0
    def _apply_web3_event(self, event: AttributeDict) -> None:
        event_name = event.event

        if event_name == TRANSFER_EVENT_NAME:
            if event.args.value == 0 or is_same_address(
                    event.args["from"], ZERO_ADDRESS):
                logger.warning(f"skipping event {event}")
                return
            transfer_hash = compute_transfer_hash(event)
            self.transfer_hashes.add(transfer_hash)
            self.transfer_events[transfer_hash] = event
        elif event_name == CONFIRMATION_EVENT_NAME:
            transfer_hash = Hash32(bytes(event.args.transferHash))
            assert len(transfer_hash) == 32
            self.confirmation_hashes.add(transfer_hash)
        elif event_name == COMPLETION_EVENT_NAME:
            transfer_hash = Hash32(bytes(event.args.transferHash))
            assert len(transfer_hash) == 32
            self.completion_hashes.add(transfer_hash)
        else:
            raise ValueError(f"Got unknown event {event}")
Beispiel #8
0
def test_transfer_hash_computation(transfer_event):
    transfer_hash = compute_transfer_hash(transfer_event)
    assert transfer_event.logIndex == 5
    assert transfer_hash == keccak(transfer_event.transactionHash + b"\x05")