def register_payment(self, sender: str, open_block_number: int, balance: int, signature: str): """Register a payment. Method will try to reconstruct (verify) balance update data with a signature sent by the client. If verification is succesfull, an internal payment state is updated. Parameters: sender (str): sender of the balance proof open_block_number (int): block the channel was opened in balance (int): updated balance signature(str): balance proof to verify """ assert is_checksum_address(sender) c = self.verify_balance_proof(sender, open_block_number, balance, signature) if balance <= c.balance: raise InvalidBalanceAmount('The balance must not decrease.') if balance > c.deposit: raise InvalidBalanceProof( 'Balance must not be greater than deposit') received = balance - c.balance c.balance = balance c.last_signature = signature c.mtime = time.time() self.state.set_channel(c) self.log.debug( 'registered payment (sender %s, block number %s, new balance %s)', c.sender, open_block_number, balance) return c.sender, received
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 sign_close(self, sender: str, open_block_number: int, balance: int): """Sign an agreement for a channel closing. Returns: channel close signature (str): a signature that can be used client-side to close the channel by directly calling contract's close method on-chain. """ assert is_checksum_address(sender) if (sender, open_block_number) not in self.channels: raise NoOpenChannel('Channel does not exist or has been closed' '(sender=%s, open_block_number=%d)' % (sender, open_block_number)) c = self.channels[sender, open_block_number] if c.is_closed: raise NoOpenChannel('Channel closing has been requested already.') assert balance is not None if c.last_signature is None: raise NoBalanceProofReceived('Payment has not been registered.') if balance != c.balance: raise InvalidBalanceProof( 'Requested closing balance does not match latest one.') c.is_closed = True c.mtime = time.time() receiver_sig = sign_close(self.private_key, sender, open_block_number, c.balance, self.channel_manager_contract.address) self.state.set_channel(c) self.log.info( 'signed cooperative closing message (sender %s, block number %s)', sender, open_block_number) return receiver_sig
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 """ 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: print('NoOpenChannel key error') raise NoOpenChannel('Channel does not exist or has been closed' '(sender=%s, open_block_number=%s)' % (sender, open_block_number)) if c.is_closed: print('NoOpenChannel c.is_closed') raise NoOpenChannel('Channel closing has been requested already.') print('is_same_address', self.receiver, open_block_number, balance, decode_hex(signature), sender) if not is_same_address( verify_balance_proof(self.receiver, open_block_number, balance, decode_hex(signature)), sender): raise InvalidBalanceProof( 'Recovered signer does not match the sender') return c
def sign_close(self, sender, open_block_number, balance): """Sign an agreement for a channel closing.""" if (sender, open_block_number) not in self.channels: raise NoOpenChannel('Channel does not exist or has been closed' '(sender=%s, open_block_number=%d)' % (sender, open_block_number)) c = self.channels[sender, open_block_number] print('sign_close', c) if c.is_closed: raise NoOpenChannel('Channel closing has been requested already.') assert balance is not None # if c.last_signature is None:todo fix # raise NoBalanceProofReceived('Payment has not been registered.') if balance != c.balance: raise InvalidBalanceProof( 'Requested closing balance does not match latest one.') c.is_closed = True c.mtime = time.time() receiver_sig = sign_balance_proof(self.private_key, self.receiver, open_block_number, balance) self.state.store() self.log.info( 'signed cooperative closing message (sender %s, block number %s)', sender, open_block_number) return receiver_sig
def register_payment(self, sender, open_block_number, balance, signature): """Register a payment.""" c = self.verify_balance_proof(sender, open_block_number, balance, signature) if balance <= c.balance: raise InvalidBalanceAmount('The balance must increase.') if balance > c.deposit: raise InvalidBalanceProof('Balance must not be greater than deposit.') received = balance - c.balance c.balance = balance c.last_signature = signature c.mtime = time.time() self.state.store() self.log.debug('registered payment (sender %s, block number %s, new balance %s)', c.sender, open_block_number, balance) return (c.sender, received)