def test_create_wait_certificate_before_wait_timer_expires(self): # Need to create signup information SignupInfo.create_signup_info( validator_address='1660 Pennsylvania Avenue NW', originator_public_key_hash=self._originator_public_key_hash, most_recent_wait_certificate_id=NullIdentifier) # Create a wait certificate for the genesis block so that we can # create another wait certificate that has to play by the rules. wt = \ WaitTimer.create_wait_timer( validator_address='1660 Pennsylvania Avenue NW', certificates=[]) wc = \ WaitCertificate.create_wait_certificate( wait_timer=wt, block_digest="Reader's Digest") wt = \ WaitTimer.create_wait_timer( validator_address='1660 Pennsylvania Avenue NW', certificates=[wc]) with self.assertRaises(ValueError): WaitCertificate.create_wait_certificate( wait_timer=wt, block_digest="Reader's Digest")
def test_create_wait_certificate_with_wrong_wait_timer(self): # Need to create signup information SignupInfo.create_signup_info( validator_address='1660 Pennsylvania Avenue NW', originator_public_key_hash=self._originator_public_key_hash, most_recent_wait_certificate_id=NullIdentifier) # Create two timers and try to create the wait certificate with the # first one, which should fail as it is not the current wait timer invalid_wt = \ WaitTimer.create_wait_timer( validator_address='1660 Pennsylvania Avenue NW', certificates=[]) valid_wt = \ WaitTimer.create_wait_timer( validator_address='1660 Pennsylvania Avenue NW', certificates=[]) # Verify that we cannot create a wait certificate with the old wait # timer, but we can with the new one with self.assertRaises(ValueError): WaitCertificate.create_wait_certificate( wait_timer=invalid_wt, block_digest="Reader's Digest") WaitCertificate.create_wait_certificate( wait_timer=valid_wt, block_digest="Reader's Digest")
def test_create_wait_certificate_after_wait_timer_timed_out(self): # Need to create signup information SignupInfo.create_signup_info( validator_address='1660 Pennsylvania Avenue NW', originator_public_key_hash=self._originator_public_key_hash, most_recent_wait_certificate_id=NullIdentifier) # Create a wait certificate for the genesis block so that we can # create another wait certificate that has to play by the rules. wt = \ WaitTimer.create_wait_timer( validator_address='1660 Pennsylvania Avenue NW', certificates=[]) wc = \ WaitCertificate.create_wait_certificate( wait_timer=wt, block_digest="Reader's Digest") wt = \ WaitTimer.create_wait_timer( validator_address='1660 Pennsylvania Avenue NW', certificates=[wc]) while not wt.has_expired(time.time()): time.sleep(1) time.sleep(WaitTimer.poet_enclave.TIMER_TIMEOUT_PERIOD + 1) with self.assertRaises(ValueError): WaitCertificate.create_wait_certificate( wait_timer=wt, block_digest="Reader's Digest")
def test_create_wait_certificate_with_wrong_wait_timer(self): # Need to create signup information SignupInfo.create_signup_info( validator_address='1660 Pennsylvania Avenue NW', originator_public_key_hash=self._originator_public_key_hash, most_recent_wait_certificate_id=NullIdentifier) # Create two timers and try to create the wait certificate with the # first one, which should fail as it is not the current wait timer invalid_wt = \ WaitTimer.create_wait_timer( validator_address='1660 Pennsylvania Avenue NW', certificates=[]) valid_wt = \ WaitTimer.create_wait_timer( validator_address='1660 Pennsylvania Avenue NW', certificates=[]) # Verify that we cannot create a wait certificate with the old wait # timer, but we can with the new one with self.assertRaises(ValueError): WaitCertificate.create_wait_certificate( wait_timer=invalid_wt, block_digest="Reader's Digest") WaitCertificate.create_wait_certificate(wait_timer=valid_wt, block_digest="Reader's Digest")
def test_create_wait_certificate(self): # Need to create signup information and wait timer first signup_info = \ SignupInfo.create_signup_info( validator_address='1660 Pennsylvania Avenue NW', originator_public_key_hash=self._originator_public_key_hash, most_recent_wait_certificate_id=NullIdentifier) wt = \ WaitTimer.create_wait_timer( validator_address='1660 Pennsylvania Avenue NW', certificates=[]) while not wt.has_expired(time.time()): time.sleep(1) # Now we can create a wait certificate and verify that it correlates # to the wait timer we just created wc = \ WaitCertificate.create_wait_certificate( wait_timer=None, block_digest="Reader's Digest") self.assertIsNotNone(wc) self.assertEquals( wc.previous_certificate_id, wt.previous_certificate_id) self.assertAlmostEquals(wc.local_mean, wt.local_mean) self.assertAlmostEquals(wc.request_time, wt.request_time) self.assertAlmostEquals(wc.duration, wt.duration) self.assertEqual(wc.validator_address, wt.validator_address) 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)) # Create another wait certificate and verify it is valid also wt = \ WaitTimer.create_wait_timer( validator_address='1660 Pennsylvania Avenue NW', certificates=[wc]) while not wt.has_expired(time.time()): time.sleep(1) # Now we can create a wait certificate and verify that it correlates # to the wait timer we just created another_wc = \ WaitCertificate.create_wait_certificate( wait_timer=None, block_digest="Pepto Bismol") self.assertTrue( another_wc.is_valid([wc], 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( validator_address='1660 Pennsylvania Avenue NW', originator_public_key_hash=self._originator_public_key_hash, most_recent_wait_certificate_id=NullIdentifier) wt = \ WaitTimer.create_wait_timer( validator_address='1660 Pennsylvania Avenue NW', certificates=[]) while not wt.has_expired(time.time()): time.sleep(1) # Now we can create a wait certificate and verify that it correlates # to the wait timer we just created wc = \ WaitCertificate.create_wait_certificate( wait_timer=wt, block_digest="Reader's Digest") self.assertIsNotNone(wc) self.assertEqual( wc.previous_certificate_id, wt.previous_certificate_id) self.assertAlmostEqual(wc.local_mean, wt.local_mean) self.assertAlmostEqual(wc.request_time, wt.request_time) self.assertAlmostEqual(wc.duration, wt.duration) self.assertEqual(wc.validator_address, wt.validator_address) self.assertEqual(wc.block_digest, "Reader's Digest") self.assertIsNotNone(wc.signature) self.assertIsNotNone(wc.identifier) # A newly-created wait certificate should be valid wc.check_valid([], signup_info.poet_public_key) # Create another wait certificate and verify it is valid also wt = \ WaitTimer.create_wait_timer( validator_address='1660 Pennsylvania Avenue NW', certificates=[wc]) while not wt.has_expired(time.time()): time.sleep(1) # Now we can create a wait certificate and verify that it correlates # to the wait timer we just created another_wc = \ WaitCertificate.create_wait_certificate( wait_timer=wt, block_digest="Pepto Bismol") another_wc.check_valid([wc], signup_info.poet_public_key)
def test_create_wait_certificate_before_wait_timer_expires(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) # Create a wait certificate for the genesis block so that we can # create another wait certificate that has to play by the rules. wt = WaitTimer.create_wait_timer([]) wc = WaitCertificate.create_wait_certificate("Reader's Digest") wt = WaitTimer.create_wait_timer([wc]) with self.assertRaises(WaitCertificateError): wc = WaitCertificate.create_wait_certificate("Reader's Digest")
def test_wait_certificate_serialization(self): # Need to create signup information and wait timer first signup_info = \ SignupInfo.create_signup_info( validator_address='1660 Pennsylvania Avenue NW', originator_public_key_hash=self._originator_public_key_hash, most_recent_wait_certificate_id=NullIdentifier) wt = \ WaitTimer.create_wait_timer( validator_address='1660 Pennsylvania Avenue NW', certificates=[]) while not wt.has_expired(time.time()): time.sleep(1) # Now we can create a wait certificate and serialize wc = \ WaitCertificate.create_wait_certificate( wait_timer=wt, block_digest="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')) self.assertEqual( wc.previous_certificate_id, wc_copy.previous_certificate_id) self.assertAlmostEqual(wc.local_mean, wc_copy.local_mean) self.assertAlmostEqual(wc.request_time, wc_copy.request_time) self.assertAlmostEqual(wc.duration, wc_copy.duration) self.assertEqual(wc.validator_address, wc_copy.validator_address) self.assertEqual(wc.block_digest, wc_copy.block_digest) self.assertEqual(wc.signature, wc_copy.signature) self.assertEqual(wc.identifier, wc_copy.identifier) # Serialize the copy and verify that its serialization and # signature are the same dumped_copy = wc_copy.dump() self.assertTrue( dumped.get('SerializedCertificate'), dumped_copy.get('SerializedCertificate')) self.assertTrue( dumped.get('Signature'), dumped_copy.get('Signature')) wc_copy.check_valid([], signup_info.poet_public_key)
def test_wait_certificate_serialization(self): # Need to create signup information and wait timer first signup_info = \ SignupInfo.create_signup_info( validator_address='1660 Pennsylvania Avenue NW', originator_public_key_hash=self._originator_public_key_hash, most_recent_wait_certificate_id=NullIdentifier) wt = \ WaitTimer.create_wait_timer( validator_address='1660 Pennsylvania Avenue NW', certificates=[]) while not wt.has_expired(time.time()): time.sleep(1) # Now we can create a wait certificate and serialize wc = \ WaitCertificate.create_wait_certificate( wait_timer=None, block_digest="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')) self.assertEquals( wc.previous_certificate_id, wc_copy.previous_certificate_id) self.assertAlmostEquals(wc.local_mean, wc_copy.local_mean) self.assertAlmostEquals(wc.request_time, wc_copy.request_time) self.assertAlmostEquals(wc.duration, wc_copy.duration) self.assertEqual(wc.validator_address, wc_copy.validator_address) self.assertEqual(wc.block_digest, wc_copy.block_digest) self.assertEqual(wc.signature, wc_copy.signature) self.assertEqual(wc.identifier, wc_copy.identifier) # Serialize the copy and verify that its serialization and # signature are the same dumped_copy = wc_copy.dump() self.assertTrue( dumped.get('SerializedCertificate'), dumped_copy.get('SerializedCertificate')) self.assertTrue( dumped.get('Signature'), dumped_copy.get('Signature')) self.assertTrue(wc_copy.is_valid([], signup_info.poet_public_key))
def test_create_wait_certificate_with_reused_wait_timer(self): # Need to create signup information SignupInfo.create_signup_info( validator_address='1660 Pennsylvania Avenue NW', originator_public_key_hash=self._originator_public_key_hash, most_recent_wait_certificate_id=NullIdentifier) # Create a wait certificate for the genesis block so that we can # create another wait certificate that has to play by the rules. wt = \ WaitTimer.create_wait_timer( validator_address='1660 Pennsylvania Avenue NW', certificates=[]) wc = \ WaitCertificate.create_wait_certificate( wait_timer=wt, block_digest="Reader's Digest") consumed_wt = wt # Verify that we cannot use the consumed wait timer to create a wait # certificate either before or after creating a new wait timer with self.assertRaises(ValueError): WaitCertificate.create_wait_certificate( wait_timer=consumed_wt, block_digest="Reader's Digest") wt = \ WaitTimer.create_wait_timer( validator_address='1660 Pennsylvania Avenue NW', certificates=[wc]) with self.assertRaises(ValueError): WaitCertificate.create_wait_certificate( wait_timer=consumed_wt, block_digest="Reader's Digest") # Verify that once the new timer expires, we can create a wait # certificate with it while not wt.has_expired(time.time()): time.sleep(1) WaitCertificate.create_wait_certificate( wait_timer=wt, block_digest="Reader's Digest")
def test_create_wait_certificate_with_reused_wait_timer(self): # Need to create signup information SignupInfo.create_signup_info( validator_address='1660 Pennsylvania Avenue NW', originator_public_key_hash=self._originator_public_key_hash, most_recent_wait_certificate_id=NullIdentifier) # Create a wait certificate for the genesis block so that we can # create another wait certificate that has to play by the rules. wt = \ WaitTimer.create_wait_timer( validator_address='1660 Pennsylvania Avenue NW', certificates=[]) wc = \ WaitCertificate.create_wait_certificate( wait_timer=wt, block_digest="Reader's Digest") consumed_wt = wt # Verify that we cannot use the consumed wait timer to create a wait # certificate either before or after creating a new wait timer with self.assertRaises(ValueError): WaitCertificate.create_wait_certificate( wait_timer=consumed_wt, block_digest="Reader's Digest") wt = \ WaitTimer.create_wait_timer( validator_address='1660 Pennsylvania Avenue NW', certificates=[wc]) with self.assertRaises(ValueError): WaitCertificate.create_wait_certificate( wait_timer=consumed_wt, block_digest="Reader's Digest") # Verify that once the new timer expires, we can create a wait # certificate with it while not wt.has_expired(time.time()): time.sleep(1) WaitCertificate.create_wait_certificate(wait_timer=wt, block_digest="Reader's Digest")
def check_valid(self, certificates, poet_public_key): """Determines whether the wait certificate is valid. Args: certificates (list): A list of historical certs. poet_public_key (str): The PoET public key that corresponds to the private key used to sign the certificate. This is obtained from the signup information for the validator that is the originator of the block for which the wait certificate is associated. Returns: True if the wait certificate is valid, False otherwise. """ enclave_certificate = self.enclave_wait_certificate expected_mean = WaitTimer.compute_local_mean(certificates) if enclave_certificate.duration < WaitTimer.minimum_wait_time: raise \ ValueError( 'Wait time less than minimum: {0} < {1}'.format( enclave_certificate.duration, WaitTimer.minimum_wait_time)) if not _is_close( enclave_certificate.local_mean, expected_mean, abs_tol=0.001): raise \ ValueError( 'Local mean does not match: {0} != {1}'.format( enclave_certificate.local_mean, expected_mean)) if len(certificates) != 0 and \ enclave_certificate.previous_certificate_id != \ certificates[-1].identifier: raise \ ValueError( 'Previous certificate ID does not match: {0} != ' '{1}'.foramt( enclave_certificate.previous_certificate_id, certificates[-1].identifier)) try: self.poet_enclave.verify_wait_certificate( certificate=enclave_certificate, poet_public_key=poet_public_key) except Timeout: raise NotAvailableException except ConnectionError: raise NotAvailableException
def is_valid(self, certificates, poet_public_key): """Determines whether the wait certificate is valid. Args: certificates (list): A list of historical certs. poet_public_key (str): The PoET public key that corresponds to the private key used to sign the certificate. This is obtained from the signup information for the validator that is the originator of the block for which the wait certificate is associated. Returns: True if the wait certificate is valid, False otherwise. """ enclave_certificate = self.enclave_wait_certificate expected_mean = WaitTimer.compute_local_mean(certificates) if enclave_certificate.duration < self.poet_enclave.MINIMUM_WAIT_TIME: LOGGER.warn('Wait time less then minimum: %s != %s', enclave_certificate.duration, self.poet_enclave.MINIMUM_WAIT_TIME) return False if not _is_close( enclave_certificate.local_mean, expected_mean, abs_tol=0.001): LOGGER.warn('mismatch local mean: %s != %s', enclave_certificate.local_mean, expected_mean) return False if enclave_certificate.previous_certificate_id == NullIdentifier: if len(certificates) == 0: return True if enclave_certificate.previous_certificate_id != \ certificates[-1].identifier: LOGGER.warn('mismatch previous identifier: %s != %s', enclave_certificate.previous_certificate_id, certificates[-1].identifier) return False try: return \ self.poet_enclave.verify_wait_certificate( certificate=enclave_certificate, poet_public_key=poet_public_key) except Timeout: raise NotAvailableException except ConnectionError: raise NotAvailableException