예제 #1
0
def test_save_and_load_channel(ms_database):
    token_network_address = get_random_address()
    ms_database.conn.execute("INSERT INTO token_network (address) VALUES (?)",
                             [token_network_address])
    for update_status in [
            None,
            OnChainUpdateStatus(
                update_sender_address=Address(get_random_address()),
                nonce=random.randint(0, UINT256_MAX),
            ),
    ]:
        channel = Channel(
            token_network_address=TokenNetworkAddress(token_network_address),
            identifier=ChannelID(random.randint(0, UINT256_MAX)),
            participant1=Address(get_random_address()),
            participant2=Address(get_random_address()),
            settle_timeout=random.randint(0, UINT256_MAX),
            state=random.choice(list(ChannelState)),
            closing_block=BlockNumber(random.randint(0, UINT256_MAX)),
            closing_participant=Address(get_random_address()),
            closing_tx_hash=TransactionHash('%d' %
                                            random.randint(0, UINT64_MAX)),
            claim_tx_hash=TransactionHash('%d' %
                                          random.randint(0, UINT64_MAX)),
            update_status=update_status,
        )
        ms_database.upsert_channel(channel)
        loaded_channel = ms_database.get_channel(
            token_network_address=channel.token_network_address,
            channel_id=channel.identifier)
        assert loaded_channel == channel
예제 #2
0
    def f():
        contract_address = get_random_address()
        channel_identifier = get_random_identifier()

        balance_hash_data = '%d' % random.randint(0, UINT64_MAX)
        additional_hash_data = '%d' % random.randint(0, UINT64_MAX)

        balance_hash = encode_hex((balance_hash_data.encode()))
        nonce = random.randint(0, UINT64_MAX)
        additional_hash = encode_hex(keccak(additional_hash_data.encode()))
        chain_id = 1

        privkey = get_random_privkey()
        privkey_non_closing = get_random_privkey()

        bp = HashedBalanceProof(  # type: ignore
            channel_identifier=channel_identifier,
            token_network_address=contract_address,
            chain_id=chain_id,
            balance_hash=balance_hash,
            nonce=nonce,
            additional_hash=additional_hash,
            priv_key=privkey,
        )
        monitor_request = UnsignedMonitorRequest.from_balance_proof(
            bp, reward_amount=TokenAmount(0)).sign(privkey_non_closing)
        return monitor_request, privkey, privkey_non_closing
예제 #3
0
def test_process_payment_errors(pathfinding_service_web3_mock, web3,
                                deposit_to_udc, create_account,
                                get_private_key):
    pfs = pathfinding_service_web3_mock
    pfs.service_fee = 1
    sender = create_account()
    privkey = get_private_key(sender)

    # expires too early
    iou = make_iou(privkey,
                   pfs.address,
                   expiration_block=web3.eth.blockNumber + 5)
    with pytest.raises(exceptions.IOUExpiredTooEarly):
        process_payment(iou, pfs)

    # it fails it the no deposit is in the UDC
    iou = make_iou(privkey, pfs.address)
    with pytest.raises(exceptions.DepositTooLow):
        process_payment(iou, pfs)

    # must succeed if we add enough deposit to UDC
    deposit_to_udc(sender, 10)
    iou = make_iou(privkey, pfs.address)
    process_payment(iou, pfs)

    # wrong recipient
    iou = make_iou(privkey, get_random_address())
    with pytest.raises(exceptions.WrongIOURecipient):
        process_payment(iou, pfs)

    # payment too low
    pfs.service_fee = 2
    iou = make_iou(privkey, pfs.address)
    with pytest.raises(exceptions.InsufficientServicePayment):
        process_payment(iou, pfs)
예제 #4
0
def test_process_payment_errors(
    pathfinding_service_mocked_listeners,
    web3,
    deposit_to_udc,
    create_account,
    get_private_key,
):
    pfs = pathfinding_service_mocked_listeners
    pfs.service_fee = 1
    sender = create_account()
    privkey = get_private_key(sender)

    # expires too early
    iou = make_iou(privkey,
                   pfs.address,
                   expiration_block=web3.eth.blockNumber + 5)
    with pytest.raises(exceptions.IOUExpiredTooEarly):
        process_payment(iou, pfs)

    # it fails it the no deposit is in the UDC
    iou = make_iou(privkey, pfs.address)
    with pytest.raises(exceptions.DepositTooLow):
        process_payment(iou, pfs)

    # must succeed if we add enough deposit to UDC
    deposit_to_udc(sender, 10)
    iou = make_iou(privkey, pfs.address)
    process_payment(iou, pfs)

    # malformed
    iou = make_iou(privkey, pfs.address)
    del iou['amount']
    with pytest.raises(exceptions.InvalidRequest):
        process_payment(iou, pfs)

    # wrong recipient
    iou = make_iou(privkey, get_random_address())
    with pytest.raises(exceptions.WrongIOURecipient):
        process_payment(iou, pfs)

    # bad signature
    iou = make_iou(privkey, pfs.address)
    iou['signature'] = hex(int(iou['signature'], 16) + 1)
    with pytest.raises(exceptions.InvalidSignature):
        process_payment(iou, pfs)

    # payment too low
    pfs.service_fee = 2
    iou = make_iou(privkey, pfs.address)
    with pytest.raises(exceptions.InsufficientServicePayment):
        process_payment(iou, pfs)
