def test_transaction_order(self): """Tests the that transactions are returned in order added. Adds three batches with varying number of transactions, then tests that they are returned in the appropriate order when using an iterator. This test also creates a second iterator and verifies that both iterators return the same transactions. This test also finalizes the scheduler and verifies that StopIteration is thrown by the iterator. """ private_key = bitcoin.random_key() public_key = bitcoin.encode_pubkey( bitcoin.privkey_to_pubkey(private_key), "hex") context_manager = ContextManager(dict_database.DictDatabase()) squash_handler = context_manager.get_squash_handler() first_state_root = context_manager.get_first_root() scheduler = SerialScheduler(squash_handler, first_state_root) txns = [] for names in [['a', 'b', 'c'], ['d', 'e'], ['f', 'g', 'h', 'i']]: batch_txns = [] for name in names: txn = create_transaction( name=name, private_key=private_key, public_key=public_key) batch_txns.append(txn) txns.append(txn) batch = create_batch( transactions=batch_txns, private_key=private_key, public_key=public_key) scheduler.add_batch(batch) scheduler.finalize() iterable1 = iter(scheduler) iterable2 = iter(scheduler) for txn in txns: scheduled_txn_info = next(iterable1) self.assertEqual(scheduled_txn_info, next(iterable2)) self.assertIsNotNone(scheduled_txn_info) self.assertEquals(txn.payload, scheduled_txn_info.txn.payload) scheduler.set_status(txn.header_signature, False, None) with self.assertRaises(StopIteration): next(iterable1)
def test_valid_batch_invalid_batch(self): """Tests the squash function. That the correct hash is being used for each txn and that the batch ending state hash is being set. Basically: 1. Adds two batches, one where all the txns are valid, and one where one of the txns is invalid. 2. Run through the scheduler executor interaction as txns are processed. 3. Verify that the valid state root is obtained through the squash function. 4. Verify that correct batch statuses are set """ private_key = bitcoin.random_key() public_key = bitcoin.encode_pubkey( bitcoin.privkey_to_pubkey(private_key), "hex") context_manager = ContextManager(dict_database.DictDatabase()) squash_handler = context_manager.get_squash_handler() first_state_root = context_manager.get_first_root() scheduler = SerialScheduler(squash_handler, first_state_root) # 1) batch_signatures = [] for names in [['a', 'b'], ['invalid', 'c']]: batch_txns = [] for name in names: txn = create_transaction( name=name, private_key=private_key, public_key=public_key) batch_txns.append(txn) batch = create_batch( transactions=batch_txns, private_key=private_key, public_key=public_key) batch_signatures.append(batch.signature) scheduler.add_batch(batch) scheduler.finalize() # 2) sched1 = iter(scheduler) invalid_payload = hashlib.sha512('invalid'.encode()).hexdigest() while not scheduler.complete(): txn_info = next(sched1) txn_header = transaction_pb2.TransactionHeader() txn_header.ParseFromString(txn_info.txn.header) inputs_or_outputs = list(txn_header.inputs) c_id = context_manager.create_context(txn_info.state_hash, inputs_or_outputs, inputs_or_outputs) if txn_header.payload_sha512 == invalid_payload: scheduler.set_status(txn_info.txn.signature, False, c_id) else: context_manager.set(c_id, [{inputs_or_outputs[0]: 1}]) scheduler.set_status(txn_info.txn.signature, True, c_id) sched2 = iter(scheduler) # 3) txn_info_a = next(sched2) self.assertEquals(first_state_root, txn_info_a.state_hash) txn_a_header = transaction_pb2.TransactionHeader() txn_a_header.ParseFromString(txn_info_a.txn.header) inputs_or_outputs = list(txn_a_header.inputs) address_a = inputs_or_outputs[0] c_id_a = context_manager.create_context(first_state_root, inputs_or_outputs, inputs_or_outputs) context_manager.set(c_id_a, [{address_a: 1}]) state_root2 = context_manager.commit_context([c_id_a], virtual=False) txn_info_b = next(sched2) self.assertEquals(txn_info_b.state_hash, state_root2) txn_b_header = transaction_pb2.TransactionHeader() txn_b_header.ParseFromString(txn_info_b.txn.header) inputs_or_outputs = list(txn_b_header.inputs) address_b = inputs_or_outputs[0] c_id_b = context_manager.create_context(state_root2, inputs_or_outputs, inputs_or_outputs) context_manager.set(c_id_b, [{address_b: 1}]) state_root3 = context_manager.commit_context([c_id_b], virtual=False) txn_infoInvalid = next(sched2) self.assertEquals(txn_infoInvalid.state_hash, state_root3) txn_info_c = next(sched2) self.assertEquals(txn_info_c.state_hash, state_root3) # 4) batch1_status = scheduler.batch_status(batch_signatures[0]) self.assertTrue(batch1_status.valid) self.assertEquals(batch1_status.state_hash, state_root3) batch2_status = scheduler.batch_status(batch_signatures[1]) self.assertFalse(batch2_status.valid) self.assertIsNone(batch2_status.state_hash)