def test_create_wait_certificate_before_create_wait_timer(self): # Need to create signup information SignupInfo.create_signup_info( originator_public_key_hash=self._originator_public_key_hash, most_recent_wait_certificate_id=NullIdentifier) with self.assertRaises(WaitCertificateError): WaitCertificate.create_wait_certificate("Reader's Digest")
def test_create_wait_certificate_before_create_wait_timer(self): # Need to create signup information SignupInfo.create_signup_info( originator_public_key=self._originator_public_key, validator_network_basename="America's Most Watched Network", most_recent_wait_certificate_id=NullIdentifier) with self.assertRaises(WaitCertificateError): WaitCertificate.create_wait_certificate("Reader's Digest")
def __init__(self, gossip, kwargs, minimum_transactions_per_block=None, max_transactions_per_block=None, max_txn_age=None, genesis_ledger=None, restore=None, data_directory=None, store_type=None): """Constructor for the PoetJournal class. Args: node (Node): The local node. """ super(PoetJournal, self).__init__(gossip, minimum_transactions_per_block, max_transactions_per_block, max_txn_age, genesis_ledger, restore, data_directory, store_type) if 'PoetEnclaveImplementation' in kwargs: enclave_module = kwargs['PoetEnclaveImplementation'] else: enclave_module = 'journal.consensus.poet1.poet_enclave_simulator' \ '.poet_enclave_simulator' poet_enclave = importlib.import_module(enclave_module) poet_enclave.initialize(**kwargs) WaitCertificate.poet_enclave = poet_enclave WaitTimer.poet_enclave = poet_enclave SignupInfo.poet_enclave = poet_enclave # initialize the poet handlers poet_transaction_block.register_message_handlers(self) # initialize stats specifically for the block chain journal self.JournalStats.add_metric(stats.Value('LocalMeanTime', 0)) self.JournalStats.add_metric(stats.Value('AggregateLocalMean', '0')) self.JournalStats.add_metric(stats.Value('PopulationEstimate', '0')) self.JournalStats.add_metric(stats.Value('ExpectedExpirationTime', '0')) self.JournalStats.add_metric(stats.Value('Duration', '0')) # propagate the maximum blocks to keep self.MaximumBlocksToKeep = max(self.MaximumBlocksToKeep, WaitTimer.certificate_sample_length) # Check to see if there is any pre-existing sealed signup data stored # in the local store sealed_signup_data = self.LocalStore.get('sealed_signup_data') # If we haven't signed up, we need to do that first. SignupInfo.create_signup_info(self.gossip.LocalNode.public_key()) self.dispatcher.on_heartbeat += self._check_certificate
def test_register_validator_re_register(self): key = signed_object.generate_signing_key() validator_id = signed_object.generate_identifier(key) name = 'DasValidator' signup_info = \ SignupInfo.create_signup_info( originator_public_key=pybitcointools.privtopub(key), validator_network_basename='Intel Validator Network', most_recent_wait_certificate_id='0' * 16) store = KeyValueStore() transaction = \ ValidatorRegistryTransaction.register_validator( name, validator_id, signup_info) transaction.sign_object(key) try: transaction.check_valid(store) transaction.apply(store) except InvalidTransactionError as e: self.fail('Failed valid transaction: {}'.format(e)) try: # check if valid to register again transaction.check_valid(store) except InvalidTransactionError as e: self.fail('Failure: Double registered validator: {}'.format(e))
def test_wait_certificate_serialization(self): # Need to create signup information and wait timer first signup_info = \ SignupInfo.create_signup_info( originator_public_key_hash=self._originator_public_key_hash, most_recent_wait_certificate_id=NullIdentifier) wt = WaitTimer.create_wait_timer([]) # Now we can create a wait certificate and serialize wc = WaitCertificate.create_wait_certificate("Reader's Digest") dumped = wc.dump() self.assertIsNotNone(dumped.get('SerializedCertificate')) self.assertIsNotNone(dumped.get('Signature')) # Deserialize and verify that wait certificates are the same # and that deserialized one is valid wc_copy = \ WaitCertificate.wait_certificate_from_serialized( dumped.get('SerializedCertificate'), dumped.get('Signature'), signup_info.poet_public_key) self.assertEquals(wc.previous_certificate_id, wc_copy.previous_certificate_id) self.assertEqual(wc.local_mean, wc_copy.local_mean) self.assertEqual(wc.request_time, wc_copy.request_time) self.assertEqual(wc.duration, wc_copy.duration) self.assertEqual(wc.block_digest, wc_copy.block_digest) self.assertEqual(wc.signature, wc_copy.signature) self.assertEqual(wc.identifier, wc_copy.identifier) self.assertTrue(wc_copy.is_valid([], signup_info.poet_public_key))
def test_create_wait_certificate(self): # Need to create signup information and wait timer first signup_info = \ SignupInfo.create_signup_info( originator_public_key_hash=self._originator_public_key_hash, most_recent_wait_certificate_id=NullIdentifier) wt = WaitTimer.create_wait_timer([]) # Now we can create a wait certificate and verify that it correlates # to the wait timer we just created wc = WaitCertificate.create_wait_certificate("Reader's Digest") self.assertIsNotNone(wc) self.assertEquals(wc.previous_certificate_id, wt.previous_certificate_id) self.assertEqual(wc.local_mean, wt.local_mean) self.assertEqual(wc.request_time, wt.request_time) self.assertEqual(wc.duration, wt.duration) self.assertEqual(wc.block_digest, "Reader's Digest") self.assertIsNotNone(wc.signature) self.assertIsNotNone(wc.identifier) # A newly-created wait certificate should be valid self.assertTrue(wc.is_valid([], signup_info.poet_public_key))
def test_basic_create_signup_info(self): signup_info = \ SignupInfo.create_signup_info( self._create_random_public_key()) self.assertIsNotNone(signup_info.poet_public_key) self.assertIsNotNone(signup_info.anti_sybil_id) self.assertIsNotNone(signup_info.proof_data) self.assertIsNotNone(signup_info.sealed_signup_data)
def test_basic_create_signup_info(self): signup_info = \ SignupInfo.create_signup_info( originator_public_key=self._originator_public_key, validator_network_basename='This is CNN.', most_recent_wait_certificate_id=NullIdentifier) self.assertIsNotNone(signup_info.poet_public_key) self.assertIsNotNone(signup_info.proof_data) self.assertIsNotNone(signup_info.sealed_signup_data)
def test_non_matching_originator_public_key(self): signup_info = \ SignupInfo.create_signup_info( originator_public_key_hash=self._originator_public_key_hash, most_recent_wait_certificate_id=NullIdentifier) with self.assertRaises(SignupInfoError): signup_info.check_valid( originator_public_key_hash=self._another_public_key_hash, most_recent_wait_certificate_id=NullIdentifier)
def test_basic_create_signup_info(self): signup_info = \ SignupInfo.create_signup_info( originator_public_key_hash=self._originator_public_key_hash, most_recent_wait_certificate_id=NullIdentifier) self.assertIsNotNone(signup_info.poet_public_key) self.assertIsNotNone(signup_info.proof_data) self.assertIsNotNone(signup_info.anti_sybil_id) self.assertIsNotNone(signup_info.sealed_signup_data)
def test_verify_unsealing_data(self): signup_info = \ SignupInfo.create_signup_info( self._create_random_public_key()) encoded_poet_public_key = \ SignupInfo.unseal_signup_data(signup_info.sealed_signup_data) self.assertEqual( signup_info.poet_public_key, encoded_poet_public_key, msg="PoET public key in signup info and sealed data don't match")
def test_has_expired(self): # Need to create signup information first SignupInfo.create_signup_info( originator_public_key=self._originator_public_key, validator_network_basename="America's Most Watched Network", most_recent_wait_certificate_id=NullIdentifier) # Verify that a timer doesn't expire before its creation time wt = wait_timer.WaitTimer.create_wait_timer([]) self.assertFalse(wt.has_expired(wt.request_time - 1)) # Create a timer and when it has expired, verify that the duration is # not greater than actual elapsed time. wt = wait_timer.WaitTimer.create_wait_timer([]) while not wt.has_expired(time.time()): time.sleep(1) self.assertLessEqual(wt.duration, time.time() - wt.request_time) # Tampering with the duration should not affect wait timer expiration wt = wait_timer.WaitTimer.create_wait_timer([]) assigned_duration = wt.duration wt.duration = 0 while not wt.has_expired(time.time()): time.sleep(1) self.assertLessEqual(assigned_duration, time.time() - wt.request_time) # Tampering with the request time should not affect wait timer # expiration wt = wait_timer.WaitTimer.create_wait_timer([]) assigned_request_time = wt.request_time wt.request_time -= wt.duration while not wt.has_expired(time.time()): time.sleep(1) self.assertLessEqual(wt.duration, time.time() - assigned_request_time)
def test_non_matching_validator_network_basename(self): signup_info = \ SignupInfo.create_signup_info( originator_public_key=self._originator_public_key, validator_network_basename='This is CNN.', most_recent_wait_certificate_id=NullIdentifier) with self.assertRaises(SignupInfoError): signup_info.check_valid( originator_public_key=self._originator_public_key, validator_network_basename="This is Fox News.", most_recent_wait_certificate_id=NullIdentifier)
def test_verify_unsealing_data(self): signup_info = \ SignupInfo.create_signup_info( originator_public_key_hash=self._originator_public_key_hash, most_recent_wait_certificate_id=NullIdentifier) poet_public_key = \ SignupInfo.unseal_signup_data(signup_info.sealed_signup_data) self.assertEqual( signup_info.poet_public_key, poet_public_key, msg="PoET public key in signup info and sealed data don't match")
def test_verify_signup_info(self): signup_info = \ SignupInfo.create_signup_info( originator_public_key_hash=self._originator_public_key_hash, most_recent_wait_certificate_id=NullIdentifier) try: signup_info.check_valid( originator_public_key_hash=self._originator_public_key_hash, most_recent_wait_certificate_id=NullIdentifier) except SignupInfoError as e: self.fail('Error with SignupInfo: {}'.format(e))
def test_verify_serialized_signup_info(self): signup_info = \ SignupInfo.create_signup_info( originator_public_key=self._originator_public_key, validator_network_basename='This is CNN.', most_recent_wait_certificate_id=NullIdentifier) serialized = signup_info.serialize() copy_signup_info = SignupInfo.signup_info_from_serialized(serialized) self.assertEqual(signup_info.poet_public_key, copy_signup_info.poet_public_key) self.assertEqual(signup_info.proof_data, copy_signup_info.proof_data) self.assertIsNone(copy_signup_info.sealed_signup_data)
def test_verify_unsealing_data(self): signup_info = \ SignupInfo.create_signup_info( originator_public_key=self._originator_public_key, validator_network_basename='This is CNN.', most_recent_wait_certificate_id=NullIdentifier) encoded_poet_public_key = \ SignupInfo.unseal_signup_data(signup_info.sealed_signup_data) self.assertEqual( signup_info.poet_public_key, encoded_poet_public_key, msg="PoET public key in signup info and sealed data don't match")
def test_verify_serialized_signup_info(self): signup_info = \ SignupInfo.create_signup_info( self._create_random_public_key()) serialized = signup_info.serialize() copy_signup_info = SignupInfo.signup_info_from_serialized(serialized) self.assertEqual(signup_info.poet_public_key, copy_signup_info.poet_public_key) self.assertEqual(signup_info.anti_sybil_id, copy_signup_info.anti_sybil_id) self.assertEqual(signup_info.proof_data, copy_signup_info.proof_data) self.assertIsNone(copy_signup_info.sealed_signup_data)
def test_verify_signup_info(self): signup_info = \ SignupInfo.create_signup_info( originator_public_key=self._originator_public_key, validator_network_basename='This is CNN.', most_recent_wait_certificate_id=NullIdentifier) try: signup_info.check_valid( originator_public_key=self._originator_public_key, validator_network_basename="This is CNN.", most_recent_wait_certificate_id=NullIdentifier) except SignupInfoError as e: self.fail('Error with SignupInfo: {}'.format(e))
def test_verify_serialized_signup_info(self): signup_info = \ SignupInfo.create_signup_info( originator_public_key_hash=self._originator_public_key_hash, most_recent_wait_certificate_id=NullIdentifier) serialized = signup_info.serialize() copy_signup_info = SignupInfo.signup_info_from_serialized(serialized) self.assertEqual(signup_info.poet_public_key, copy_signup_info.poet_public_key) self.assertEqual(signup_info.proof_data, copy_signup_info.proof_data) self.assertEqual(signup_info.anti_sybil_id, copy_signup_info.anti_sybil_id) self.assertIsNone(copy_signup_info.sealed_signup_data)
def test_verify_serialized_signup_info(self): signup_info = \ SignupInfo.create_signup_info( originator_public_key=self._originator_public_key, validator_network_basename='This is CNN.', most_recent_wait_certificate_id=NullIdentifier) serialized = signup_info.serialize() copy_signup_info = SignupInfo.signup_info_from_serialized(serialized) self.assertEqual( signup_info.poet_public_key, copy_signup_info.poet_public_key) self.assertEqual(signup_info.proof_data, copy_signup_info.proof_data) self.assertIsNone(copy_signup_info.sealed_signup_data)
def test_non_matching_most_recent_wait_certificate_id(self): signup_info = \ SignupInfo.create_signup_info( originator_public_key_hash=self._originator_public_key_hash, most_recent_wait_certificate_id=NullIdentifier) # NOTE - this requires that the signup information check for validity # actually make this check. Currently the check is not done. # Once the check is added back, it should raise a # SignupInfoError exception and this test will fail, alerting # you that you need to wrap the call in self.assertRaises # # with self.assertRaises(SignupInfoError): signup_info.check_valid( originator_public_key_hash=self._originator_public_key_hash, most_recent_wait_certificate_id='SomeFunkyCertificateID')
def test_non_matching_most_recent_wait_certificate_id(self): signup_info = \ SignupInfo.create_signup_info( originator_public_key=self._originator_public_key, validator_network_basename='This is CNN.', most_recent_wait_certificate_id=NullIdentifier) # NOTE - this requires that the signup information check for validity # actually make this check. Currently the check is not done. # Once the check is added back, it should raise a # SignupInfoError exception and this test will fail, alerting # you that you need to wrap the call in self.assertRaises # # with self.assertRaises(SignupInfoError): signup_info.check_valid( originator_public_key=self._originator_public_key, validator_network_basename="This is CNN.", most_recent_wait_certificate_id='SomeFunkyCertificateID')
def test_register_validator_key_mismatch(self): key = signed_object.generate_signing_key() key2 = signed_object.generate_signing_key() validator_id = signed_object.generate_identifier(key) name = 'DasValidator' signup_info = \ SignupInfo.create_signup_info( originator_public_key=pybitcointools.privtopub(key), validator_network_basename='Intel Validator Network', most_recent_wait_certificate_id='0' * 16) store = KeyValueStore() transaction = \ ValidatorRegistryTransaction.register_validator( name, validator_id, signup_info) transaction.sign_object(key2) with self.assertRaises(InvalidTransactionError): transaction.check_valid(store) self.fail("Failure: Verified an invalid transaction")
def initialization_complete(self, journal): """Processes all invocations that arrived while the ledger was being initialized. """ # Before we allow the base journal to do anything that might result # in a wait timer or wait certificate from being created, we have to # ensure that the PoET enclave has been initialized. This can be done # in one of two ways: # 1. If we have sealed signup data (meaning that we have previously # created signup info), we can request that the enclave unseal it, # in the process restoring the enclave to its previous state. # 2. Create new signup information. signup_info = None sealed_signup_data = journal.local_store.get('sealed_signup_data') if sealed_signup_data is not None: SignupInfo.unseal_signup_data( sealed_signup_data=sealed_signup_data) else: wait_certificate_id = journal.most_recent_committed_block_id signup_info = \ SignupInfo.create_signup_info( originator_public_key=journal.local_node.public_key(), validator_network_basename='Intel Validator Network', most_recent_wait_certificate_id=wait_certificate_id) # Save off the sealed signup data self.local_store.set('sealed_signup_data', signup_info.sealed_signup_data) self.local_store.sync() # initialize the poet handlers poet_transaction_block.register_message_handlers(journal) # initialize stats specifically for the block chain journal journal.JournalStats.add_metric(stats.Value('LocalMeanTime', 0)) journal.JournalStats.add_metric( stats.Value('AggregateLocalMean', '0')) journal.JournalStats.add_metric( stats.Value('PopulationEstimate', '0')) journal.JournalStats.add_metric( stats.Value('ExpectedExpirationTime', '0')) journal.JournalStats.add_metric(stats.Value('Duration', '0')) # If we created signup information, then insert ourselves into the # validator registry. if signup_info is not None: # Create a validator register transaction and sign it. Wrap # the transaction in a message. Broadcast it to out. transaction = \ val_reg.ValidatorRegistryTransaction.register_validator( self.local_node.Name, self.local_node.Identifier, signup_info) transaction.sign_from_node(self.local_node) message = \ val_reg.ValidatorRegistryTransactionMessage() message.Transaction = transaction LOGGER.info('Register PoET 1 validator with name %s', journal.local_node.Name) journal.gossip.broadcast_message(message)
def test_create_wait_timer(self): # Need to create signup information first signup_info = \ SignupInfo.create_signup_info( originator_public_key=self._originator_public_key, validator_network_basename="America's Most Watched Network", most_recent_wait_certificate_id=NullIdentifier) stake_in_the_sand = time.time() # An empty certificate list should result in a local mean that is # the target wait time wt = wait_timer.WaitTimer.create_wait_timer([]) self.assertIsNotNone(wt) self.assertEqual(wt.local_mean, wait_timer.WaitTimer.target_wait_time) self.assertEquals(wt.previous_certificate_id, NullIdentifier) self.assertGreaterEqual(wt.request_time, stake_in_the_sand) self.assertLessEqual(wt.request_time, time.time()) self.assertGreaterEqual( wt.duration, wait_timer.WaitTimer.minimum_wait_time) wt = wait_timer.WaitTimer.create_wait_timer(tuple()) self.assertIsNotNone(wt) self.assertEqual(wt.local_mean, wait_timer.WaitTimer.target_wait_time) self.assertEquals(wt.previous_certificate_id, NullIdentifier) self.assertGreaterEqual(wt.request_time, stake_in_the_sand) self.assertLessEqual(wt.request_time, time.time()) self.assertGreaterEqual( wt.duration, wait_timer.WaitTimer.minimum_wait_time) # Ensure that the enclave is set back to initial state SignupInfo.poet_enclave = reload(poet_enclave) wait_timer.WaitTimer.poet_enclave = SignupInfo.poet_enclave # Make sure that trying to create a wait timer before signup # information is provided causes an error with self.assertRaises(wait_timer.WaitTimerError): wait_timer.WaitTimer.create_wait_timer([]) with self.assertRaises(wait_timer.WaitTimerError): wait_timer.WaitTimer.create_wait_timer(tuple()) # Initialize the enclave with sealed signup data SignupInfo.unseal_signup_data(signup_info.sealed_signup_data) stake_in_the_sand = time.time() # An empty certificate list should result in a local mean that is # the target wait time wt = wait_timer.WaitTimer.create_wait_timer([]) self.assertIsNotNone(wt) self.assertEqual(wt.local_mean, wait_timer.WaitTimer.target_wait_time) self.assertEquals(wt.previous_certificate_id, NullIdentifier) self.assertGreaterEqual(wt.request_time, stake_in_the_sand) self.assertLessEqual(wt.request_time, time.time()) self.assertGreaterEqual( wt.duration, wait_timer.WaitTimer.minimum_wait_time) wt = wait_timer.WaitTimer.create_wait_timer(tuple()) self.assertIsNotNone(wt) self.assertEqual(wt.local_mean, wait_timer.WaitTimer.target_wait_time) self.assertEquals(wt.previous_certificate_id, NullIdentifier) self.assertGreaterEqual(wt.request_time, stake_in_the_sand) self.assertLessEqual(wt.request_time, time.time()) self.assertGreaterEqual( wt.duration, wait_timer.WaitTimer.minimum_wait_time)
def initialization_complete(self, journal): """Processes all invocations that arrived while the ledger was being initialized. """ # Before we allow the base journal to do anything that might result # in a wait timer or wait certificate being created, we have to ensure # the PoET enclave has been initialized. This can be done in one of # two ways: # 1. If we have sealed signup data (meaning that we have previously # created signup info), we can request that the enclave unseal it, # in the process restoring the enclave to its previous state. # 2. Create new signup information. signup_info = None sealed_signup_data = journal.local_store.get('sealed_signup_data') if sealed_signup_data is not None: SignupInfo.unseal_signup_data( sealed_signup_data=sealed_signup_data) else: wait_certificate_id = journal.most_recent_committed_block_id signup_info = \ SignupInfo.create_signup_info( originator_public_key=journal.local_node.public_key(), validator_network_basename='Intel Validator Network', most_recent_wait_certificate_id=wait_certificate_id) # Save off the sealed signup data journal.local_store.set( 'sealed_signup_data', signup_info.sealed_signup_data) journal.local_store.sync() # propagate the maximum blocks to keep journal.maximum_blocks_to_keep = max( journal.maximum_blocks_to_keep, WaitTimer.certificate_sample_length) # initialize stats specifically for the block chain journal journal.JournalStats.add_metric(stats.Value('LocalMeanTime', 0)) journal.JournalStats.add_metric(stats.Value('AggregateLocalMean', '0')) journal.JournalStats.add_metric(stats.Value('PopulationEstimate', '0')) journal.JournalStats.add_metric(stats.Value('ExpectedExpirationTime', '0')) journal.JournalStats.add_metric(stats.Value('Duration', '0')) # initialize the block handlers poet_transaction_block.register_message_handlers(journal) # If we created signup information, then insert ourselves into the # validator registry. if signup_info is not None: # Create a validator register transaction and sign it. Wrap # the transaction in a message. Broadcast it to out. transaction = \ val_reg.ValidatorRegistryTransaction.register_validator( journal.local_node.Name, journal.local_node.Identifier, signup_info) transaction.sign_from_node(journal.local_node) message = \ val_reg.ValidatorRegistryTransactionMessage() message.Transaction = transaction LOGGER.info( 'Register PoET 1 validator with name %s', journal.local_node.Name) journal.gossip.broadcast_message(message)