def is_valid_batch(batch): # validate batch signature header = BatchHeader() header.ParseFromString(batch.header) context = create_context('secp256k1') public_key = Secp256k1PublicKey.from_hex(header.signer_public_key) if not context.verify(batch.header_signature, batch.header, public_key): LOGGER.debug("batch failed signature validation: %s", batch.header_signature) return False # validate all transactions in batch for txn in batch.transactions: if not is_valid_transaction(txn): return False txn_header = TransactionHeader() txn_header.ParseFromString(txn.header) if txn_header.batcher_public_key != header.signer_public_key: LOGGER.debug( "txn batcher public_key does not match signer" "public_key for batch: %s txn: %s", batch.header_signature, txn.header_signature) return False return True
def is_valid_batch(batch): # validate batch signature header = BatchHeader() header.ParseFromString(batch.header) if not signing.verify(batch.header, batch.header_signature, header.signer_public_key): LOGGER.debug("batch failed signature validation: %s", batch.header_signature) return False # validate all transactions in batch for txn in batch.transactions: if not is_valid_transaction(txn): return False txn_header = TransactionHeader() txn_header.ParseFromString(txn.header) if txn_header.batcher_public_key != header.signer_public_key: LOGGER.debug( "txn batcher public_key does not match signer" "public_key for batch: %s txn: %s", batch.header_signature, txn.header_signature) return False return True
def validate_batch(batch): # validate batch signature header = BatchHeader() header.ParseFromString(batch.header) valid = signing.verify(batch.header, batch.header_signature, header.signer_pubkey) if not valid: LOGGER.debug("batch failed signature validation: %s", batch.header_signature) # validate all transactions in batch total = len(batch.transactions) index = 0 while valid and index < total: txn = batch.transactions[index] valid = validate_transaction(txn) if valid: txn_header = TransactionHeader() txn_header.ParseFromString(txn.header) if txn_header.batcher_pubkey != header.signer_pubkey: LOGGER.debug( "txn batcher pubkey does not match signer" "pubkey for batch: %s txn: %s", batch.header_signature, txn.header_signature) valid = False index += 1 return valid
def is_batch_signer_authorized(self, batch, state_root=None, from_state=False): """ Check the batch signing key against the allowed transactor permissions. The roles being checked are the following, from first to last: "transactor.batch_signer" "transactor" "default" The first role that is set will be the one used to enforce if the batch signer is allowed. Args: batch (Batch): The batch that is being verified. state_root(string): The state root of the previous block. If this is None, the current state root hash will be retrieved. from_state (bool): Whether the identity value should be read directly from state, instead of using the cached values. This should be used when the state_root passed is not from the current chain head. """ if state_root is None: state_root = self._current_root_func() LOGGER.debug("authorized Chain head is %s.", state_root) if state_root == INIT_ROOT_KEY: LOGGER.debug("Chain head is not set yet. Permit all.") return True self._cache.update_view(state_root) header = BatchHeader() header.ParseFromString(batch.header) role = self._cache.get_role("transactor.batch_signer", state_root, from_state) if role is None: role = self._cache.get_role("transactor", state_root, from_state) if role is None: policy_name = "default" else: policy_name = role.policy_name policy = self._cache.get_policy(policy_name, state_root, from_state) if policy is None: allowed = True else: allowed = self._allowed(header.signer_public_key, policy) if allowed: return self.is_transaction_signer_authorized( batch.transactions, state_root, from_state) LOGGER.debug("Batch Signer: %s is not permitted.", header.signer_public_key) return False
def is_valid_batch(batch): # batch structure verification header = BatchHeader() header.ParseFromString(batch.header) # check whether a batch has duplicate transactions if len(header.transaction_ids) != len(set(header.transaction_ids)): LOGGER.debug("Batch has duplicate transactions. Dropping batch: %s", batch.header_signature) return False # validate the transaction_ids field in batch header contains a list of # transaction header_signatures and must be the same order as the # transactions field if len(batch.transactions) > len(header.transaction_ids): LOGGER.debug("Batch has extra transactions. Dropping batch: %s", batch.header_signature) return False if len(batch.transactions) < len(header.transaction_ids): LOGGER.debug("Batch lacks transactions. Dropping batch: %s", batch.header_signature) return False for header_txn_id, txn in zip(header.transaction_ids, batch.transactions): if header_txn_id != txn.header_signature: LOGGER.debug( "The header.transaction_ids does not match the " "order of transactions in the batch: %s txn: %s", batch.header_signature, header_txn_id) return False return True
def handle(self, connection_id, message_content): batch_header = BatchHeader() for batch in message_content.batches: batch_header.ParseFromString(batch.header) if batch_header.signer_public_key == self._whitelist_public_key: # There is a whitelisted batch, so allow it to continue return HandlerResult(status=HandlerStatus.PASS) batch_header.Clear() if self._is_batch_pool_full(): if not self._applying_backpressure: self._applying_backpressure = True LOGGER.info( 'Applying back pressure on client submitted batches') self._batches_rejected_count.inc() self._batches_rejected_gauge.set_value( self._batches_rejected_gauge.get_value() + 1) response = ClientBatchSubmitResponse( status=ClientBatchSubmitResponse.QUEUE_FULL) return HandlerResult( status=HandlerStatus.RETURN, message_out=response, message_type=Message.CLIENT_BATCH_SUBMIT_RESPONSE ) if self._applying_backpressure: self._applying_backpressure = False self._batches_rejected_gauge.set_value(0) LOGGER.info('Ending back pressure on client submitted batches') return HandlerResult(status=HandlerStatus.PASS)
def is_batch_signer_authorized(batch, allowed_pubkeys): header = BatchHeader() header.ParseFromString(batch.header) if header.signer_pubkey not in allowed_pubkeys: LOGGER.info("Batch was signed by an unauthorized signing key %s", header.signer_pubkey) return False return True
def is_batch_signer_authorized(self, batch, state_root=None): """ Check the batch signing key against the allowed transactor permissions. The roles being checked are the following, from first to last: "transactor.batch_signer" "transactor" "default" The first role that is set will be the one used to enforce if the batch signer is allowed. Args: batch (Batch): The batch that is being verified. state_root(string): The state root of the previous block. If this is None, the current state root hash will be retrieved. """ if state_root is None: state_root = self._current_root_func() if state_root == INIT_ROOT_KEY: LOGGER.debug("Chain head is not set yet. Permit all.") return True identity_view = \ self._identity_view_factory.create_identity_view(state_root) header = BatchHeader() header.ParseFromString(batch.header) role = \ identity_view.get_role("transactor.batch_signer") if role is None: role = identity_view.get_role("transactor") if role is None: policy_name = "default" else: policy_name = role.policy_name policy = identity_view.get_policy(policy_name) if policy is None: allowed = True else: allowed = self._allowed(header.signer_pubkey, policy) if allowed: return self.is_transaction_signer_authorized( batch.transactions, identity_view) LOGGER.debug("Batch Signer: %s is not permitted.", header.signer_pubkey) return False
def get_batch_by_transaction(self, transaction_id): """ Check to see if the requested transaction_id is in the current chain. If so, find the batch that has the transaction referenced by the transaction_id and return the batch. This is done by finding the block and searching for the batch. :param transaction_id (string): The id of the transaction that is being requested. :return: The batch that has the transaction. """ block = self.get_block_by_transaction_id(transaction_id) # Find batch in block for batch in block.batches: batch_header = BatchHeader() batch_header.ParseFromString(batch.header) if transaction_id in batch_header.transaction_ids: return batch
def validate_batch(batch): # validate batch signature header = BatchHeader() header.ParseFromString(batch.header) valid = signing.verify(batch.header, batch.header_signature, header.signer_pubkey) # validate all transactions in batch total = len(batch.transactions) index = 0 while valid and index < total: txn = batch.transactions[index] valid = validate_transaction(txn) if valid: txn_header = TransactionHeader() txn_header.ParseFromString(txn.header) if txn_header.batcher_pubkey != header.signer_pubkey: valid = False index += 1 return valid
def check_off_chain_batch_roles(self, batch): """ Check the batch signing key against the allowed off-chain transactor permissions. The roles being checked are the following, from first to last: "transactor.batch_signer" "transactor" The first role that is set will be the one used to enforce if the batch signer is allowed. Args: batch (Batch): The batch that is being verified. state_root(string): The state root of the previous block. If this is None, the current state root hash will be retrieved. """ if self._permissions is None: return True header = BatchHeader() header.ParseFromString(batch.header) policy = None if "transactor.batch_signer" in self._permissions: policy = self._permissions["transactor.batch_signer"] elif "transactor" in self._permissions: policy = self._permissions["transactor"] allowed = True if policy is not None: allowed = self._allowed(header.signer_public_key, policy) if allowed: return self.check_off_chain_transaction_roles(batch.transactions) LOGGER.debug( "Batch Signer: %s is not permitted by local" " configuration.", header.signer_public_key) return False
def is_batch_signer_authorized(self, batch, state_root=None): """ Check the batch signing key against the allowed transactor permissions. The roles being checked are the following, from first to last: "transactor.batch_signer" "transactor" "default" The first role that is set will be the one used to enforce if the batch signer is allowed. Args: batch (Batch): The batch that is being verified. state_root(string): The state root of the previous block; if this is specified, do not read cached values. If this is None, the current state root hash and cached values will be used. """ if state_root is None: state_root_func = self._current_root_func from_state = False if not self._chain_head_set: if self._current_root_func() == INIT_ROOT_KEY: if not self._log_guard.chain_head_not_yet_set: LOGGER.debug("Chain head is not set yet. Permit all.") self._log_guard.chain_head_not_yet_set = True return True self._chain_head_set = True else: def state_root_func(): return state_root from_state = True self._cache.update_view(state_root_func()) header = BatchHeader() header.ParseFromString(batch.header) role = self._cache.get_role("transactor.batch_signer", state_root_func, from_state) if role is None: role = self._cache.get_role("transactor", state_root_func, from_state) if role is None: policy_name = "default" else: policy_name = role.policy_name policy = self._cache.get_policy(policy_name, state_root_func, from_state) if policy is None: allowed = True else: allowed = self._allowed(header.signer_public_key, policy) if allowed: return self.is_transaction_signer_authorized( batch.transactions, state_root_func, from_state) LOGGER.debug("Batch Signer: %s is not permitted.", header.signer_public_key) return False