Example #1
0
def make_balance_proof_from_counter(counter) -> BalanceProofUnsignedState:
    return BalanceProofUnsignedState(
        nonce=next(counter),
        transferred_amount=next(counter),
        locked_amount=next(counter),
        locksroot=Locksroot(sha3(next(counter).to_bytes(1, "big"))),
        canonical_identifier=factories.make_canonical_identifier(
            chain_identifier=next(counter),
            token_network_address=factories.make_address(),
            channel_identifier=next(counter),
        ),
    )
Example #2
0
def make_signed_balance_proof_from_counter(counter):
    lock = Lock(
        amount=next(counter),
        expiration=next(counter),
        secrethash=factories.make_secret_hash(next(counter)),
    )
    lock_expired_balance_proof = factories.create(
        factories.BalanceProofSignedStateProperties(
            nonce=next(counter),
            transferred_amount=next(counter),
            locked_amount=next(counter),
            canonical_identifier=factories.make_canonical_identifier(
                token_network_address=factories.make_address(),
                channel_identifier=next(counter)),
            locksroot=Locksroot(sha3(lock.as_bytes)),
            message_hash=AdditionalHash(sha3(b"")),
            sender=factories.HOP1,
            pkey=factories.HOP1_KEY,
        ))

    return lock_expired_balance_proof
Example #3
0
def merkleroot(merkletree: "MerkleTreeState") -> Locksroot:
    """ Return the root element of the merkle tree. """
    assert merkletree.layers, "the merkle tree layers are empty"
    assert merkletree.layers[MERKLEROOT], "the root layer is empty"

    return Locksroot(merkletree.layers[MERKLEROOT][0])
Example #4
0
GENESIS_BLOCK_NUMBER = BlockNumber(0)
# Set at 64 since parity's default is 64 and Geth's default is 128
# TODO: Make this configurable. Since in parity this is also a configurable value
STATE_PRUNING_AFTER_BLOCKS = 64
STATE_PRUNING_SAFETY_MARGIN = 8
NO_STATE_QUERY_AFTER_BLOCKS = STATE_PRUNING_AFTER_BLOCKS - STATE_PRUNING_SAFETY_MARGIN

NULL_ADDRESS_BYTES = bytes(20)
NULL_ADDRESS = to_checksum_address(NULL_ADDRESS_BYTES)

EMPTY_HASH = BlockHash(bytes(32))
EMPTY_BALANCE_HASH = BalanceHash(bytes(32))
EMPTY_MESSAGE_HASH = AdditionalHash(bytes(32))
EMPTY_HASH_KECCAK = keccak(EMPTY_HASH)
EMPTY_SIGNATURE = Signature(bytes(65))
EMPTY_MERKLE_ROOT = Locksroot(bytes(32))
EMPTY_SECRET = Secret(b"")
ZERO_TOKENS = TokenAmount(0)

SECRET_HEXSTRING_LENGTH = len(to_hex(EMPTY_HASH))
SECRETHASH_HEXSTRING_LENGTH = SECRET_HEXSTRING_LENGTH

RECEIPT_FAILURE_CODE = 0


class EthClient(Enum):
    GETH = "geth"
    PARITY = "parity"


ETH_RPC_DEFAULT_PORT = 8545
Example #5
0
def deserialize_locksroot(data: str) -> Locksroot:
    return Locksroot(deserialize_bytes(data))
