def propose_remove_role_admins( txn_key, batch_key, proposal_id, role_id, user_id, reason, metadata ): propose = role_transaction_pb2.ProposeRemoveRoleAdmin( proposal_id=proposal_id, role_id=role_id, user_id=user_id, reason=reason, metadata=metadata, ) inputs = [ addresser.make_user_address(user_id=user_id), addresser.make_proposal_address(role_id, user_id), addresser.make_role_admins_address(role_id, user_id), addresser.make_role_attributes_address(role_id=role_id), ] outputs = [addresser.make_proposal_address(role_id, user_id)] rbac_payload = rbac_payload_pb2.RBACPayload( content=propose.SerializeToString(), message_type=rbac_payload_pb2.RBACPayload.PROPOSE_REMOVE_ROLE_ADMINS, ) return make_header_and_batch(rbac_payload, inputs, outputs, txn_key, batch_key)
def create_task(txn_key, batch_key, task_id, task_name, admins, owners, metadata): create_payload = task_transaction_pb2.CreateTask(task_id=task_id, name=task_name) create_payload.admins.extend(admins) inputs = [ addresser.make_task_attributes_address(task_id=task_id), addresser.make_sysadmin_members_address(txn_key.public_key), ] inputs.extend([addresser.make_user_address(user_id=u) for u in admins]) inputs.extend([addresser.make_task_admins_address(task_id, u) for u in admins]) outputs = [addresser.make_task_attributes_address(task_id=task_id)] outputs.extend([addresser.make_task_admins_address(task_id, u) for u in admins]) if owners: create_payload.owners.extend(owners) inputs.extend([addresser.make_user_address(user_id=u) for u in owners]) inputs.extend([addresser.make_task_owners_address(task_id, u) for u in owners]) outputs.extend([addresser.make_task_owners_address(task_id, u) for u in owners]) rbac_payload = rbac_payload_pb2.RBACPayload( content=create_payload.SerializeToString(), message_type=rbac_payload_pb2.RBACPayload.CREATE_TASK, ) return make_header_and_batch(rbac_payload, inputs, outputs, txn_key, batch_key)
def propose_remove_task_owners( txn_key, batch_key, proposal_id, task_id, user_id, reason, metadata ): propose = task_transaction_pb2.ProposeRemoveTaskOwner( proposal_id=proposal_id, task_id=task_id, user_id=user_id, reason=reason, metadata=metadata, ) inputs = [ addresser.make_user_address(user_id), addresser.make_task_owners_address(task_id=task_id, user_id=user_id), addresser.make_proposal_address(task_id, user_id), addresser.make_task_attributes_address(task_id), ] outputs = [addresser.make_proposal_address(task_id, user_id)] rbac_payload = rbac_payload_pb2.RBACPayload( content=propose.SerializeToString(), message_type=rbac_payload_pb2.RBACPayload.PROPOSE_REMOVE_TASK_OWNERS, ) return make_header_and_batch(rbac_payload, inputs, outputs, txn_key, batch_key)
def propose_add_task_admins( txn_key, batch_key, proposal_id, task_id, user_id, reason, metadata ): propose_payload = task_transaction_pb2.ProposeAddTaskAdmin( proposal_id=proposal_id, task_id=task_id, user_id=user_id, reason=reason, metadata=metadata, ) inputs = [ addresser.make_user_address(user_id), addresser.make_task_admins_address(task_id=task_id, user_id=user_id), addresser.make_proposal_address(task_id, user_id), addresser.make_task_attributes_address(task_id), ] outputs = [addresser.make_proposal_address(task_id, user_id)] rbac_payload = rbac_payload_pb2.RBACPayload( content=propose_payload.SerializeToString(), message_type=rbac_payload_pb2.RBACPayload.PROPOSE_ADD_TASK_ADMINS, ) return make_header_and_batch(rbac_payload, inputs, outputs, txn_key, batch_key)
def propose_add_role_tasks( txn_key, batch_key, proposal_id, role_id, task_id, reason, metadata ): propose_payload = role_transaction_pb2.ProposeAddRoleTask( proposal_id=proposal_id, role_id=role_id, task_id=task_id, reason=reason, metadata=metadata, ) inputs = [ addresser.make_proposal_address(role_id, task_id), addresser.make_role_tasks_address(role_id, task_id), addresser.make_role_owners_address(role_id, txn_key.public_key), addresser.make_role_attributes_address(role_id), addresser.make_task_attributes_address(task_id), ] outputs = [addresser.make_proposal_address(role_id, task_id)] rbac_payload = rbac_payload_pb2.RBACPayload( content=propose_payload.SerializeToString(), message_type=rbac_payload_pb2.RBACPayload.PROPOSE_ADD_ROLE_TASKS, ) return make_header_and_batch(rbac_payload, inputs, outputs, txn_key, batch_key)
def create_role(txn_key, batch_key, role_name, role_id, metadata, admins, owners): """Create a BatchList with a CreateRole transaction in it. Args: txn_key (Key): The transaction signer's key pair. batch_key (Key): The batch signer's key pair. role_name (str): The name of the Role. role_id (str): A uuid that identifies this Role. metadata (str): Client supplied information that is not parsed. admins (list): A list of User ids of the Users who are admins of this Role. owners (list): A list of User ids of the Users who are owners of this Role. Returns: tuple BatchList, batch header_signature tuple """ create_role_payload = role_transaction_pb2.CreateRole( role_id=role_id, name=role_name, metadata=metadata, admins=admins, owners=owners ) inputs = [ addresser.make_sysadmin_members_address(txn_key.public_key), addresser.make_role_attributes_address(role_id), ] inputs.extend([addresser.make_user_address(u) for u in admins]) inputs.extend([addresser.make_user_address(u) for u in owners]) inputs.extend( [addresser.make_role_admins_address(role_id=role_id, user_id=a) for a in admins] ) inputs.extend( [addresser.make_role_owners_address(role_id=role_id, user_id=o) for o in owners] ) outputs = [addresser.make_role_attributes_address(role_id)] outputs.extend( [addresser.make_role_admins_address(role_id=role_id, user_id=a) for a in admins] ) outputs.extend( [addresser.make_role_owners_address(role_id=role_id, user_id=o) for o in owners] ) rbac_payload = rbac_payload_pb2.RBACPayload( content=create_role_payload.SerializeToString(), message_type=rbac_payload_pb2.RBACPayload.CREATE_ROLE, ) return make_header_and_batch(rbac_payload, inputs, outputs, txn_key, batch_key)
def propose_manager(txn_key, batch_key, proposal_id, user_id, new_manager_id, reason, metadata): """Create a BatchList with a ProposeUpdateUserManager transaction in it. Args: txn_key (Key): The transaction signer public/private key pair batch_key (Key): The batch signer public/private key pair proposal_id (str): The id of the proposal supplied by the rest api. user_id (str): The User id of the user whose manager will be updated. new_manager_id (str): The new manager's id. reason (str): The reason for this update. metadata (str): Client supplied metadata. Returns: tuple BatchList, batch header_signature tuple """ propose_update_payload = user_transaction_pb2.ProposeUpdateUserManager( proposal_id=proposal_id, user_id=user_id, new_manager_id=new_manager_id, reason=reason, metadata=metadata, ) inputs = [ addresser.make_user_address(user_id=user_id), addresser.make_user_address(user_id=new_manager_id), addresser.make_proposal_address(object_id=user_id, related_id=new_manager_id), ] outputs = [ addresser.make_proposal_address(object_id=user_id, related_id=new_manager_id) ] rbac_payload = rbac_payload_pb2.RBACPayload( content=propose_update_payload.SerializeToString(), message_type=rbac_payload_pb2.RBACPayload.PROPOSE_UPDATE_USER_MANAGER, ) return make_header_and_batch(rbac_payload, inputs, outputs, txn_key, batch_key)
def reject_manager(txn_key, batch_key, proposal_id, reason, user_id, manager_id): """Create a BatchList with a RejectUpdateUserManager in it. Args: txn_key (Key): The public/private key pair for signing the txn. batch_key (Key): The public/private key pair for signing the batch. proposal_id (str): The identifier of the proposal. reason (str): The client supplied reason for rejecting the proposal. user_id (str): The user's public key. manager_id (str): The manager's public key. Returns: tuple BatchList, signature tuple """ reject_update_payload = user_transaction_pb2.RejectUpdateUserManager( proposal_id=proposal_id, user_id=user_id, manager_id=manager_id, reason=reason) inputs = [ addresser.make_proposal_address(object_id=user_id, related_id=manager_id) ] outputs = [ addresser.make_proposal_address(object_id=user_id, related_id=manager_id) ] rbac_payload = rbac_payload_pb2.RBACPayload( content=reject_update_payload.SerializeToString(), message_type=rbac_payload_pb2.RBACPayload.REJECT_UPDATE_USER_MANAGER, ) return make_header_and_batch( rbac_payload=rbac_payload, inputs=inputs, outputs=outputs, txn_key=txn_key, batch_key=batch_key, )
def reject_add_task_owners(txn_key, batch_key, proposal_id, task_id, user_id, reason): reject = task_transaction_pb2.RejectAddTaskOwner( proposal_id=proposal_id, task_id=task_id, user_id=user_id, reason=reason ) inputs = [ addresser.make_proposal_address(task_id, user_id), addresser.make_task_admins_address(task_id, txn_key.public_key), ] outputs = [addresser.make_proposal_address(task_id, user_id)] rbac_payload = rbac_payload_pb2.RBACPayload( content=reject.SerializeToString(), message_type=rbac_payload_pb2.RBACPayload.REJECT_ADD_TASK_OWNERS, ) return make_header_and_batch(rbac_payload, inputs, outputs, txn_key, batch_key)
def reject_add_role_members(txn_key, batch_key, proposal_id, role_id, user_id, reason): reject_payload = role_transaction_pb2.RejectAddRoleMember( proposal_id=proposal_id, role_id=role_id, user_id=user_id, reason=reason ) inputs = [ addresser.make_proposal_address(role_id, user_id), addresser.make_role_owners_address(role_id, txn_key.public_key), ] outputs = [addresser.make_proposal_address(role_id, user_id)] rbac_payload = rbac_payload_pb2.RBACPayload( content=reject_payload.SerializeToString(), message_type=rbac_payload_pb2.RBACPayload.REJECT_ADD_ROLE_MEMBERS, ) return make_header_and_batch(rbac_payload, inputs, outputs, txn_key, batch_key)
def reject_remove_role_tasks(txn_key, batch_key, proposal_id, role_id, task_id, reason): reject_payload = role_transaction_pb2.RejectRemoveRoleTask( proposal_id=proposal_id, role_id=role_id, task_id=task_id, reason=reason ) inputs = [ addresser.make_proposal_address(role_id, task_id), addresser.make_task_owners_address(task_id, txn_key.public_key), ] outputs = [addresser.make_proposal_address(role_id, task_id)] rbac_payload = rbac_payload_pb2.RBACPayload( content=reject_payload.SerializeToString(), message_type=rbac_payload_pb2.RBACPayload.REJECT_REMOVE_ROLE_TASKS, ) return make_header_and_batch(rbac_payload, inputs, outputs, txn_key, batch_key)
def reject_add_role_admins(txn_key, batch_key, proposal_id, role_id, user_id, reason): reject_add_payload = role_transaction_pb2.RejectAddRoleAdmin( proposal_id=proposal_id, role_id=role_id, user_id=user_id, reason=reason ) inputs = [ addresser.make_role_admins_address(role_id=role_id, user_id=txn_key.public_key) ] inputs.append(addresser.make_proposal_address(role_id, user_id)) outputs = [addresser.make_proposal_address(role_id, user_id)] rbac_payload = rbac_payload_pb2.RBACPayload( content=reject_add_payload.SerializeToString(), message_type=rbac_payload_pb2.RBACPayload.REJECT_ADD_ROLE_ADMINS, ) return make_header_and_batch(rbac_payload, inputs, outputs, txn_key, batch_key)
def create_user(txn_key, batch_key, name, user_name, user_id, metadata, manager_id=None): """Create a BatchList with a CreateUser RBAC transaction. Args: txn_key (Key): The transaction signer's public/private key pair. batch_key (Key): The batch signer's public/private key pair. user_name (str): The user name of the User. user_id (str): The User's public key. metadata (str): Client supplied metadata. manager_id (str): The optional id of the manager of this User. Returns: tuple The CreateUser BatchList as the zeroth element and the batch header_signature as the first element. """ create_user_payload = user_transaction_pb2.CreateUser(name=name, user_name=user_name, user_id=user_id, metadata=metadata) inputs = [addresser.make_user_address(user_id=user_id)] outputs = [addresser.make_user_address(user_id=user_id)] if manager_id: create_user_payload.manager_id = manager_id inputs.append(addresser.make_user_address(user_id=manager_id)) outputs.append(addresser.make_user_address(user_id=manager_id)) rbac_payload = rbac_payload_pb2.RBACPayload( content=create_user_payload.SerializeToString(), message_type=rbac_payload_pb2.RBACPayload.CREATE_USER, ) return make_header_and_batch(rbac_payload, inputs, outputs, txn_key, batch_key)
def propose_add_role_admins( txn_key, batch_key, proposal_id, role_id, user_id, reason, metadata ): """Create a BatchList with a ProposeAddRoleAdmins transaction in it. Args: txn_key (Key): The txn signer key pair. batch_key (Key): The batch signer key pair. role_id (str): The role's id. user_id (str): The user that is being proposed to be an admin. reason (str): The client supplied reason for the proposal. metadata (str): The client supplied metadata. Returns: tuple BatchList, batch header_signature tuple """ propose_add_payload = role_transaction_pb2.ProposeAddRoleAdmin( proposal_id=proposal_id, role_id=role_id, user_id=user_id, reason=reason, metadata=metadata, ) inputs = [ addresser.make_user_address(user_id=user_id), addresser.make_proposal_address(role_id, user_id), addresser.make_role_admins_address(role_id, user_id), addresser.make_role_attributes_address(role_id=role_id), ] outputs = [addresser.make_proposal_address(role_id, user_id)] rbac_payload = rbac_payload_pb2.RBACPayload( content=propose_add_payload.SerializeToString(), message_type=rbac_payload_pb2.RBACPayload.PROPOSE_ADD_ROLE_ADMINS, ) return make_header_and_batch(rbac_payload, inputs, outputs, txn_key, batch_key)
def confirm_add_task_admins(txn_key, batch_key, proposal_id, task_id, user_id, reason): confirm_payload = task_transaction_pb2.ConfirmAddTaskAdmin( proposal_id=proposal_id, task_id=task_id, user_id=user_id, reason=reason ) inputs = [ addresser.make_task_admins_address(task_id, txn_key.public_key), addresser.make_proposal_address(task_id, user_id), ] outputs = [ addresser.make_proposal_address(task_id, user_id), addresser.make_task_admins_address(task_id, user_id), ] rbac_payload = rbac_payload_pb2.RBACPayload( content=confirm_payload.SerializeToString(), message_type=rbac_payload_pb2.RBACPayload.CONFIRM_ADD_TASK_ADMINS, ) return make_header_and_batch(rbac_payload, inputs, outputs, txn_key, batch_key)
def confirm_add_role_tasks(txn_key, batch_key, proposal_id, role_id, task_id, reason): confirm_payload = role_transaction_pb2.ConfirmAddRoleTask( proposal_id=proposal_id, role_id=role_id, task_id=task_id, reason=reason ) inputs = [ addresser.make_proposal_address(role_id, task_id), addresser.make_task_owners_address(task_id, txn_key.public_key), ] outputs = [ addresser.make_proposal_address(role_id, task_id), addresser.make_role_tasks_address(role_id, task_id), ] rbac_payload = rbac_payload_pb2.RBACPayload( content=confirm_payload.SerializeToString(), message_type=rbac_payload_pb2.RBACPayload.CONFIRM_ADD_ROLE_TASKS, ) return make_header_and_batch(rbac_payload, inputs, outputs, txn_key, batch_key)
def confirm_manager(txn_key, batch_key, proposal_id, user_id, manager_id, reason): """Create a BatchList with a ConfirmUpdateUserManager transaction in it. Args: txn_key (Key): The transaction signer public/private key pair. batch_key (Key): The batch signer public/private key pair. proposal_id (str): The identifier of the proposal. reason (str): The client supplied reason for the confirmation. Returns: tuple BatchList, batch header_signature tuple """ confirm_update_payload = user_transaction_pb2.ConfirmUpdateUserManager( proposal_id=proposal_id, user_id=user_id, manager_id=manager_id, reason=reason) inputs = [ addresser.make_proposal_address(user_id, manager_id), addresser.make_user_address(user_id), ] outputs = [ addresser.make_proposal_address(user_id, manager_id), addresser.make_user_address(user_id), ] rbac_payload = rbac_payload_pb2.RBACPayload( content=confirm_update_payload.SerializeToString(), message_type=rbac_payload_pb2.RBACPayload.CONFIRM_UPDATE_USER_MANAGER, ) return make_header_and_batch(rbac_payload, inputs, outputs, txn_key, batch_key)
def propose_add_role_members( txn_key, batch_key, proposal_id, role_id, user_id, reason, metadata ): propose_payload = role_transaction_pb2.ProposeAddRoleMember( proposal_id=proposal_id, role_id=role_id, user_id=user_id, reason=reason ) inputs = [ addresser.make_role_members_address(role_id, user_id), addresser.make_role_attributes_address(role_id=role_id), addresser.make_user_address(user_id=user_id), addresser.make_proposal_address(role_id, user_id), ] outputs = [addresser.make_proposal_address(role_id, user_id)] rbac_payload = rbac_payload_pb2.RBACPayload( content=propose_payload.SerializeToString(), message_type=rbac_payload_pb2.RBACPayload.PROPOSE_ADD_ROLE_MEMBERS, ) return make_header_and_batch(rbac_payload, inputs, outputs, txn_key, batch_key)
def confirm_remove_task_owners( txn_key, batch_key, proposal_id, task_id, user_id, reason ): confirm = task_transaction_pb2.ConfirmRemoveTaskOwner( proposal_id=proposal_id, task_id=task_id, user_id=user_id, reason=reason ) inputs = [ addresser.make_proposal_address(task_id, user_id), addresser.make_task_owners_address(task_id, user_id), addresser.make_task_admins_address(task_id, txn_key.public_key), ] outputs = [ addresser.make_proposal_address(task_id, user_id), addresser.make_task_owners_address(task_id, user_id), ] rbac_payload = rbac_payload_pb2.RBACPayload( content=confirm.SerializeToString(), message_type=rbac_payload_pb2.RBACPayload.CONFIRM_REMOVE_TASK_OWNERS, ) return make_header_and_batch(rbac_payload, inputs, outputs, txn_key, batch_key)
def confirm_add_role_admins(txn_key, batch_key, proposal_id, role_id, user_id, reason): """Creates a BatchList with a ConfirmAddRoleAdmin transaction in it. Args: txn_key (Key): The txn signer key pair. batch_key (Key): The batch signer key pair. proposal_id (str): The proposal's identifier. role_id (str): The role's identifier. user_id (str): The user's signer public key. reason (str): The client supplied reason to confirm. Returns: tuple BatchList, batch header_signature tuple """ confirm_add_payload = role_transaction_pb2.ConfirmAddRoleAdmin( proposal_id=proposal_id, role_id=role_id, user_id=user_id, reason=reason ) inputs = [ addresser.make_role_admins_address(role_id=role_id, user_id=txn_key.public_key) ] inputs.append(addresser.make_proposal_address(role_id, user_id)) outputs = [ addresser.make_proposal_address(role_id, user_id), addresser.make_role_admins_address(role_id, user_id), ] rbac_payload = rbac_payload_pb2.RBACPayload( content=confirm_add_payload.SerializeToString(), message_type=rbac_payload_pb2.RBACPayload.CONFIRM_ADD_ROLE_ADMINS, ) return make_header_and_batch(rbac_payload, inputs, outputs, txn_key, batch_key)
def confirm_remove_role_admins( txn_key, batch_key, proposal_id, role_id, user_id, reason ): confirm_add_payload = role_transaction_pb2.ConfirmRemoveRoleAdmin( proposal_id=proposal_id, role_id=role_id, user_id=user_id, reason=reason ) inputs = [ addresser.make_role_admins_address(role_id=role_id, user_id=txn_key.public_key) ] inputs.append(addresser.make_proposal_address(role_id, user_id)) outputs = [ addresser.make_proposal_address(role_id, user_id), addresser.make_role_admins_address(role_id, user_id), ] rbac_payload = rbac_payload_pb2.RBACPayload( content=confirm_add_payload.SerializeToString(), message_type=rbac_payload_pb2.RBACPayload.CONFIRM_REMOVE_ROLE_ADMINS, ) return make_header_and_batch(rbac_payload, inputs, outputs, txn_key, batch_key)
def confirm_remove_role_members( txn_key, batch_key, proposal_id, role_id, user_id, reason ): confirm_payload = role_transaction_pb2.ConfirmRemoveRoleMember( proposal_id=proposal_id, role_id=role_id, user_id=user_id, reason=reason ) inputs = [ addresser.make_proposal_address(role_id, user_id), addresser.make_role_owners_address(role_id, txn_key.public_key), ] outputs = [ addresser.make_proposal_address(role_id, user_id), addresser.make_role_members_address(role_id, user_id), ] rbac_payload = rbac_payload_pb2.RBACPayload( content=confirm_payload.SerializeToString(), message_type=rbac_payload_pb2.RBACPayload.CONFIRM_REMOVE_ROLE_MEMBERS, ) return make_header_and_batch(rbac_payload, inputs, outputs, txn_key, batch_key)
def create_user_transaction(self, name, username, metadata): txn_private_key = Secp256k1PrivateKey.new_random() batch_private_key = Secp256k1PrivateKey.new_random() txn_key = Key(txn_private_key.as_hex()) batch_key = Key(batch_private_key.as_hex()) batchlist, sig = create_user( txn_key, batch_key, name, username, txn_key.public_key, metadata ) self.assertEqual(type(sig), str) self.assertEqual(type(batchlist), batch_pb2.BatchList) self.assertEqual(len(sig), SIGNATURE_LENGTH) self.assertTrue(SIGNATURE_PATTERN.match(sig)) batch_count = 0 for batch in batchlist.batches: batch_count += 1 self.assertEqual(type(batch), batch_pb2.Batch) self.assertEqual(type(batch.header_signature), str) self.assertEqual(len(batch.header_signature), SIGNATURE_LENGTH) self.assertTrue(SIGNATURE_PATTERN.match(batch.header_signature)) trans_count = 0 for transaction in batch.transactions: trans_count += 1 self.assertEqual(type(transaction.header), bytes) self.assertEqual(type(transaction.header_signature), str) self.assertEqual(type(transaction.payload), bytes) self.assertEqual(len(transaction.header_signature), SIGNATURE_LENGTH) self.assertTrue(SIGNATURE_PATTERN.match(transaction.header_signature)) header = transaction_pb2.TransactionHeader() header.ParseFromString(transaction.header) self.assertEqual(type(header), transaction_pb2.TransactionHeader) self.assertEqual(header.family_name, addresser.FAMILY_NAME) self.assertEqual(header.family_version, addresser.FAMILY_VERSION) self.assertEqual(header.batcher_public_key, batch_key.public_key) self.assertEqual(header.signer_public_key, txn_key.public_key) self.assertEqual(len(header.payload_sha512), SIGNATURE_LENGTH) self.assertTrue(SIGNATURE_PATTERN.match(header.payload_sha512)) input_count = 0 for address in header.inputs: input_count += 1 self.assertEqual(type(address), str) self.assertEqual(len(address), addresser.ADDRESS_LENGTH) self.assertTrue(addresser.is_address(address)) self.assertTrue(addresser.namespace_ok(address)) self.assertTrue(addresser.is_family_address(address)) self.assertEqual(addresser.address_is(address), AddressSpace.USER) self.assertEqual(input_count, 1) output_count = 0 for address in header.outputs: output_count += 1 self.assertEqual(type(address), str) self.assertEqual(len(address), addresser.ADDRESS_LENGTH) self.assertTrue(addresser.is_address(address)) self.assertTrue(addresser.namespace_ok(address)) self.assertTrue(addresser.is_family_address(address)) self.assertEqual(addresser.address_is(address), AddressSpace.USER) self.assertEqual(output_count, 1) payload = rbac_payload_pb2.RBACPayload() payload.ParseFromString(transaction.payload) self.assertEqual(type(payload), rbac_payload_pb2.RBACPayload) self.assertEqual( payload.message_type, rbac_payload_pb2.RBACPayload.CREATE_USER ) self.assertEqual(type(payload.content), bytes) user = user_transaction_pb2.CreateUser() user.ParseFromString(payload.content) self.assertEqual(type(user), user_transaction_pb2.CreateUser) self.assertEqual(user.name, name) self.assertEqual(user.user_name, username) self.assertEqual(type(user.user_id), str) self.assertEqual(user.user_id, txn_key.public_key) self.assertEqual(trans_count, 1) self.assertEqual(batch_count, 1)