示例#1
0
def test_close_tampered_nonce(tester_channels):
    """ Messages with a tampered nonce must be rejected. """
    pkey0, pkey1, nettingchannel, channel0, channel1 = tester_channels[0]

    transfer0 = make_direct_transfer_from_channel(
        channel0,
        channel1,
        amount=90,
        pkey=pkey0,
    )
    transfer0_data = transfer0.encode()

    tampered_transfer = DirectTransfer.decode(transfer0_data)
    tampered_transfer.nonce += 1

    tampered_transfer_hash = sha3(tampered_transfer.encode()[:-65])
    with pytest.raises(TransactionFailed):
        nettingchannel.close(
            tampered_transfer.nonce,
            tampered_transfer.transferred_amount,
            tampered_transfer.locksroot,
            tampered_transfer_hash,
            tampered_transfer.signature,
            sender=pkey1,
        )
def test_close_tampered_nonce(tester_chain, tester_channels):
    """ Messages with a tampered nonce must be rejected. """
    pkey0, pkey1, nettingchannel, channel0, channel1 = tester_channels[0]

    block_number = tester_chain.block.number
    transfer0 = make_direct_transfer_from_channel(
        block_number,
        channel0,
        channel1,
        amount=90,
        pkey=pkey0,
    )
    transfer0_data = transfer0.encode()

    tampered_transfer = DirectTransfer.decode(transfer0_data)
    tampered_transfer.nonce += 1

    tampered_transfer_hash = sha3(tampered_transfer.encode()[:-65])
    with pytest.raises(TransactionFailed):
        nettingchannel.close(
            tampered_transfer.nonce,
            tampered_transfer.transferred_amount,
            tampered_transfer.locksroot,
            tampered_transfer_hash,
            tampered_transfer.signature,
            sender=pkey1,
        )
示例#3
0
def test_close_tampered_identifier(tester_channels):
    """ Messages with a tampered identifier must be rejected. """
    pkey0, pkey1, nettingchannel, channel0, channel1 = tester_channels[0]
    payment_network_identifier = factories.make_address()

    transfer0 = make_direct_transfer_from_channel(
        payment_network_identifier,
        channel0,
        channel1,
        amount=90,
        pkey=pkey0,
    )
    transfer0_data = transfer0.encode()

    tampered_transfer = DirectTransfer.decode(transfer0_data)
    tampered_transfer.payment_identifier += 1

    tampered_transfer_hash = sha3(tampered_transfer.encode()[:-65])
    with pytest.raises(TransactionFailed):
        nettingchannel.close(
            tampered_transfer.nonce,
            tampered_transfer.transferred_amount,
            tampered_transfer.locksroot,
            tampered_transfer_hash,
            tampered_transfer.signature,
            sender=pkey1,
        )
示例#4
0
def decode_transfer(transfer_encoded):
    if transfer_encoded[0] == DIRECTTRANSFER:
        return DirectTransfer.decode(transfer_encoded)
    elif transfer_encoded[0] == MEDIATEDTRANSFER:
        return MediatedTransfer.decode(transfer_encoded)
    elif transfer_encoded[0] == REFUNDTRANSFER:
        return RefundTransfer.decode(transfer_encoded)
    else:
        raise ValueError('invalid transfer type {}'.format(
            type(transfer_encoded[0])))
示例#5
0
def decode_transfer(transfer_encoded):
    if transfer_encoded[0] == DIRECTTRANSFER:
        return DirectTransfer.decode(transfer_encoded)
    elif transfer_encoded[0] == MEDIATEDTRANSFER:
        return MediatedTransfer.decode(transfer_encoded)
    elif transfer_encoded[0] == CANCELTRANSFER:
        return CancelTransfer.decode(transfer_encoded)
    # convinience for testing only (LockedTransfer are not exchanged between nodes)
    elif transfer_encoded[0] == LOCKEDTRANSFER:
        return LockedTransfer.decode(transfer_encoded)
    else:
        raise ValueError('invalid transfer type {}'.format(type(transfer_encoded[0])))
示例#6
0
def decode_transfer(transfer_encoded):
    if transfer_encoded[0] == DIRECTTRANSFER:
        return DirectTransfer.decode(transfer_encoded)
    elif transfer_encoded[0] == MEDIATEDTRANSFER:
        return MediatedTransfer.decode(transfer_encoded)
    elif transfer_encoded[0] == REFUNDTRANSFER:
        return RefundTransfer.decode(transfer_encoded)
    # convinience for testing only (LockedTransfer are not exchanged between nodes)
    elif transfer_encoded[0] == LOCKEDTRANSFER:
        return LockedTransfer.decode(transfer_encoded)
    else:
        raise ValueError('invalid transfer type {}'.format(type(transfer_encoded[0])))