Example #6
0
def test_regression_multiple_revealsecret(
        raiden_network: List[App],
        token_addresses: List[TokenAddress]) -> None:
    """ Multiple RevealSecret messages arriving at the same time must be
    handled properly.

    Unlock handling followed these steps:

        The Unlock message arrives
        The secret is registered
        The channel is updated and the correspoding lock is removed
        * A balance proof for the new channel state is created and sent to the
          payer
        The channel is unregistered for the given secrethash

    The step marked with an asterisk above introduced a context-switch. This
    allowed a second Reveal Unlock message to be handled before the channel was
    unregistered. And because the channel was already updated an exception was raised
    for an unknown secret.
    """
    app0, app1 = raiden_network
    token = token_addresses[0]
    token_network_address = views.get_token_network_address_by_token_address(
        views.state_from_app(app0), app0.raiden.default_registry.address,
        token)
    assert token_network_address
    channelstate_0_1 = get_channelstate(app0, app1, token_network_address)

    payment_identifier = PaymentID(1)
    secret, secrethash = make_secret_with_hash()
    expiration = BlockExpiration(app0.raiden.get_block_number() + 100)
    lock_amount = PaymentWithFeeAmount(10)
    lock = Lock(amount=lock_amount,
                expiration=expiration,
                secrethash=secrethash)

    nonce = Nonce(1)
    transferred_amount = TokenAmount(0)
    mediated_transfer = LockedTransfer(
        chain_id=UNIT_CHAIN_ID,
        message_identifier=make_message_identifier(),
        payment_identifier=payment_identifier,
        nonce=nonce,
        token_network_address=token_network_address,
        token=token,
        channel_identifier=channelstate_0_1.identifier,
        transferred_amount=transferred_amount,
        locked_amount=LockedAmount(lock_amount),
        recipient=app1.raiden.address,
        locksroot=Locksroot(lock.lockhash),
        lock=lock,
        target=TargetAddress(app1.raiden.address),
        initiator=InitiatorAddress(app0.raiden.address),
        signature=EMPTY_SIGNATURE,
        metadata=Metadata(routes=[
            RouteMetadata(route=[app0.raiden.address, app1.raiden.address])
        ]),
    )
    app0.raiden.sign(mediated_transfer)
    app1.raiden.on_messages([mediated_transfer])

    reveal_secret = RevealSecret(message_identifier=make_message_identifier(),
                                 secret=secret,
                                 signature=EMPTY_SIGNATURE)
    app0.raiden.sign(reveal_secret)

    token_network_address = channelstate_0_1.token_network_address
    unlock = Unlock(
        chain_id=UNIT_CHAIN_ID,
        message_identifier=make_message_identifier(),
        payment_identifier=payment_identifier,
        nonce=Nonce(mediated_transfer.nonce + 1),
        token_network_address=token_network_address,
        channel_identifier=channelstate_0_1.identifier,
        transferred_amount=TokenAmount(lock_amount),
        locked_amount=LockedAmount(0),
        locksroot=LOCKSROOT_OF_NO_LOCKS,
        secret=secret,
        signature=EMPTY_SIGNATURE,
    )
    app0.raiden.sign(unlock)

    messages = [unlock, reveal_secret]
    receive_method = app1.raiden.on_messages
    wait = set(
        gevent.spawn_later(0.1, receive_method, [data]) for data in messages)

    gevent.joinall(wait, raise_error=True)
Example #7
0
def test_receive_secrethashtransfer_unknown(
        raiden_network: List[RaidenService], token_addresses):
    app0 = raiden_network[0]
    token_address = token_addresses[0]

    token_network_address = views.get_token_network_address_by_token_address(
        views.state_from_raiden(app0), app0.default_registry.address,
        token_address)
    assert token_network_address

    other_key = HOP1_KEY
    other_signer = LocalSigner(other_key)
    canonical_identifier = factories.make_canonical_identifier(
        token_network_address=token_network_address)

    amount = TokenAmount(10)
    locksroot = Locksroot(make_32bytes())
    refund_transfer_message = factories.create(
        factories.RefundTransferProperties(
            payment_identifier=PaymentID(1),
            nonce=Nonce(1),
            token=token_address,
            canonical_identifier=canonical_identifier,
            transferred_amount=amount,
            recipient=TargetAddress(app0.address),
            locksroot=locksroot,
            amount=amount,
            secret=UNIT_SECRET,
        ))
    sign_and_inject(refund_transfer_message, other_signer, app0)

    unlock = Unlock(
        chain_id=UNIT_CHAIN_ID,
        message_identifier=make_message_identifier(),
        payment_identifier=PaymentID(1),
        nonce=Nonce(1),
        channel_identifier=canonical_identifier.channel_identifier,
        token_network_address=token_network_address,
        transferred_amount=amount,
        locked_amount=LockedAmount(0),
        locksroot=locksroot,
        secret=UNIT_SECRET,
        signature=EMPTY_SIGNATURE,
    )
    sign_and_inject(unlock, other_signer, app0)

    secret_request_message = SecretRequest(
        message_identifier=make_message_identifier(),
        payment_identifier=PaymentID(1),
        secrethash=UNIT_SECRETHASH,
        amount=PaymentAmount(1),
        expiration=refund_transfer_message.lock.expiration,
        signature=EMPTY_SIGNATURE,
    )
    sign_and_inject(secret_request_message, other_signer, app0)

    reveal_secret_message = RevealSecret(
        message_identifier=make_message_identifier(),
        secret=UNIT_SECRET,
        signature=EMPTY_SIGNATURE)
    sign_and_inject(reveal_secret_message, other_signer, app0)
Example #8
0
def make_locksroot() -> Locksroot:
    return Locksroot(make_32bytes())