예제 #5
0
def test_crash(tmpdir, get_accounts, get_private_key, mockchain):  # pylint: disable=too-many-locals
    """ Process blocks and compare results with/without crash

    A somewhat meaninful crash handling is simulated by not including the
    UpdatedHeadBlockEvent in every block.
    """
    channel_identifier = ChannelID(3)
    c1, c2 = get_accounts(2)
    token_network_address = TokenNetworkAddress(
        to_canonical_address(get_random_address()))
    balance_proof = HashedBalanceProof(
        nonce=Nonce(1),
        transferred_amount=TokenAmount(2),
        priv_key=get_private_key(c1),
        channel_identifier=channel_identifier,
        token_network_address=token_network_address,
        chain_id=ChainID(1),
        additional_hash="0x%064x" % 0,
        locked_amount=0,
        locksroot=encode_hex(LOCKSROOT_OF_NO_LOCKS),
    )
    monitor_request = balance_proof.get_monitor_request(
        get_private_key(c2),
        reward_amount=TokenAmount(0),
        msc_address=TEST_MSC_ADDRESS)

    events = [
        [
            ReceiveChannelOpenedEvent(
                token_network_address=token_network_address,
                channel_identifier=channel_identifier,
                participant1=c1,
                participant2=c2,
                settle_timeout=20,
                block_number=BlockNumber(0),
            )
        ],
        [UpdatedHeadBlockEvent(BlockNumber(1))],
        [
            ActionMonitoringTriggeredEvent(
                token_network_address=token_network_address,
                channel_identifier=channel_identifier,
                non_closing_participant=c2,
            )
        ],
        [UpdatedHeadBlockEvent(BlockNumber(3))],
    ]
    mockchain(events)

    server_private_key = get_random_privkey()

    contracts = {
        CONTRACT_TOKEN_NETWORK_REGISTRY: ContractMock(),
        CONTRACT_MONITORING_SERVICE: ContractMock(),
        CONTRACT_USER_DEPOSIT: ContractMock(),
        CONTRACT_SERVICE_REGISTRY: ContractMock(),
    }

    def new_ms(filename):
        ms = MonitoringService(
            web3=Web3Mock(),
            private_key=server_private_key,
            contracts=contracts,
            db_filename=os.path.join(tmpdir, filename),
        )
        msc = Mock()
        ms.context.monitoring_service_contract = msc
        ms.monitor_mock = msc.functions.monitor.return_value.transact  # type: ignore
        ms.monitor_mock.return_value = bytes(0)  # type: ignore
        return ms

    # initialize both monitoring services
    stable_ms = new_ms("stable.db")
    crashy_ms = new_ms("crashy.db")
    for ms in [stable_ms, crashy_ms]:
        ms.database.conn.execute(
            "INSERT INTO token_network(address) VALUES (?)",
            [to_checksum_address(token_network_address)],
        )
        ms.context.ms_state.blockchain_state.token_network_addresses = [
            token_network_address
        ]
        ms.database.upsert_monitor_request(monitor_request)
        ms.database.conn.commit()

    # process each block and compare results between crashy and stable ms
    for to_block in range(len(events)):
        crashy_ms = new_ms("crashy.db")  # new instance to simulate crash
        stable_ms.monitor_mock.reset_mock()  # clear calls from last block
        result_state: List[dict] = []
        for ms in [stable_ms, crashy_ms]:
            ms._process_new_blocks(to_block)  # pylint: disable=protected-access
            result_state.append(
                dict(
                    blockchain_state=ms.context.ms_state.blockchain_state,
                    db_dump=list(ms.database.conn.iterdump()),
                    monitor_calls=ms.monitor_mock.mock_calls,
                ))

        # both instances should have the same state after processing
        for stable_state, crashy_state in zip(result_state[0].values(),
                                              result_state[1].values()):
            # do asserts for each key separately to get better error messages
            assert stable_state == crashy_state
예제 #6
0
 def __init__(self, **kwargs):
     super().__init__(**kwargs)
     if "address" not in kwargs:
         self.address = get_random_address()