def has_corresponding_commit_transaction(self, transaction): epoch_hashes = self.epoch.get_epoch_hashes() commit_hash = transaction.commit_hash for top, _epoch_hash in epoch_hashes.items(): commits = self.epoch.get_commits_for_epoch(top) if commit_hash in commits: commit = commits[commit_hash] # check if commited random can be encrypted by reveal private key try: Private.decrypt(commit.rand, transaction.key) except IntegrityError as e: raise AcceptionException( "Private key in reveal random transaction is not valid for corresponding commit transaction!" ) else: raise AcceptionException( "Reveal transaction has no corresponding commit transaction in the chain!" )
def reveal_commited_random(self, block_hash): if block_hash == self.dag.genesis_block().get_hash(): return 0 seed = 0 commits = self.get_commits_for_epoch(block_hash) reveals = self.get_reveals_for_epoch(block_hash) randoms_list = [] for reveal in reveals: if reveal.commit_hash in commits: commit = commits[reveal.commit_hash] key = Keys.from_bytes(reveal.key) revealed_data = Private.decrypt(commit.rand, key) randoms_list.append( int.from_bytes(revealed_data, byteorder='big')) seed = sum_random(randoms_list) return seed
def test_commit_reveal(self): dag = Dag(0) epoch = Epoch(dag) private = Private.generate() prev_hash = ChainGenerator.fill_with_dummies( dag, dag.genesis_block().get_hash(), Epoch.get_round_range(1, Round.PUBLIC)) randoms_list = [] for i in Epoch.get_round_range(1, Round.COMMIT): random_value = int.from_bytes(os.urandom(32), byteorder='big') randoms_list.append(random_value) expected_seed = sum_random(randoms_list) reveals = [] epoch_hash = dag.genesis_block().get_hash() for i in Epoch.get_round_range(1, Round.COMMIT): rand = randoms_list.pop() random_bytes = rand.to_bytes(32, byteorder='big') commit, reveal = TestEpoch.create_dummy_commit_reveal( random_bytes, epoch_hash) commit_block = BlockFactory.create_block_with_timestamp( [prev_hash], i * BLOCK_TIME) commit_block.system_txs = [commit] signed_block = BlockFactory.sign_block(commit_block, private) dag.add_signed_block(i, signed_block) prev_hash = commit_block.get_hash() reveals.append(reveal) revealing_key = Keys.from_bytes(reveal.key) encrypted_bytes = Public.encrypt(random_bytes, Private.publickey(revealing_key)) decrypted_bytes = Private.decrypt(encrypted_bytes, revealing_key) # TODO check if encryption decryption can work million times in a row self.assertEqual(decrypted_bytes, random_bytes) revealed_value = Private.decrypt(commit.rand, revealing_key) self.assertEqual(revealed_value, random_bytes) # self.assertEqual(len(reveals), ROUND_DURATION) prev_hash = ChainGenerator.fill_with_dummies( dag, prev_hash, Epoch.get_round_range(1, Round.SECRETSHARE)) for i in Epoch.get_round_range(1, Round.REVEAL): reveal_block = BlockFactory.create_block_with_timestamp( [prev_hash], i * BLOCK_TIME) reveal_block.system_txs = [reveals.pop()] signed_block = BlockFactory.sign_block(reveal_block, private) dag.add_signed_block(i, signed_block) prev_hash = reveal_block.get_hash() prev_hash = ChainGenerator.fill_with_dummies( dag, prev_hash, Epoch.get_round_range(1, Round.PRIVATE)) prev_hash = ChainGenerator.fill_with_dummies( dag, prev_hash, Epoch.get_round_range(1, Round.FINAL)) seed = epoch.reveal_commited_random(prev_hash) self.assertEqual(expected_seed, seed)
def dec_part_secret(privatekey, enc_data, number): split = Private.decrypt(enc_data, privatekey) if split: return (number + 1, int.from_bytes(split, byteorder="big")) return None