Example #9
0
STATE_PRUNING_AFTER_BLOCKS = 64
STATE_PRUNING_SAFETY_MARGIN = 8
NO_STATE_QUERY_AFTER_BLOCKS = STATE_PRUNING_AFTER_BLOCKS - STATE_PRUNING_SAFETY_MARGIN

NULL_ADDRESS_BYTES = bytes(20)
NULL_ADDRESS_HEX = to_hex_address(Address(NULL_ADDRESS_BYTES))
NULL_ADDRESS_CHECKSUM = to_checksum_address(Address(NULL_ADDRESS_BYTES))

EMPTY_HASH = BlockHash(bytes(32))
EMPTY_BALANCE_HASH = BalanceHash(bytes(32))
EMPTY_MESSAGE_HASH = AdditionalHash(bytes(32))
EMPTY_SIGNATURE = Signature(bytes(65))
EMPTY_SECRET = Secret(bytes(32))
EMPTY_SECRETHASH = SecretHash(bytes(32))
EMPTY_SECRET_SHA256 = sha256_secrethash(EMPTY_SECRET)
LOCKSROOT_OF_NO_LOCKS = Locksroot(keccak(b""))
EMPTY_LOCKSROOT = Locksroot(bytes(32))
ZERO_TOKENS = TokenAmount(0)

ABSENT_SECRET = Secret(b"")

SECRET_LENGTH = 32
SECRETHASH_LENGTH = 32

RECEIPT_FAILURE_CODE = 0


class EthClient(Enum):
    GETH = "geth"
    PARITY = "parity"
Example #10
0
STATE_PRUNING_AFTER_BLOCKS = 64
STATE_PRUNING_SAFETY_MARGIN = 8
NO_STATE_QUERY_AFTER_BLOCKS = STATE_PRUNING_AFTER_BLOCKS - STATE_PRUNING_SAFETY_MARGIN

NULL_ADDRESS_BYTES = bytes(20)
NULL_ADDRESS = to_checksum_address(NULL_ADDRESS_BYTES)

EMPTY_HASH = BlockHash(bytes(32))
EMPTY_TRANSACTION_HASH = TransactionHash(bytes(32))
EMPTY_BALANCE_HASH = BalanceHash(bytes(32))
EMPTY_MESSAGE_HASH = AdditionalHash(bytes(32))
EMPTY_SIGNATURE = Signature(bytes(65))
EMPTY_SECRET = Secret(bytes(32))
EMPTY_SECRETHASH = SecretHash(bytes(32))
EMPTY_SECRET_SHA256 = sha256_secrethash(EMPTY_SECRET)
LOCKSROOT_OF_NO_LOCKS = Locksroot(keccak(b""))
ZERO_TOKENS = TokenAmount(0)

ABSENT_SECRET = Secret(b"")

SECRET_LENGTH = 32
SECRETHASH_LENGTH = 32

RECEIPT_FAILURE_CODE = 0


class EthClient(Enum):
    GETH = "geth"
    PARITY = "parity"

