def verify_balance_proof(self, sender, open_block_number, balance, signature): """Verify that a balance proof is valid and return the sender. Does not check the balance itself. :returns: the channel """ assert is_checksum_address(sender) if (sender, open_block_number) in self.unconfirmed_channels: raise InsufficientConfirmations( 'Insufficient confirmations for the channel ' '(sender=%s, open_block_number=%d)' % (sender, open_block_number)) try: c = self.channels[sender, open_block_number] except KeyError: raise NoOpenChannel('Channel does not exist or has been closed' '(sender=%s, open_block_number=%s)' % (sender, open_block_number)) if c.is_closed: raise NoOpenChannel('Channel closing has been requested already.') if not is_same_address( verify_balance_proof(self.receiver, open_block_number, balance, decode_hex(signature), self.channel_manager_contract.address), sender): raise InvalidBalanceProof( 'Recovered signer does not match the sender') return c
def test_verify_balance_proof_v0(channel_manager_address: str): sig = sign_balance_proof(SENDER_PRIVATE_KEY, RECEIVER_ADDR, 312524, 11, channel_manager_address) sig = sig[:-1] + bytes([sig[-1] % 27]) assert is_same_address( verify_balance_proof(RECEIVER_ADDR, 312524, 11, sig, channel_manager_address), SENDER_ADDR)
def on_invalid_amount(self, method: str, url: str, response: Response, **kwargs) -> bool: log.debug('Server claims an invalid amount sent.') balance_sig = response.headers.get(HTTPHeaders.BALANCE_SIGNATURE) if balance_sig: balance_sig = decode_hex(balance_sig) last_balance = int(response.headers.get(HTTPHeaders.SENDER_BALANCE)) verified = balance_sig and is_same_address( verify_balance_proof(self.channel.receiver, self.channel.block, last_balance, balance_sig, self.client.context.channel_manager.address), self.channel.sender) if verified: if last_balance == self.channel.balance: log.error( 'Server tried to disguise the last unconfirmed payment as a confirmed payment.' ) return False else: log.debug( 'Server provided proof for a different channel balance ({}). Adopting.' .format(last_balance)) self.channel.update_balance(last_balance) else: log.debug( 'Server did not provide proof for a different channel balance. Reverting to 0.' ) self.channel.update_balance(0) return self.on_payment_requested(method, url, response, **kwargs)
def test_verify_balance_proof(channel_manager_address: str): sig = sign_balance_proof( SENDER_PRIVATE_KEY, RECEIVER_ADDR, 315123, 8, channel_manager_address ) assert is_same_address(verify_balance_proof( RECEIVER_ADDR, 315123, 8, sig, channel_manager_address ), SENDER_ADDR)
def test_verify_balance_proof_v27(channel_manager_address: str): # Should be default but test anyway. sig = sign_balance_proof(SENDER_PRIVATE_KEY, RECEIVER_ADDR, 312524, 11, channel_manager_address) sig = sig[:-1] + b'\x1b' assert verify_balance_proof(RECEIVER_ADDR, 312524, 11, sig, channel_manager_address) == SENDER_ADDR
def verify_balance_proof(self, sender, open_block_number, balance, signature): """Verify that a balance proof is valid and return the sender. This method just verifies if the balance proof is valid - no state update is performed. :returns: Channel, if it exists """ assert is_checksum_address(sender) if (sender, open_block_number) in self.unconfirmed_channels: raise InsufficientConfirmations( 'Insufficient confirmations for the channel ' '(sender=%s, open_block_number=%d)' % (sender, open_block_number)) try: c = self.channels[sender, open_block_number] except KeyError: raise NoOpenChannel('Channel does not exist or has been closed' '(sender=%s, open_block_number=%s)' % (sender, open_block_number)) if c.is_closed: raise NoOpenChannel('Channel closing has been requested already.') if not is_same_address( verify_balance_proof( self.receiver, open_block_number, balance, decode_hex(signature), self.channel_manager_contract.address ), sender ): raise InvalidBalanceProof('Recovered signer does not match the sender') return c
def test_verify_balance_proof(channel_manager_address: str): sig = sign_balance_proof( SENDER_PRIVATE_KEY, RECEIVER_ADDR, 315123, 8, channel_manager_address ) assert verify_balance_proof( RECEIVER_ADDR, 315123, 8, sig, channel_manager_address ) == SENDER_ADDR
def test_verify_balance_proof_v27(channel_manager_address: str): # Should be default but test anyway. sig = sign_balance_proof(SENDER_PRIVATE_KEY, RECEIVER_ADDR, 312524, 11, channel_manager_address) sig = sig[:-1] + bytes([sig[-1] % 27 + 27]) assert is_same_address( verify_balance_proof(RECEIVER_ADDR, 312524, 11, sig, channel_manager_address), SENDER_ADDR)
def test_verify_balance_proof_v0(channel_manager_address: str): sig = sign_balance_proof( SENDER_PRIVATE_KEY, RECEIVER_ADDR, 312524, 11, channel_manager_address ) sig = sig[:-1] + bytes([sig[-1] % 27]) assert is_same_address(verify_balance_proof( RECEIVER_ADDR, 312524, 11, sig, channel_manager_address ), SENDER_ADDR)
def test_verify_balance_proof_v0(channel_manager_address: str): sig = sign_balance_proof( SENDER_PRIVATE_KEY, RECEIVER_ADDR, 312524, 11, channel_manager_address ) sig = sig[:-1] + b'\x00' assert verify_balance_proof( RECEIVER_ADDR, 312524, 11, sig, channel_manager_address ) == SENDER_ADDR
def test_verify_balance_proof_v27(channel_manager_address: str): # Should be default but test anyway. sig = sign_balance_proof( SENDER_PRIVATE_KEY, RECEIVER_ADDR, 312524, 11, channel_manager_address ) sig = sig[:-1] + bytes([sig[-1] % 27 + 27]) assert is_same_address(verify_balance_proof( RECEIVER_ADDR, 312524, 11, sig, channel_manager_address ), SENDER_ADDR)
def on_invalid_amount( self, method: str, url: str, response: Response, **kwargs ) -> bool: log.debug('Server claims an invalid amount sent.') balance_sig = response.headers.get(HTTPHeaders.BALANCE_SIGNATURE) if balance_sig: balance_sig = decode_hex(balance_sig) last_balance = int(response.headers.get(HTTPHeaders.SENDER_BALANCE)) verified = balance_sig and is_same_address( verify_balance_proof( self.channel.receiver, self.channel.block, last_balance, balance_sig, self.client.context.channel_manager.address ), self.channel.sender ) if verified: if last_balance == self.channel.balance: log.error( 'Server tried to disguise the last unconfirmed payment as a confirmed payment.' ) return False else: log.debug( 'Server provided proof for a different channel balance ({}). Adopting.'.format( last_balance ) ) self.channel.update_balance(last_balance) else: log.debug( 'Server did not provide proof for a different channel balance. Reverting to 0.' ) self.channel.update_balance(0) return self.on_payment_requested(method, url, response, **kwargs)