def sign(self, priv_key: str) -> 'MonitorRequest': local_signer = LocalSigner(private_key=decode_hex(priv_key)) return MonitorRequest( channel_identifier=self.channel_identifier, token_network_address=self.token_network_address, chain_id=self.chain_id, balance_hash=self.balance_hash, nonce=self.nonce, additional_hash=self.additional_hash, closing_signature=self.closing_signature, reward_amount=self.reward_amount, reward_proof_signature=encode_hex(local_signer.sign(self.packed_reward_proof_data())), non_closing_signature=encode_hex(local_signer.sign(self.packed_non_closing_data())), )
def get_counter_signature(self, privkey: str) -> Signature: """Get a signature of this balance proof by the other party Useful for `closing_signature` of `TokenNetwork.closeChannel` """ signer = LocalSigner(decode_hex(privkey)) return signer.sign(self.serialize_bin() + self.signature)
def _(properties: BalanceProofSignedStateProperties, defaults=None) -> BalanceProofSignedState: defaults = defaults or BALANCE_PROOF_SIGNED_STATE_DEFAULTS params = _properties_to_dict(properties, defaults) params.update( _properties_to_dict(params.pop('balance_proof'), defaults.balance_proof), ) signer = LocalSigner(params.pop('pkey')) if params['signature'] is EMPTY: keys = ('transferred_amount', 'locked_amount', 'locksroot') balance_hash = hash_balance_data(**_partial_dict(params, *keys)) canonical_identifier = CanonicalIdentifier( chain_identifier=params.pop('chain_id'), token_network_address=params.pop('token_network_identifier'), channel_identifier=params.pop('channel_identifier'), ) params['canonical_identifier'] = canonical_identifier data_to_sign = balance_proof.pack_balance_proof( balance_hash=balance_hash, additional_hash=params['message_hash'], canonical_identifier=canonical_identifier, nonce=params.get('nonce'), ) params['signature'] = signer.sign(data=data_to_sign) return BalanceProofSignedState(**params)
def sign(self, priv_key: PrivateKey) -> "MonitorRequest": local_signer = LocalSigner(private_key=priv_key) non_closing_signature = local_signer.sign( self.packed_non_closing_data()) return MonitorRequest( channel_identifier=self.channel_identifier, token_network_address=self.token_network_address, chain_id=self.chain_id, balance_hash=self.balance_hash, nonce=self.nonce, additional_hash=self.additional_hash, closing_signature=self.closing_signature, non_closing_signature=non_closing_signature, reward_amount=self.reward_amount, non_closing_participant=self.non_closing_participant, reward_proof_signature=local_signer.sign( self.packed_reward_proof_data(non_closing_signature)), msc_address=self.msc_address, )
def make_signed_balance_proof( nonce: typing.Nonce = EMPTY, transferred_amount: typing.TokenAmount = EMPTY, locked_amount: typing.TokenAmount = EMPTY, token_network_address: typing.TokenNetworkID = EMPTY, channel_identifier: typing.ChannelID = EMPTY, locksroot: typing.Locksroot = EMPTY, extra_hash: typing.Keccak256 = EMPTY, private_key: bytes = EMPTY, sender_address: typing.Address = EMPTY, ) -> BalanceProofSignedState: nonce = if_empty(nonce, make_uint256()) transferred_amount = if_empty(transferred_amount, make_uint256()) locked_amount = if_empty(locked_amount, make_uint256()) token_network_address = if_empty(token_network_address, make_address()) channel_identifier = if_empty(channel_identifier, make_uint256()) locksroot = if_empty(locksroot, make_32bytes()) extra_hash = if_empty(extra_hash, make_keccak_hash()) private_key = if_empty(private_key, make_privatekey()) sender_address = if_empty(sender_address, make_address()) signer = LocalSigner(private_key) balance_hash = hash_balance_data( transferred_amount=transferred_amount, locked_amount=locked_amount, locksroot=locksroot, ) data_to_sign = balance_proof.pack_balance_proof( nonce=nonce, balance_hash=balance_hash, additional_hash=extra_hash, canonical_identifier=CanonicalIdentifier( chain_identifier=UNIT_CHAIN_ID, token_network_address=token_network_address, channel_identifier=channel_identifier, ), ) signature = signer.sign(data=data_to_sign) return BalanceProofSignedState( nonce=nonce, transferred_amount=transferred_amount, locked_amount=locked_amount, locksroot=locksroot, message_hash=extra_hash, signature=signature, sender=sender_address, canonical_identifier=CanonicalIdentifier( chain_identifier=UNIT_CHAIN_ID, token_network_address=token_network_address, channel_identifier=channel_identifier, ), )
def test_metrics_iou( # pylint: disable=too-many-locals pathfinding_service_web3_mock: PathfindingService, one_to_n_contract, web3: Web3, deposit_to_udc, get_accounts, get_private_key, ): pfs = pathfinding_service_web3_mock metrics_state = save_metrics_state(metrics.REGISTRY) # Prepare test data account = [decode_hex(acc) for acc in get_accounts(1)][0] local_signer = LocalSigner(private_key=get_private_key(account)) iou = IOU( sender=account, receiver=pfs.address, amount=TokenAmount(100), expiration_block=BlockNumber(100), signature=Signature(bytes([1] * 64)), chain_id=ChainID(61), one_to_n_address=to_canonical_address(one_to_n_contract.address), claimed=False, ) iou.signature = Signature(local_signer.sign(iou.packed_data())) pfs.database.upsert_iou(iou) deposit_to_udc(iou.sender, 300) # Claim IOUs skipped, failures = claim_ious( ious=[iou], claim_cost_rdn=TokenAmount(100), one_to_n_contract=one_to_n_contract, web3=web3, database=pfs.database, ) assert (skipped, failures) == (0, 0) assert ( metrics_state.get_delta( "economics_iou_claims_total", labels=metrics.IouStatus.SUCCESSFUL.to_label_dict() ) == 1.0 ) assert ( metrics_state.get_delta( "economics_iou_claims_token_total", labels=metrics.IouStatus.SUCCESSFUL.to_label_dict(), ) == 100.0 )
def make_params(timestamp: str): params = { "sender": to_checksum_address(sender), "receiver": to_checksum_address(api_sut.pathfinding_service.address), "timestamp": timestamp, } local_signer = LocalSigner(private_key=privkey) params["signature"] = encode_hex( local_signer.sign( to_canonical_address(params["sender"]) + to_canonical_address(params["receiver"]) + params["timestamp"].encode("utf8"))) return params
def matrix_api_shell(address, password, server): am = AccountManager(os.path.expanduser("~/.ethereum/keystore")) signer = LocalSigner(am.get_privkey(to_checksum_address(address), password)) server_name = server.split("//")[1] matrix_password = encode_hex(signer.sign(server_name.encode())) api = GMatrixHttpApi(server) resp = api.login("m.login.password", user=to_normalized_address(address), password=matrix_password) api.token = resp["access_token"] IPython.embed( header=f"Use the `api` object to interact with matrix on {server}.")
def get_login(address, password) -> None: path = os.path.expanduser("~/.ethereum/keystore") if sys.platform.startswith("darwin"): path = os.path.expanduser("~/Library/Ethereum/keystore") am = AccountManager(path) signer = LocalSigner(am.get_privkey(to_checksum_address(address), password)) print(f"Username: {to_normalized_address(address)}") print("Password:"******"\ttransport {i:02d}:", encode_hex(signer.sign(f"transport{i:02d}.raiden.network".encode())), )
def make_params(timestamp: datetime): params = { 'sender': sender, 'receiver': api_sut.pathfinding_service.address, 'timestamp': timestamp.isoformat(), } local_signer = LocalSigner(private_key=decode_hex(privkey)) params['signature'] = encode_hex( local_signer.sign( pack_data( ['address', 'address', 'string'], [params['sender'], params['receiver'], params['timestamp']], ) ) ) return params
def make_params(timestamp: datetime): params = { "sender": sender, "receiver": api_sut.pathfinding_service.address, "timestamp": timestamp.isoformat(), } local_signer = LocalSigner(private_key=decode_hex(privkey)) params["signature"] = encode_hex( local_signer.sign( pack_data( ["address", "address", "string"], [params["sender"], params["receiver"], params["timestamp"]], ) ) ) return params
def make_params(timestamp: str): params = { "sender": to_checksum_address(sender), "receiver": to_checksum_address(api_sut.pathfinding_service.address), "timestamp": timestamp, } local_signer = LocalSigner(private_key=decode_hex(privkey)) params["signature"] = encode_hex( local_signer.sign( pack_data( (params["sender"], "address"), (params["receiver"], "address"), (params["timestamp"], "string"), ))) return params
def update_transfer(self, partner_address: Address, balance_proof: HashedBalanceProof): """Given a valid signed balance proof, this method calls `updateNonClosingBalanceProof` for an open channel """ local_signer = LocalSigner(decode_hex(self.privkey)) serialized = balance_proof.serialize_bin(msg_type=MessageTypeId.BALANCE_PROOF_UPDATE) non_closing_data = serialized + decode_hex(balance_proof.signature) non_closing_signature = encode_hex(local_signer.sign(non_closing_data)) self.contract.functions.updateNonClosingBalanceProof( self.partner_to_channel_id[partner_address], partner_address, self.address, balance_proof.balance_hash, balance_proof.nonce, balance_proof.additional_hash, balance_proof.signature, non_closing_signature, ).transact({'from': self.address})
def test_signer_sign_seed_retry(): # Rsk Address 0x6d369723521B4080A19457D5Fdd2194d633B0c3A privkey = decode_hex( '0x51dd3591fb7ce95b0bd77ca14a5236a4989d399c80b8150d3799dd0afcb14282') message = 'seed' # generated with Metamask's web3.personal.sign signature = decode_hex( "0xd5adc7e384a8e080e187a4de4d0a51820a3585f7c44ddf39f32f94ea58a6611b") signer = LocalSigner(privkey) # signer: Signer = LocalSigner(privkey) print(f'SEED SIGNATURE: {encode_hex(signer.sign(message.encode()))}') result = signer.sign(message.encode())[-32:] assert result == signature
def _(properties: BalanceProofSignedStateProperties, defaults=None) -> BalanceProofSignedState: defaults = defaults or BalanceProofSignedStateProperties.DEFAULTS params = create_properties(properties, defaults).__dict__ signer = LocalSigner(params.pop("pkey")) if params["signature"] is GENERATE: keys = ("transferred_amount", "locked_amount", "locksroot") balance_hash = hash_balance_data(**_partial_dict(params, *keys)) data_to_sign = balance_proof.pack_balance_proof( balance_hash=balance_hash, additional_hash=params["message_hash"], canonical_identifier=params["canonical_identifier"], nonce=params.get("nonce"), ) params["signature"] = signer.sign(data=data_to_sign) return BalanceProofSignedState(**params)
def __init__( self, channel_identifier: ChannelID, token_network_address: TokenNetworkAddress, chain_id: ChainID, nonce: Nonce, additional_hash: AdditionalHash, balance_hash: BalanceHash = None, signature: Signature = None, # these three parameters can be passed instead of `balance_hash` transferred_amount: int = None, locked_amount: int = None, locksroot: str = None, # can be used instead of passing `signature` priv_key: str = None, ) -> None: self.channel_identifier = channel_identifier self.token_network_address = token_network_address self.chain_id = chain_id self.nonce = nonce self.additional_hash = additional_hash if balance_hash is None: assert signature is None balance_hash_data = (transferred_amount, locked_amount, locksroot) assert all(x is not None for x in balance_hash_data) self.balance_hash = encode_hex( Web3.soliditySha3( ['uint256', 'uint256', 'bytes32'], balance_hash_data, )) else: self.balance_hash = balance_hash if signature is None: assert priv_key local_signer = LocalSigner(private_key=decode_hex(priv_key)) self.signature = encode_hex(local_signer.sign( self.serialize_bin())) else: self.signature = signature
def __init__( # pylint: disable=too-many-arguments self, channel_identifier: ChannelID, token_network_address: TokenNetworkAddress, chain_id: ChainID, nonce: Nonce, additional_hash: str, balance_hash: Optional[str] = None, signature: Optional[Signature] = None, # these three parameters can be passed instead of `balance_hash` transferred_amount: Optional[int] = None, locked_amount: Optional[int] = None, locksroot: Optional[str] = None, # can be used instead of passing `signature` priv_key: Optional[PrivateKey] = None, ) -> None: self.channel_identifier = channel_identifier self.token_network_address = token_network_address self.chain_id = chain_id self.nonce = nonce self.additional_hash = additional_hash if balance_hash is None: assert signature is None balance_hash_data = (transferred_amount, locked_amount, locksroot) assert all(x is not None for x in balance_hash_data) self.balance_hash = encode_hex( Web3.solidityKeccak(["uint256", "uint256", "bytes32"], balance_hash_data)) else: self.balance_hash = balance_hash if signature is None: assert priv_key local_signer = LocalSigner(private_key=priv_key) self.signature = local_signer.sign(self.serialize_bin()) else: self.signature = signature
def test_claim_fees( # pylint: disable=too-many-locals pathfinding_service_mock, one_to_n_contract, web3, deposit_to_udc, get_accounts, get_private_key, ): # Prepare test data accounts = [decode_hex(acc) for acc in get_accounts(6)] pfs = pathfinding_service_mock iou_inputs: List[dict] = [ dict(sender=accounts[0], amount=100, deposit=200), dict(sender=accounts[1], amount=200, deposit=100), dict(sender=accounts[2], amount=102, deposit=0), # insufficient deposit dict(sender=accounts[3], amount=103, deposit=99), # insufficient deposit dict(sender=accounts[4], amount=104, claimed=True), # already claimed dict(sender=accounts[4], amount=99), # too low amount dict(sender=accounts[5], expiration_block=1000, amount=104), # does not expire, yet ] # Create IOUs from `iou_inputs` ious: List[IOU] = [] for iou_dict in iou_inputs: local_signer = LocalSigner( private_key=decode_hex(get_private_key(iou_dict["sender"]))) iou = IOU( sender=iou_dict["sender"], receiver=pfs.address, amount=TokenAmount(iou_dict["amount"]), expiration_block=BlockNumber(iou_dict.get("expiration_block", 100)), signature=Signature(bytes([1] * 64)), # dummy, replaced below chain_id=ChainID(1), one_to_n_address=decode_hex(one_to_n_contract.address), claimed=iou_dict.get("claimed", False), ) iou.signature = Signature(local_signer.sign(iou.packed_data())) ious.append(iou) pfs.database.upsert_iou(iou) if iou_dict.get("deposit", 0) > 0: deposit_to_udc(iou.sender, iou_dict["deposit"]) # Check if the right IOUs are considered to be claimable expected_claimable = ious[:4] claimable_ious = list( get_claimable_ious(pfs.database, expires_before=BlockNumber(1000), claim_cost_rdn=TokenAmount(100))) assert claimable_ious == expected_claimable # Claim IOUs skipped, failures = claim_ious( claimable_ious, claim_cost_rdn=TokenAmount(100), one_to_n_contract=one_to_n_contract, web3=web3, database=pfs.database, ) assert (skipped, failures) == (2, 0) # Those IOUs which have enough deposit should be marked as claimed # * in the blockchain # * in the database # All other IOUs must not be changed. claimable_with_enough_deposit = ious[:2] for iou in ious: expected_claimed = iou in claimable_with_enough_deposit iou_in_db = pfs.database.get_iou(sender=iou.sender, expiration_block=iou.expiration_block) assert iou_in_db.claimed == expected_claimed is_settled = bool( one_to_n_contract.functions.settled_sessions( iou.session_id).call()) assert is_settled == expected_claimed
def test_token_network_proxy(token_network_proxy, private_keys, token_proxy, chain_id, web3, contract_manager): assert token_network_proxy.settlement_timeout_min( ) == TEST_SETTLE_TIMEOUT_MIN assert token_network_proxy.settlement_timeout_max( ) == TEST_SETTLE_TIMEOUT_MAX token_network_address = to_canonical_address( token_network_proxy.proxy.contract.address) c1_signer = LocalSigner(private_keys[1]) c1_client = JSONRPCClient(web3, private_keys[1]) c1_chain = BlockChainService(jsonrpc_client=c1_client, contract_manager=contract_manager) c2_client = JSONRPCClient(web3, private_keys[2]) c1_token_network_proxy = TokenNetwork( jsonrpc_client=c1_client, token_network_address=token_network_address, contract_manager=contract_manager, ) c2_token_network_proxy = TokenNetwork( jsonrpc_client=c2_client, token_network_address=token_network_address, contract_manager=contract_manager, ) initial_token_balance = 100 token_proxy.transfer(c1_client.address, initial_token_balance) token_proxy.transfer(c2_client.address, initial_token_balance) initial_balance_c1 = token_proxy.balance_of(c1_client.address) assert initial_balance_c1 == initial_token_balance initial_balance_c2 = token_proxy.balance_of(c2_client.address) assert initial_balance_c2 == initial_token_balance # instantiating a new channel - test basic assumptions assert (c1_token_network_proxy._channel_exists_and_not_settled( participant1=c1_client.address, participant2=c2_client.address, block_identifier="latest", ) is False) channel_identifier = c1_token_network_proxy._call_and_check_result( "latest", "getChannelIdentifier", to_checksum_address(c1_client.address), to_checksum_address(c2_client.address), ) assert channel_identifier == 0 msg = "Zero is not a valid channel_identifier identifier, ValueError must be " "raised." with pytest.raises(ValueError, message=msg): assert c1_token_network_proxy.channel_is_opened( participant1=c1_client.address, participant2=c2_client.address, block_identifier="latest", channel_identifier=0, ) msg = "Zero is not a valid channel_identifier identifier. ValueError must be " "raised." with pytest.raises(ValueError, message=msg): assert c1_token_network_proxy.channel_is_closed( participant1=c1_client.address, participant2=c2_client.address, block_identifier="latest", channel_identifier=0, ) msg = ("Opening a channel with a settle_timeout lower then token " "network's minimum will fail. This must be validated and the " "transaction must not be sent.") with pytest.raises(InvalidSettleTimeout, message=msg): c1_token_network_proxy.new_netting_channel( partner=c2_client.address, settle_timeout=TEST_SETTLE_TIMEOUT_MIN - 1, given_block_identifier="latest", ) msg = ("Opening a channel with a settle_timeout larger then token " "network's maximum will fail. This must be validated and the " "transaction must not be sent.") with pytest.raises(InvalidSettleTimeout, message=msg): c1_token_network_proxy.new_netting_channel( partner=c2_client.address, settle_timeout=TEST_SETTLE_TIMEOUT_MAX + 1, given_block_identifier="latest", ) msg = ( "Opening a channel with itself is not allow. This must be validated and " "the transaction must not be sent.") with pytest.raises(SamePeerAddress, message=msg): c1_token_network_proxy.new_netting_channel( partner=c1_client.address, settle_timeout=TEST_SETTLE_TIMEOUT_MIN, given_block_identifier="latest", ) msg = "Trying a deposit to an inexisting channel must fail." with pytest.raises(RaidenUnrecoverableError, message=msg, match="does not exist"): c1_token_network_proxy.set_total_deposit( given_block_identifier="latest", channel_identifier=1, total_deposit=1, partner=c2_client.address, ) msg = "Trying to close an inexisting channel must fail." match = "The channel was not open at the provided block" with pytest.raises(RaidenUnrecoverableError, message=msg, match=match): c1_token_network_proxy.close( channel_identifier=1, partner=c2_client.address, balance_hash=EMPTY_HASH, nonce=0, additional_hash=EMPTY_HASH, signature=EMPTY_SIGNATURE, given_block_identifier="latest", ) channel_identifier = c1_token_network_proxy.new_netting_channel( partner=c2_client.address, settle_timeout=TEST_SETTLE_TIMEOUT_MIN, given_block_identifier="latest", ) msg = "new_netting_channel did not return a valid channel id" assert isinstance(channel_identifier, T_ChannelID), msg msg = "multiple channels with the same peer are not allowed" with pytest.raises(DuplicatedChannelError, message=msg): c1_token_network_proxy.new_netting_channel( partner=c2_client.address, settle_timeout=TEST_SETTLE_TIMEOUT_MIN, given_block_identifier="latest", ) assert (c1_token_network_proxy._channel_exists_and_not_settled( participant1=c1_client.address, participant2=c2_client.address, channel_identifier=channel_identifier, block_identifier="latest", ) is True) assert (c1_token_network_proxy.channel_is_opened( participant1=c1_client.address, participant2=c2_client.address, block_identifier="latest", channel_identifier=channel_identifier, ) is True) msg = "set_total_deposit must fail if the amount exceed the account's balance" with pytest.raises(DepositMismatch, message=msg): c1_token_network_proxy.set_total_deposit( given_block_identifier="latest", channel_identifier=channel_identifier, total_deposit=initial_token_balance + 1, partner=c2_client.address, ) msg = "set_total_deposit must fail with a negative amount" with pytest.raises(DepositMismatch): c1_token_network_proxy.set_total_deposit( given_block_identifier="latest", channel_identifier=channel_identifier, total_deposit=-1, partner=c2_client.address, ) msg = "set_total_deposit must fail with a zero amount" with pytest.raises(DepositMismatch): c1_token_network_proxy.set_total_deposit( given_block_identifier="latest", channel_identifier=channel_identifier, total_deposit=0, partner=c2_client.address, ) c1_token_network_proxy.set_total_deposit( given_block_identifier="latest", channel_identifier=channel_identifier, total_deposit=10, partner=c2_client.address, ) transferred_amount = 3 balance_proof = BalanceProof( channel_identifier=channel_identifier, token_network_address=to_checksum_address(token_network_address), nonce=1, chain_id=chain_id, transferred_amount=transferred_amount, ) signature = c1_signer.sign(data=balance_proof.serialize_bin()) balance_proof.signature = encode_hex(signature) signature_number = int.from_bytes(signature, "big") bit_to_change = random.randint(0, SIGNATURE_SIZE_IN_BITS - 1) signature_number_bit_flipped = signature_number ^ (2**bit_to_change) invalid_signatures = [ EMPTY_SIGNATURE, b"\x11" * 65, signature_number_bit_flipped.to_bytes(len(signature), "big"), ] msg = "close must fail if the signature is invalid" for invalid_signature in invalid_signatures: with pytest.raises(RaidenUnrecoverableError, message=msg): c2_token_network_proxy.close( channel_identifier=channel_identifier, partner=c1_client.address, balance_hash=decode_hex(balance_proof.balance_hash), nonce=balance_proof.nonce, additional_hash=decode_hex(balance_proof.additional_hash), signature=invalid_signature, given_block_identifier="latest", ) blocknumber_prior_to_close = c2_client.block_number() c2_token_network_proxy.close( channel_identifier=channel_identifier, partner=c1_client.address, balance_hash=decode_hex(balance_proof.balance_hash), nonce=balance_proof.nonce, additional_hash=decode_hex(balance_proof.additional_hash), signature=decode_hex(balance_proof.signature), given_block_identifier="latest", ) assert (c1_token_network_proxy.channel_is_closed( participant1=c1_client.address, participant2=c2_client.address, block_identifier="latest", channel_identifier=channel_identifier, ) is True) assert (c1_token_network_proxy._channel_exists_and_not_settled( participant1=c1_client.address, participant2=c2_client.address, channel_identifier=channel_identifier, block_identifier="latest", ) is True) msg = ( "given_block_identifier is the block at which the transaction is being " "sent. If the channel is already closed at that block the client code " "has a programming error. An exception is raised for that.") with pytest.raises(RaidenUnrecoverableError, message=msg): c2_token_network_proxy.close( channel_identifier=channel_identifier, partner=c1_client.address, balance_hash=decode_hex(balance_proof.balance_hash), nonce=balance_proof.nonce, additional_hash=decode_hex(balance_proof.additional_hash), signature=decode_hex(balance_proof.signature), given_block_identifier="latest", ) msg = ("The channel cannot be closed two times. If it was not closed at " "given_block_identifier but it is closed at the time the proxy is " "called an exception must be raised.") with pytest.raises(RaidenRecoverableError, message=msg): c2_token_network_proxy.close( channel_identifier=channel_identifier, partner=c1_client.address, balance_hash=decode_hex(balance_proof.balance_hash), nonce=balance_proof.nonce, additional_hash=decode_hex(balance_proof.additional_hash), signature=decode_hex(balance_proof.signature), given_block_identifier=blocknumber_prior_to_close, ) msg = "depositing to a closed channel must fail" match = "setTotalDeposit call will fail. Channel is already closed" with pytest.raises(RaidenRecoverableError, message=msg, match=match): c2_token_network_proxy.set_total_deposit( given_block_identifier=blocknumber_prior_to_close, channel_identifier=channel_identifier, total_deposit=20, partner=c1_client.address, ) c1_chain.wait_until_block(target_block_number=c1_chain.block_number() + TEST_SETTLE_TIMEOUT_MIN) invalid_transferred_amount = 1 msg = "settle with invalid transferred_amount data must fail" with pytest.raises(RaidenUnrecoverableError, message=msg): c2_token_network_proxy.settle( channel_identifier=channel_identifier, transferred_amount=invalid_transferred_amount, locked_amount=0, locksroot=EMPTY_HASH, partner=c1_client.address, partner_transferred_amount=transferred_amount, partner_locked_amount=0, partner_locksroot=EMPTY_HASH, given_block_identifier="latest", ) c2_token_network_proxy.settle( channel_identifier=channel_identifier, transferred_amount=0, locked_amount=0, locksroot=EMPTY_HASH, partner=c1_client.address, partner_transferred_amount=transferred_amount, partner_locked_amount=0, partner_locksroot=EMPTY_HASH, given_block_identifier="latest", ) assert (c1_token_network_proxy._channel_exists_and_not_settled( participant1=c1_client.address, participant2=c2_client.address, channel_identifier=channel_identifier, block_identifier="latest", ) is False) assert token_proxy.balance_of(c1_client.address) == (initial_balance_c1 - transferred_amount) assert token_proxy.balance_of(c2_client.address) == (initial_balance_c2 + transferred_amount) msg = "depositing to a settled channel must fail" match = "setTotalDeposit call will fail." with pytest.raises(RaidenUnrecoverableError, message=msg, match=match): c1_token_network_proxy.set_total_deposit( given_block_identifier="latest", channel_identifier=channel_identifier, total_deposit=10, partner=c2_client.address, )
def test_token_network_proxy(token_network_proxy, private_keys, token_proxy, chain_id, web3, contract_manager): assert token_network_proxy.settlement_timeout_min( ) == TEST_SETTLE_TIMEOUT_MIN assert token_network_proxy.settlement_timeout_max( ) == TEST_SETTLE_TIMEOUT_MAX token_network_address = to_canonical_address( token_network_proxy.proxy.contract.address) c1_signer = LocalSigner(private_keys[1]) c1_client = JSONRPCClient(web3, private_keys[1]) c1_proxy_manager = ProxyManager( rpc_client=c1_client, contract_manager=contract_manager, metadata=ProxyManagerMetadata( token_network_registry_deployed_at=GENESIS_BLOCK_NUMBER, filters_start_at=GENESIS_BLOCK_NUMBER, ), ) c2_client = JSONRPCClient(web3, private_keys[2]) c2_proxy_manager = ProxyManager( rpc_client=c2_client, contract_manager=contract_manager, metadata=ProxyManagerMetadata( token_network_registry_deployed_at=GENESIS_BLOCK_NUMBER, filters_start_at=GENESIS_BLOCK_NUMBER, ), ) c2_signer = LocalSigner(private_keys[2]) c1_token_network_proxy = c1_proxy_manager.token_network( token_network_address) c2_token_network_proxy = c2_proxy_manager.token_network( token_network_address) initial_token_balance = 100 token_proxy.transfer(c1_client.address, initial_token_balance) token_proxy.transfer(c2_client.address, initial_token_balance) initial_balance_c1 = token_proxy.balance_of(c1_client.address) assert initial_balance_c1 == initial_token_balance initial_balance_c2 = token_proxy.balance_of(c2_client.address) assert initial_balance_c2 == initial_token_balance # instantiating a new channel - test basic assumptions assert (c1_token_network_proxy.get_channel_identifier_or_none( participant1=c1_client.address, participant2=c2_client.address, block_identifier="latest", ) is None) msg = "Hex encoded addresses are not supported, an assertion must be raised" with pytest.raises(AssertionError): c1_token_network_proxy.get_channel_identifier( participant1=to_checksum_address(c1_client.address), participant2=to_checksum_address(c2_client.address), block_identifier="latest", ) pytest.fail(msg) msg = "Zero is not a valid channel_identifier identifier, an exception must be raised." with pytest.raises(InvalidChannelID): assert c1_token_network_proxy.channel_is_opened( participant1=c1_client.address, participant2=c2_client.address, block_identifier="latest", channel_identifier=0, ) pytest.fail(msg) msg = "Zero is not a valid channel_identifier identifier. an exception must be raised." with pytest.raises(InvalidChannelID): assert c1_token_network_proxy.channel_is_closed( participant1=c1_client.address, participant2=c2_client.address, block_identifier="latest", channel_identifier=0, ) pytest.fail(msg) msg = ("Opening a channel with a settle_timeout lower then token " "network's minimum will fail. This must be validated and the " "transaction must not be sent.") with pytest.raises(InvalidSettleTimeout): c1_token_network_proxy.new_netting_channel( partner=c2_client.address, settle_timeout=TEST_SETTLE_TIMEOUT_MIN - 1, given_block_identifier="latest", ) pytest.fail(msg) # Using exactly the minimal timeout must succeed c1_token_network_proxy.new_netting_channel( partner=make_address(), settle_timeout=TEST_SETTLE_TIMEOUT_MIN, given_block_identifier="latest", ) msg = ("Opening a channel with a settle_timeout larger then token " "network's maximum will fail. This must be validated and the " "transaction must not be sent.") with pytest.raises(InvalidSettleTimeout): c1_token_network_proxy.new_netting_channel( partner=c2_client.address, settle_timeout=TEST_SETTLE_TIMEOUT_MAX + 1, given_block_identifier="latest", ) pytest.fail(msg) # Using exactly the maximal timeout must succeed c1_token_network_proxy.new_netting_channel( partner=make_address(), settle_timeout=TEST_SETTLE_TIMEOUT_MAX, given_block_identifier="latest", ) msg = ( "Opening a channel with itself is not allow. This must be validated and " "the transaction must not be sent.") with pytest.raises(SamePeerAddress): c1_token_network_proxy.new_netting_channel( partner=c1_client.address, settle_timeout=TEST_SETTLE_TIMEOUT_MIN, given_block_identifier="latest", ) pytest.fail(msg) msg = "Trying a deposit to an inexisting channel must fail." with pytest.raises(BrokenPreconditionError): c1_token_network_proxy.set_total_deposit( given_block_identifier="latest", channel_identifier=100, total_deposit=1, partner=c2_client.address, ) pytest.fail(msg) empty_balance_proof = BalanceProof( channel_identifier=100, token_network_address=c1_token_network_proxy.address, balance_hash=encode_hex(EMPTY_BALANCE_HASH), nonce=0, chain_id=chain_id, transferred_amount=0, ) closing_data = (empty_balance_proof.serialize_bin( msg_type=MessageTypeId.BALANCE_PROOF) + EMPTY_SIGNATURE) msg = "Trying to close an inexisting channel must fail." match = "The channel was not open at the provided block" with pytest.raises(RaidenUnrecoverableError, match=match): c1_token_network_proxy.close( channel_identifier=100, partner=c2_client.address, balance_hash=EMPTY_HASH, nonce=0, additional_hash=EMPTY_HASH, non_closing_signature=EMPTY_SIGNATURE, closing_signature=c1_signer.sign(data=closing_data), given_block_identifier="latest", ) pytest.fail(msg) channel_identifier = c1_token_network_proxy.new_netting_channel( partner=c2_client.address, settle_timeout=TEST_SETTLE_TIMEOUT_MIN, given_block_identifier="latest", ) msg = "new_netting_channel did not return a valid channel id" assert isinstance(channel_identifier, T_ChannelID), msg msg = "multiple channels with the same peer are not allowed" with pytest.raises(BrokenPreconditionError): c1_token_network_proxy.new_netting_channel( partner=c2_client.address, settle_timeout=TEST_SETTLE_TIMEOUT_MIN, given_block_identifier="latest", ) pytest.fail(msg) assert (c1_token_network_proxy.get_channel_identifier_or_none( participant1=c1_client.address, participant2=c2_client.address, block_identifier="latest", ) is not None) assert (c1_token_network_proxy.channel_is_opened( participant1=c1_client.address, participant2=c2_client.address, block_identifier="latest", channel_identifier=channel_identifier, ) is True) msg = "set_total_deposit must fail if the amount exceed the account's balance" with pytest.raises(BrokenPreconditionError): c1_token_network_proxy.set_total_deposit( given_block_identifier="latest", channel_identifier=channel_identifier, total_deposit=initial_token_balance + 1, partner=c2_client.address, ) pytest.fail(msg) msg = "set_total_deposit must fail with a negative amount" with pytest.raises(BrokenPreconditionError): c1_token_network_proxy.set_total_deposit( given_block_identifier="latest", channel_identifier=channel_identifier, total_deposit=-1, partner=c2_client.address, ) pytest.fail(msg) msg = "set_total_deposit must fail with a zero amount" with pytest.raises(BrokenPreconditionError): c1_token_network_proxy.set_total_deposit( given_block_identifier="latest", channel_identifier=channel_identifier, total_deposit=0, partner=c2_client.address, ) pytest.fail(msg) c1_token_network_proxy.set_total_deposit( given_block_identifier="latest", channel_identifier=channel_identifier, total_deposit=10, partner=c2_client.address, ) transferred_amount = 3 balance_proof = BalanceProof( channel_identifier=channel_identifier, token_network_address=to_checksum_address(token_network_address), nonce=1, chain_id=chain_id, transferred_amount=transferred_amount, ) signature = c1_signer.sign(data=balance_proof.serialize_bin()) balance_proof.signature = encode_hex(signature) signature_number = int.from_bytes(signature, "big") bit_to_change = random.randint(0, SIGNATURE_SIZE_IN_BITS - 1) signature_number_bit_flipped = signature_number ^ (2**bit_to_change) invalid_signatures = [ EMPTY_SIGNATURE, b"\x11" * 65, signature_number_bit_flipped.to_bytes(len(signature), "big"), ] msg = "close must fail if the closing_signature is invalid" for invalid_signature in invalid_signatures: closing_data = ( balance_proof.serialize_bin(msg_type=MessageTypeId.BALANCE_PROOF) + invalid_signature) with pytest.raises(RaidenUnrecoverableError): c2_token_network_proxy.close( channel_identifier=channel_identifier, partner=c1_client.address, balance_hash=decode_hex(balance_proof.balance_hash), nonce=balance_proof.nonce, additional_hash=decode_hex(balance_proof.additional_hash), non_closing_signature=invalid_signature, closing_signature=c2_signer.sign(data=closing_data), given_block_identifier="latest", ) pytest.fail(msg) blocknumber_prior_to_close = c2_client.block_number() closing_data = balance_proof.serialize_bin( msg_type=MessageTypeId.BALANCE_PROOF) + decode_hex( balance_proof.signature) c2_token_network_proxy.close( channel_identifier=channel_identifier, partner=c1_client.address, balance_hash=decode_hex(balance_proof.balance_hash), nonce=balance_proof.nonce, additional_hash=decode_hex(balance_proof.additional_hash), non_closing_signature=decode_hex(balance_proof.signature), closing_signature=c2_signer.sign(data=closing_data), given_block_identifier="latest", ) assert (c1_token_network_proxy.channel_is_closed( participant1=c1_client.address, participant2=c2_client.address, block_identifier="latest", channel_identifier=channel_identifier, ) is True) assert (c1_token_network_proxy.get_channel_identifier_or_none( participant1=c1_client.address, participant2=c2_client.address, block_identifier="latest", ) is not None) msg = ( "given_block_identifier is the block at which the transaction is being " "sent. If the channel is already closed at that block the client code " "has a programming error. An exception is raised for that.") with pytest.raises(RaidenUnrecoverableError): c2_token_network_proxy.close( channel_identifier=channel_identifier, partner=c1_client.address, balance_hash=decode_hex(balance_proof.balance_hash), nonce=balance_proof.nonce, additional_hash=decode_hex(balance_proof.additional_hash), non_closing_signature=decode_hex(balance_proof.signature), closing_signature=c2_signer.sign(data=closing_data), given_block_identifier="latest", ) pytest.fail(msg) msg = ("The channel cannot be closed two times. If it was not closed at " "given_block_identifier but it is closed at the time the proxy is " "called an exception must be raised.") with pytest.raises(RaidenRecoverableError): c2_token_network_proxy.close( channel_identifier=channel_identifier, partner=c1_client.address, balance_hash=decode_hex(balance_proof.balance_hash), nonce=balance_proof.nonce, additional_hash=decode_hex(balance_proof.additional_hash), non_closing_signature=decode_hex(balance_proof.signature), closing_signature=c2_signer.sign(data=closing_data), given_block_identifier=blocknumber_prior_to_close, ) pytest.fail(msg) msg = "depositing to a closed channel must fail" match = "closed" with pytest.raises(RaidenRecoverableError, match=match): c2_token_network_proxy.set_total_deposit( given_block_identifier=blocknumber_prior_to_close, channel_identifier=channel_identifier, total_deposit=20, partner=c1_client.address, ) pytest.fail(msg) c1_proxy_manager.wait_until_block( target_block_number=c1_proxy_manager.client.block_number() + TEST_SETTLE_TIMEOUT_MIN) invalid_transferred_amount = 1 msg = "settle with invalid transferred_amount data must fail" with pytest.raises(BrokenPreconditionError): c2_token_network_proxy.settle( channel_identifier=channel_identifier, transferred_amount=invalid_transferred_amount, locked_amount=0, locksroot=LOCKSROOT_OF_NO_LOCKS, partner=c1_client.address, partner_transferred_amount=transferred_amount, partner_locked_amount=0, partner_locksroot=LOCKSROOT_OF_NO_LOCKS, given_block_identifier="latest", ) pytest.fail(msg) c2_token_network_proxy.settle( channel_identifier=channel_identifier, transferred_amount=0, locked_amount=0, locksroot=LOCKSROOT_OF_NO_LOCKS, partner=c1_client.address, partner_transferred_amount=transferred_amount, partner_locked_amount=0, partner_locksroot=LOCKSROOT_OF_NO_LOCKS, given_block_identifier="latest", ) assert (c1_token_network_proxy.get_channel_identifier_or_none( participant1=c1_client.address, participant2=c2_client.address, block_identifier="latest", ) is None) assert token_proxy.balance_of(c1_client.address) == (initial_balance_c1 - transferred_amount) assert token_proxy.balance_of(c2_client.address) == (initial_balance_c2 + transferred_amount) msg = "depositing to a settled channel must fail" with pytest.raises(BrokenPreconditionError): c1_token_network_proxy.set_total_deposit( given_block_identifier="latest", channel_identifier=channel_identifier, total_deposit=10, partner=c2_client.address, ) pytest.fail(msg)
def test_token_network_proxy_update_transfer(token_network_proxy, private_keys, token_proxy, chain_id, web3, contract_manager): """Tests channel lifecycle, with `update_transfer` before settling""" token_network_address = to_canonical_address( token_network_proxy.proxy.contract.address) c1_client = JSONRPCClient(web3, private_keys[1]) c1_proxy_manager = ProxyManager( rpc_client=c1_client, contract_manager=contract_manager, metadata=ProxyManagerMetadata( token_network_registry_deployed_at=GENESIS_BLOCK_NUMBER, filters_start_at=GENESIS_BLOCK_NUMBER, ), ) c1_signer = LocalSigner(private_keys[1]) c2_client = JSONRPCClient(web3, private_keys[2]) c2_proxy_manager = ProxyManager( rpc_client=c2_client, contract_manager=contract_manager, metadata=ProxyManagerMetadata( token_network_registry_deployed_at=GENESIS_BLOCK_NUMBER, filters_start_at=GENESIS_BLOCK_NUMBER, ), ) c1_token_network_proxy = c1_proxy_manager.token_network( token_network_address) c2_token_network_proxy = c2_proxy_manager.token_network( token_network_address) # create a channel channel_identifier = c1_token_network_proxy.new_netting_channel( partner=c2_client.address, settle_timeout=10, given_block_identifier="latest") # deposit to the channel initial_balance = 100 token_proxy.transfer(c1_client.address, initial_balance) token_proxy.transfer(c2_client.address, initial_balance) initial_balance_c1 = token_proxy.balance_of(c1_client.address) assert initial_balance_c1 == initial_balance initial_balance_c2 = token_proxy.balance_of(c2_client.address) assert initial_balance_c2 == initial_balance c1_token_network_proxy.set_total_deposit( given_block_identifier="latest", channel_identifier=channel_identifier, total_deposit=10, partner=c2_client.address, ) c2_token_network_proxy.set_total_deposit( given_block_identifier="latest", channel_identifier=channel_identifier, total_deposit=10, partner=c1_client.address, ) # balance proof signed by c1 transferred_amount_c1 = 1 transferred_amount_c2 = 3 balance_proof_c1 = BalanceProof( channel_identifier=channel_identifier, token_network_address=to_checksum_address(token_network_address), nonce=1, chain_id=chain_id, transferred_amount=transferred_amount_c1, ) balance_proof_c1.signature = encode_hex( LocalSigner( private_keys[1]).sign(data=balance_proof_c1.serialize_bin())) # balance proof signed by c2 balance_proof_c2 = BalanceProof( channel_identifier=channel_identifier, token_network_address=to_checksum_address(token_network_address), nonce=2, chain_id=chain_id, transferred_amount=transferred_amount_c2, ) balance_proof_c2.signature = encode_hex( LocalSigner( private_keys[2]).sign(data=balance_proof_c2.serialize_bin())) non_closing_data = balance_proof_c1.serialize_bin( msg_type=MessageTypeId.BALANCE_PROOF_UPDATE) + decode_hex( balance_proof_c1.signature) non_closing_signature = LocalSigner( c2_client.privkey).sign(data=non_closing_data) with pytest.raises(RaidenUnrecoverableError) as exc: c2_token_network_proxy.update_transfer( channel_identifier=channel_identifier, partner=c1_client.address, balance_hash=decode_hex(balance_proof_c1.balance_hash), nonce=balance_proof_c1.nonce, additional_hash=decode_hex(balance_proof_c1.additional_hash), closing_signature=decode_hex(balance_proof_c1.signature), non_closing_signature=non_closing_signature, given_block_identifier="latest", ) assert "not in a closed state" in str(exc) # close by c1 closing_data = balance_proof_c2.serialize_bin( msg_type=MessageTypeId.BALANCE_PROOF) + decode_hex( balance_proof_c2.signature) c1_token_network_proxy.close( channel_identifier=channel_identifier, partner=c2_client.address, balance_hash=decode_hex(balance_proof_c2.balance_hash), nonce=balance_proof_c2.nonce, additional_hash=decode_hex(balance_proof_c2.additional_hash), non_closing_signature=decode_hex(balance_proof_c2.signature), closing_signature=c1_signer.sign(data=closing_data), given_block_identifier="latest", ) # update transfer with completely invalid closing signature with pytest.raises(RaidenUnrecoverableError) as excinfo: c2_token_network_proxy.update_transfer( channel_identifier=channel_identifier, partner=c1_client.address, balance_hash=decode_hex(balance_proof_c1.balance_hash), nonce=balance_proof_c1.nonce, additional_hash=decode_hex(balance_proof_c1.additional_hash), closing_signature=b"", non_closing_signature=b"", given_block_identifier="latest", ) assert str(excinfo.value) == "Couldn't verify the balance proof signature" # using invalid non-closing signature # Usual mistake when calling update Transfer - balance proof signature is missing in the data non_closing_data = balance_proof_c1.serialize_bin( msg_type=MessageTypeId.BALANCE_PROOF_UPDATE) non_closing_signature = LocalSigner( c2_client.privkey).sign(data=non_closing_data) with pytest.raises(RaidenUnrecoverableError): c2_token_network_proxy.update_transfer( channel_identifier=channel_identifier, partner=c1_client.address, balance_hash=decode_hex(balance_proof_c1.balance_hash), nonce=balance_proof_c1.nonce, additional_hash=decode_hex(balance_proof_c1.additional_hash), closing_signature=decode_hex(balance_proof_c1.signature), non_closing_signature=non_closing_signature, given_block_identifier="latest", ) non_closing_data = balance_proof_c1.serialize_bin( msg_type=MessageTypeId.BALANCE_PROOF_UPDATE) + decode_hex( balance_proof_c1.signature) non_closing_signature = LocalSigner( c2_client.privkey).sign(data=non_closing_data) c2_token_network_proxy.update_transfer( channel_identifier=channel_identifier, partner=c1_client.address, balance_hash=decode_hex(balance_proof_c1.balance_hash), nonce=balance_proof_c1.nonce, additional_hash=decode_hex(balance_proof_c1.additional_hash), closing_signature=decode_hex(balance_proof_c1.signature), non_closing_signature=non_closing_signature, given_block_identifier="latest", ) with pytest.raises(BrokenPreconditionError) as exc: c1_token_network_proxy.settle( channel_identifier=channel_identifier, transferred_amount=transferred_amount_c1, locked_amount=0, locksroot=LOCKSROOT_OF_NO_LOCKS, partner=c2_client.address, partner_transferred_amount=transferred_amount_c2, partner_locked_amount=0, partner_locksroot=LOCKSROOT_OF_NO_LOCKS, given_block_identifier="latest", ) assert "cannot be settled before settlement window is over" in str(exc) c1_proxy_manager.wait_until_block( target_block_number=c1_proxy_manager.client.block_number() + 10) # settling with an invalid amount with pytest.raises(BrokenPreconditionError): c1_token_network_proxy.settle( channel_identifier=channel_identifier, transferred_amount=2, locked_amount=0, locksroot=LOCKSROOT_OF_NO_LOCKS, partner=c2_client.address, partner_transferred_amount=2, partner_locked_amount=0, partner_locksroot=LOCKSROOT_OF_NO_LOCKS, given_block_identifier="latest", ) # proper settle c1_token_network_proxy.settle( channel_identifier=channel_identifier, transferred_amount=transferred_amount_c1, locked_amount=0, locksroot=LOCKSROOT_OF_NO_LOCKS, partner=c2_client.address, partner_transferred_amount=transferred_amount_c2, partner_locked_amount=0, partner_locksroot=LOCKSROOT_OF_NO_LOCKS, given_block_identifier="latest", ) assert token_proxy.balance_of( c2_client.address) == (initial_balance_c2 + transferred_amount_c1 - transferred_amount_c2) assert token_proxy.balance_of( c1_client.address) == (initial_balance_c1 + transferred_amount_c2 - transferred_amount_c1) # Already settled with pytest.raises(BrokenPreconditionError) as exc: c2_token_network_proxy.set_total_deposit( given_block_identifier="latest", channel_identifier=channel_identifier, total_deposit=20, partner=c1_client.address, ) assert "getChannelIdentifier returned 0" in str(exc)