Example #11
0
def find_max_pending_transfers(gas_limit) -> None:
    """Measure gas consumption of TokenNetwork.unlock() depending on number of
    pending transfers and find the maximum number of pending transfers so
    gas_limit is not exceeded."""

    tester = ContractTester(generate_keys=2)

    tester.deploy_contract("SecretRegistry")

    tester.deploy_contract(
        "HumanStandardToken",
        _initialAmount=100_000,
        _decimalUnits=3,
        _tokenName="SomeToken",
        _tokenSymbol="SMT",
    )

    tester.deploy_contract(
        "TokenNetwork",
        _token_address=tester.contract_address("HumanStandardToken"),
        _secret_registry=tester.contract_address("SecretRegistry"),
        _chain_id=CHAIN_ID,
        _settlement_timeout_min=100,
        _settlement_timeout_max=200,
        _deprecation_executor=tester.accounts[0],
        _channel_participant_deposit_limit=10000,
        _token_network_deposit_limit=10000,
    )

    tester.call_transaction("HumanStandardToken",
                            "transfer",
                            _to=tester.accounts[1],
                            _value=10000)

    receipt = tester.call_transaction(
        "TokenNetwork",
        "openChannel",
        participant1=tester.accounts[0],
        participant2=tester.accounts[1],
        settle_timeout=150,
    )

    channel_identifier = ChannelID(
        int(encode_hex(receipt["logs"][0]["topics"][1]), 16))

    tester.call_transaction(
        "HumanStandardToken",
        "approve",
        sender=tester.accounts[0],
        _spender=tester.contract_address("TokenNetwork"),
        _value=10000,
    )

    tester.call_transaction(
        "HumanStandardToken",
        "approve",
        sender=tester.accounts[1],
        _spender=tester.contract_address("TokenNetwork"),
        _value=5000,
    )

    tester.call_transaction(
        "TokenNetwork",
        "setTotalDeposit",
        channel_identifier=channel_identifier,
        participant=tester.accounts[0],
        total_deposit=5000,
        partner=tester.accounts[1],
    )

    tester.call_transaction(
        "TokenNetwork",
        "setTotalDeposit",
        channel_identifier=channel_identifier,
        participant=tester.accounts[1],
        total_deposit=2000,
        partner=tester.accounts[0],
    )

    print(
        "Measuring unlock()'s gas cost for different Merkle tree widths, can take a while..."
    )

    before_closing = tester.tester.take_snapshot()
    enough = 0
    too_much = 1024

    nonce = Nonce(10)
    additional_hash = AdditionalHash(urandom(32))
    token_network_address = tester.contract_address("TokenNetwork")

    while enough + 1 < too_much:
        tree_size = (enough + too_much) // 2
        tester.tester.revert_to_snapshot(before_closing)

        pending_transfers_tree = get_pending_transfers_tree(
            tester.web3,
            unlockable_amounts=[1] * tree_size,
            expired_amounts=[])

        balance_hash = hash_balance_data(
            transferred_amount=TokenAmount(3000),
            locked_amount=TokenAmount(2000),
            locksroot=Locksroot(
                pending_transfers_tree.hash_of_packed_transfers),
        )
        canonical_identifier = CanonicalIdentifier(
            chain_identifier=CHAIN_ID,
            token_network_address=token_network_address,
            channel_identifier=ChannelID(channel_identifier),
        )
        data_to_sign = pack_balance_proof(
            nonce=Nonce(nonce),
            balance_hash=balance_hash,
            additional_hash=additional_hash,
            canonical_identifier=canonical_identifier,
        )
        signature = LocalSigner(tester.private_keys[1]).sign(data=data_to_sign)

        tester.call_transaction(
            "TokenNetwork",
            "closeChannel",
            channel_identifier=channel_identifier,
            partner=tester.accounts[1],
            balance_hash=balance_hash,
            nonce=nonce,
            additional_hash=additional_hash,
            signature=signature,
        )

        tester.tester.mine_blocks(160)  # close settlement window

        tester.call_transaction(
            "TokenNetwork",
            "settleChannel",
            channel_identifier=channel_identifier,
            participant1=tester.accounts[0],
            participant1_transferred_amount=0,
            participant1_locked_amount=0,
            participant1_locksroot=b"\x00" * 32,
            participant2=tester.accounts[1],
            participant2_transferred_amount=3000,
            participant2_locked_amount=2000,
            participant2_locksroot=pending_transfers_tree.
            hash_of_packed_transfers,
        )

        receipt = tester.call_transaction(
            "TokenNetwork",
            "unlock",
            channel_identifier=channel_identifier,
            participant=tester.accounts[0],
            partner=tester.accounts[1],
            merkle_tree_leaves=pending_transfers_tree.packed_transfers,
        )
        gas_used = receipt["gasUsed"]

        if gas_used <= gas_limit:
            enough = tree_size
            print(
                f"{tree_size} pending transfers work ({gas_used} gas needed to unlock)"
            )
        else:
            too_much = tree_size
            print(
                f"{tree_size} pending transfers are too much ({gas_used} gas needed to unlock)"
            )
Example #12
0
def merkleroot(merkletree: 'MerkleTreeState') -> Locksroot:
    """ Return the root element of the merkle tree. """
    assert merkletree.layers, 'the merkle tree layers are empty'
    assert merkletree.layers[MERKLEROOT], 'the root layer is empty'

    return Locksroot(merkletree.layers[MERKLEROOT][0])
