def validate(self, blockchain): with validates(f'block number {self.message.block_number} (identifier: {self.message.block_identifier})'): validate_not_empty(f'{self.humanized_class_name} message', self.message) self.message.validate(blockchain) validate_exact_value(f'{self.humanized_class_name} hash', self.hash, self.message.get_hash()) with validates('block signature'): self.validate_signature()
def validate_timestamp(self, blockchain): timestamp = self.timestamp validate_not_none(f'{self.humanized_class_name} timestamp', timestamp) validate_type(f'{self.humanized_class_name} timestamp', timestamp, datetime) validate_is_none(f'{self.humanized_class_name} timestamp timezone', timestamp.tzinfo) block_number = self.block_number assert block_number is not None if block_number > 0: prev_block_number = block_number - 1 prev_block = blockchain.get_block_by_number(prev_block_number) if prev_block is None: logger.debug('Partial blockchain detected') blockchain_state = blockchain.get_closest_blockchain_state_snapshot( block_number) validate_not_none('Closest blockchain state', blockchain_state) if blockchain_state.is_initial(): raise ValidationError( 'Unexpected initial account root file found') validate_exact_value('Blockchain state last block number', blockchain_state.last_block_number, prev_block_number) assert blockchain_state.last_block_timestamp min_timestamp = blockchain_state.last_block_timestamp else: min_timestamp = prev_block.message.timestamp validate_gt_value(f'{self.humanized_class_name} timestamp', timestamp, min_timestamp)
def validate_block_identifier(self, blockchain): block_identifier = self.block_identifier validate_not_none(f'{self.humanized_class_name} block_identifier', block_identifier) validate_type(f'{self.humanized_class_name} block_identifier', block_identifier, str) block_number = self.block_number assert block_number is not None expected_identifier = blockchain.get_expected_block_identifier( block_number) validate_exact_value(f'{self.humanized_class_name} block_identifier', block_identifier, expected_identifier)
def validate_updated_account_balance_lock(self, *, account_number, account_state, is_sender=False): subject = ( f'{self.humanized_class_name_lowered} {"sender" if is_sender else "recipient"} account ' f'{account_number} balance_lock') balance_lock = account_state.balance_lock if is_sender: validate_not_empty(subject, balance_lock) validate_type(subject, balance_lock, str) from ..algorithms.updated_account_states.coin_transfer import make_balance_lock validate_exact_value(subject, balance_lock, make_balance_lock(self.signed_change_request)) else: validate_empty(subject, balance_lock)
def validate_updated_account_balance(self, *, account_number, account_state, blockchain, is_sender=False): subject = ( f'{self.humanized_class_name_lowered} {"sender" if is_sender else "recipient"} account ' f'{account_number}') balance = blockchain.get_account_balance(account_number, self.block_number - 1) if is_sender: validate_greater_than_zero( f'sender account {account_number} current balance', balance) expected_balance = balance - self.get_sent_amount() else: expected_balance = balance + self.get_recipient_amount( account_number) validate_exact_value(f'{subject} balance', account_state.balance, expected_balance)
def validate_balance_lock(self, blockchain, in_block_number: int): expected_lock = blockchain.get_account_balance_lock( self.signer, in_block_number - 1) validate_exact_value( f'{self.humanized_class_name} message balance_lock', self.message.balance_lock, expected_lock)