示例#7
0
def test_close_tampered_nonce(tester_state, tester_channels):
    """ Messages with a tampered nonce must be rejected. """
    pkey0, pkey1, nettingchannel, channel0, channel1 = tester_channels[0]

    transfer0 = make_direct_transfer_from_channel(channel0, channel1, amount=90, pkey=pkey0)
    transfer0_data = transfer0.encode()

    tampered_transfer = DirectTransfer.decode(transfer0_data)
    tampered_transfer.nonce += 1
    tampered_transfer_data = tampered_transfer.encode()

    with pytest.raises(TransactionFailed):
        nettingchannel.close(tampered_transfer_data, sender=pkey1)
示例#8
0
def test_close_tampered_identifier(tester_state, tester_channels):
    """ Messages with a tampered identifier must be rejected. """
    pkey0, pkey1, nettingchannel, channel0, channel1 = tester_channels[0]

    block_number = tester_state.block.number
    transfer0 = make_direct_transfer_from_channel(
        block_number,
        channel0,
        channel1,
        amount=90,
        pkey=pkey0,
    )
    transfer0_data = transfer0.encode()

    tampered_transfer = DirectTransfer.decode(transfer0_data)
    tampered_transfer.identifier += 1
    tampered_transfer_data = tampered_transfer.encode()

    with pytest.raises(TransactionFailed):
        nettingchannel.close(tampered_transfer_data, sender=pkey1)
示例#9
0
    def close(
            self,
            ctx,
            sender,
            transfers_encoded,
            locked_encoded,  # noqa
            merkleproof_encoded,
            secret):
        """" Request the closing of the channel. Can be called multiple times.
        lock period starts with first valid call.

        Args:
            sender (address):
                The sender address.

            transfers_encoded (List[transfer]):
                A list of maximum length of 2 containing the transfer encoded
                using the fixed length format, may be empty.

            ctx:
                Block chain state used for mocking.

            locked_encoded (bin):
                The Lock to be unlocked.

            merkleproof_encoded (bin):
                A proof that the given lock is contained in the latest
                transfer. The binary data is composed of a single hash at every
                4bytes.

            secret (bin):
                The secret that unlocks the lock `hashlock = sha3(secret)`.

        Todo:
            if challenged, keep track of who provided the last valid answer,
            punish the wrongdoer here, check that participants only updates
            their own balance are counted, because they could sign something
            for the other party to blame it.
        """
        # pylint: disable=too-many-arguments,too-many-locals,too-many-branches
        # if len(transfers_encoded):
        #     raise ValueError('transfers_encoded needs at least 1 item.')

        if len(transfers_encoded) > 2:
            raise ValueError(
                'transfers_encoded cannot have more than 2 items.')

        if self.settled:
            raise RuntimeError('contract is settled')

        # the merkleproof can be empty, if there is only one haslock
        has_oneofunlocked = locked_encoded or secret
        has_allofunlocked = locked_encoded and secret
        if has_oneofunlocked and not has_allofunlocked:
            raise ValueError(
                'all arguments `merkle_proof`, `locked`, and `secret` must be provided'
            )

        last_sent_transfers = []
        for data in transfers_encoded:
            if data[0] == DIRECTTRANSFER:
                last_sent_transfers.append(DirectTransfer.decode(data))
            elif data[0] == MEDIATEDTRANSFER:
                last_sent_transfers.append(MediatedTransfer.decode(data))
            elif data[0] == CANCELTRANSFER:
                last_sent_transfers.append(CancelTransfer.decode(data))
            # convinience for testing only (LockedTransfer are not exchanged between nodes)
            elif data[0] == LOCKEDTRANSFER:
                last_sent_transfers.append(LockedTransfer.decode(data))
            else:
                raise ValueError('invalid transfer type {}'.format(
                    type(data[0])))

        # keep the latest claim
        for transfer in last_sent_transfers:
            if transfer.sender not in self.participants:
                raise ValueError(
                    'Invalid tansfer, sender is not a participant')

            sender_state = self.participants[transfer.sender]

            if is_newer_transfer(transfer, sender_state):
                sender_state['last_sent_transfer'] = transfer

        partner = self.partner(sender)
        partner_state = self.participants[partner]

        if last_sent_transfers:
            transfer = last_sent_transfers[-1]  # XXX: check me

        # register un-locked
        if merkleproof_encoded:
            merkle_proof = tuple32(merkleproof_encoded)
            lock = Lock.from_bytes(locked_encoded)

            hashlock = lock.hashlock
            if hashlock != sha3(secret):
                raise ValueError('invalid secret')

            # the partner might not have made a transfer
            if partner_state['last_sent_transfer'] is not None:
                assert check_proof(
                    merkle_proof,
                    partner_state['last_sent_transfer'].locksroot,
                    sha3(transfer.lock.as_bytes),
                )

            partner_state['unlocked'].append(lock)

        if self.closed is None:
            log.debug('closing contract',
                      netcontract_address=pex(self.netcontract_address))
            self.closed = ctx['block_number']