def test_pfs_send_unique_capacity_and_fee_updates_during_mediated_transfer(
        raiden_network):
    """
    Tests that PFSCapacityUpdates and PFSFeeUpdates are being
    sent only once with the most recent state change in a batch.
    """
    app0, app1 = raiden_network
    chain_state = views.state_from_app(app0)

    # There have been two PFSCapacityUpdates and two PFSFeeUpdates per channel per node
    assert len(get_messages(app0)) == 4
    # The mediator has two channels
    assert len(get_messages(app1)) == 4

    # Now we create two state_changes (Deposit) regarding the same channel
    # and trigger handle_state_changes() of node0. The expected outcome
    # is that only 1 PFSCapacityUpdate and 1 PFSFeeUpdate is being sent
    # not one per state change
    pfs_fee_update_1_of_app0 = get_messages(app0)[1]
    assert isinstance(pfs_fee_update_1_of_app0, PFSFeeUpdate)
    pfs_capacity_update_2_of_app0 = get_messages(app0)[2]
    assert isinstance(pfs_capacity_update_2_of_app0, PFSCapacityUpdate)
    canonical_identifier = pfs_fee_update_1_of_app0.canonical_identifier
    new_total_deposit_1 = pfs_capacity_update_2_of_app0.other_capacity * 2

    deposit_transaction_1 = TransactionChannelDeposit(
        app1.raiden.address, TokenAmount(new_total_deposit_1),
        chain_state.block_number)
    channel_deposit_1 = ContractReceiveChannelDeposit(
        transaction_hash=make_transaction_hash(),
        canonical_identifier=canonical_identifier,
        deposit_transaction=deposit_transaction_1,
        block_number=chain_state.block_number,
        block_hash=chain_state.block_hash,
        fee_config=MediationFeeConfig(),
    )

    new_total_deposit_2 = new_total_deposit_1 * 2
    deposit_transaction_2 = TransactionChannelDeposit(
        app1.raiden.address, TokenAmount(new_total_deposit_2),
        chain_state.block_number)

    channel_deposit_2 = ContractReceiveChannelDeposit(
        transaction_hash=make_transaction_hash(),
        canonical_identifier=canonical_identifier,
        deposit_transaction=deposit_transaction_2,
        block_number=chain_state.block_number,
        block_hash=chain_state.block_hash,
        fee_config=MediationFeeConfig(),
    )

    state_changes = [channel_deposit_1, channel_deposit_2]

    app0.raiden.handle_state_changes(state_changes=state_changes)

    # Now we should see that app0 send 2 new messages,
    # one PFSCapacityUpdate and one PFSFeeUpdate with
    # the updated amount of the initial amount * 4
    # so sending should only be triggered by the second state change

    pfs_capacity_update_3_of_app0 = get_messages(app0)[4]
    assert isinstance(pfs_capacity_update_3_of_app0, PFSCapacityUpdate)
    assert len(get_messages(app0)) == 6
    assert (pfs_capacity_update_3_of_app0.other_capacity ==
            pfs_capacity_update_2_of_app0.updating_capacity * 4)

    # Now we want to test if this also works with a state_change
    # that triggers only a PFSCapacityUpdate and no PFSFeeUpdate.
    # So at the end we expect 1 more PFSCapacityUpdate in the room.

    lock_secret_1 = keccak(b"test_end_state")
    unlock_message_1 = Unlock(
        chain_id=chain_state.chain_id,
        message_identifier=MessageID(123132),
        payment_identifier=PaymentID(1),
        nonce=Nonce(2),
        token_network_address=canonical_identifier.token_network_address,
        channel_identifier=canonical_identifier.channel_identifier,
        transferred_amount=TokenAmount(400),
        locked_amount=LockedAmount(0),
        locksroot=Locksroot(keccak(b"")),
        secret=Secret(lock_secret_1),
        signature=Signature(bytes(65)),
    )
    unlock_message_1.sign(app1.raiden.signer)
    balance_proof_1 = balanceproof_from_envelope(unlock_message_1)

    unlock_1 = ReceiveUnlock(
        message_identifier=MessageID(5135),
        secret=Secret(lock_secret_1),
        balance_proof=balance_proof_1,
        sender=balance_proof_1.sender,
    )

    lock_secret_2 = keccak(b"test_end_state_again")

    unlock_message_2 = Unlock(
        chain_id=chain_state.chain_id,
        message_identifier=MessageID(223132),
        payment_identifier=PaymentID(2),
        nonce=Nonce(2),
        token_network_address=canonical_identifier.token_network_address,
        channel_identifier=canonical_identifier.channel_identifier,
        transferred_amount=TokenAmount(500),
        locked_amount=LockedAmount(0),
        locksroot=Locksroot(keccak(b"")),
        secret=Secret(lock_secret_2),
        signature=Signature(bytes(65)),
    )

    unlock_message_2.sign(app1.raiden.signer)

    balance_proof_2 = balanceproof_from_envelope(unlock_message_2)

    unlock_2 = ReceiveUnlock(
        message_identifier=MessageID(5135),
        secret=Secret(lock_secret_2),
        balance_proof=balance_proof_2,
        sender=balance_proof_2.sender,
    )

    state_changes_2 = [unlock_1, unlock_2]

    app0.raiden.handle_state_changes(state_changes=state_changes_2)

    assert len(get_messages(app0)) == 7
    assert len([
        x for x in get_messages(app0) if isinstance(x, PFSCapacityUpdate)
    ]) == 4