示例#10
0
    def close(self, ctx, sender, transfers_encoded, locked_encoded,  # noqa
              merkleproof_encoded, secret):
        """" Request the closing of the channel. Can be called multiple times.
        lock period starts with first valid call.

        Args:
            sender (address):
                The sender address.

            transfers_encoded (List[transfer]):
                A list of maximum length of 2 containing the transfer encoded
                using the fixed length format, may be empty.

            ctx:
                Block chain state used for mocking.

            locked_encoded (bin):
                The Lock to be unlocked.

            merkleproof_encoded (bin):
                A proof that the given lock is contained in the latest
                transfer. The binary data is composed of a single hash at every
                4bytes.

            secret (bin):
                The secret that unlocks the lock `hashlock = sha3(secret)`.

        Todo:
            if challenged, keep track of who provided the last valid answer,
            punish the wrongdoer here, check that participants only updates
            their own balance are counted, because they could sign something
            for the other party to blame it.
        """
        # pylint: disable=too-many-arguments,too-many-locals,too-many-branches
        # if len(transfers_encoded):
        #     raise ValueError('transfers_encoded needs at least 1 item.')

        if len(transfers_encoded) > 2:
            raise ValueError('transfers_encoded cannot have more than 2 items.')

        if self.settled:
            raise RuntimeError('contract is settled')

        # the merkleproof can be empty, if there is only one haslock
        has_oneofunlocked = locked_encoded or secret
        has_allofunlocked = locked_encoded and secret
        if has_oneofunlocked and not has_allofunlocked:
            raise ValueError(
                'all arguments `merkle_proof`, `locked`, and `secret` must be provided'
            )

        last_sent_transfers = []
        for data in transfers_encoded:
            if data[0] == DIRECTTRANSFER:
                last_sent_transfers.append(
                    DirectTransfer.decode(data)
                )
            elif data[0] == MEDIATEDTRANSFER:
                last_sent_transfers.append(
                    MediatedTransfer.decode(data)
                )
            elif data[0] == CANCELTRANSFER:
                last_sent_transfers.append(
                    CancelTransfer.decode(data)
                )
            # convinience for testing only (LockedTransfer are not exchanged between nodes)
            elif data[0] == LOCKEDTRANSFER:
                last_sent_transfers.append(
                    LockedTransfer.decode(data)
                )
            else:
                raise ValueError('invalid transfer type {}'.format(type(data[0])))

        # keep the latest claim
        for transfer in last_sent_transfers:
            if transfer.sender not in self.participants:
                raise ValueError('Invalid tansfer, sender is not a participant')

            sender_state = self.participants[transfer.sender]

            if is_newer_transfer(transfer, sender_state):
                sender_state['last_sent_transfer'] = transfer

        partner = self.partner(sender)
        partner_state = self.participants[partner]

        if last_sent_transfers:
            transfer = last_sent_transfers[-1]  # XXX: check me

        # register un-locked
        if merkleproof_encoded:
            merkle_proof = tuple32(merkleproof_encoded)
            lock = Lock.from_bytes(locked_encoded)

            hashlock = lock.hashlock
            if hashlock != sha3(secret):
                raise ValueError('invalid secret')

            # the partner might not have made a transfer
            if partner_state['last_sent_transfer'] is not None:
                assert check_proof(
                    merkle_proof,
                    partner_state['last_sent_transfer'].locksroot,
                    sha3(transfer.lock.as_bytes),
                )

            partner_state['unlocked'].append(lock)

        if self.closed is None:
            log.debug('closing contract', netcontract_address=pex(self.netcontract_address))
            self.closed = ctx['block_number']