def _calc_hashchain( seed_private, epoch, blocks_per_epoch): """ generates a 20,000th hash in iterative sha256 chain..derived from private SEED :param epoch: :type epoch: int :return: """ hc_seed = getHashChainSeed(seed_private, epoch, config.dev.hashchain_nums) hc = [[hash_chain] for hash_chain in hc_seed] hc_terminator = [] for hash_chain in hc[:-1]: # skip last element as it is reveal hash for x in range(blocks_per_epoch): hash_chain.append(sha2_256(hash_chain[-1])) hc_terminator.append(hash_chain[-1]) # Reveal hash chain for hash_chain in hc[-1:]: # Extra hash to reveal one hash value for x in range(blocks_per_epoch + 1): hash_chain.append(sha2_256(hash_chain[-1])) hc_terminator.append(hash_chain[-1]) return hc_seed, hc, hc_terminator
def set_chain(self, chain): # FIXME: It is odd that we have a hash equal to 'genesis' """ :param chain: :type chain: :return: :rtype: >>> GenesisBlock().set_chain(None) is not None True >>> GenesisBlock().set_chain(None).blockheader.epoch 0 >>> GenesisBlock().set_chain(None).blockheader.block_reward 0 >>> GenesisBlock().set_chain(None).blockheader.blocknumber 0 >>> GenesisBlock().set_chain(None).blockheader.fee_reward 0 >>> GenesisBlock().set_chain(None).blockheader.reveal_hash 'genesis' >>> bin2hstr(GenesisBlock().set_chain(None).blockheader.headerhash) '6e3a32597ab20577f7adf33d77aed79631193419432ec7183fcdbbd470cfcccc' >>> bin2hstr(GenesisBlock().set_chain(None).blockheader.prev_blockheaderhash) 'a2cb1574a3e5bc97a441e478a4cb8954901a26e4fe297d72088418db51e2ed6e' """ self.blockheader.create( chain=chain, blocknumber=0, prev_blockheaderhash=sha2_256( config.dev.genesis_prev_headerhash.encode()), hashedtransactions=sha2_256(b'0'), reveal_hash='genesis', vote_hash='genesis', fee_reward=0) return self
def set_chain(self, chain): # FIXME: It is odd that we have a hash equal to 'genesis' """ :param chain: :type chain: :return: :rtype: >>> GenesisBlock().set_chain(None) is not None True >>> GenesisBlock().set_chain(None).blockheader.epoch 0 >>> GenesisBlock().set_chain(None).blockheader.block_reward 0 >>> GenesisBlock().set_chain(None).blockheader.blocknumber 0 >>> GenesisBlock().set_chain(None).blockheader.fee_reward 0 >>> GenesisBlock().set_chain(None).blockheader.reveal_hash 'genesis' >>> bin2hstr(GenesisBlock().set_chain(None).blockheader.headerhash) 'ef651a6c581c1e96c6d3b9d8cb6579d45bdb8a12db428acd23acd1ba7ab41841' >>> bin2hstr(GenesisBlock().set_chain(None).blockheader.prev_blockheaderhash) 'c593bc8feea0099ddd3a4a457150ca215499d680c49bbc4c2c24a72f2179439d' """ self.blockheader.create( chain=chain, blocknumber=0, prev_blockheaderhash=sha2_256( config.dev.genesis_prev_headerhash.encode()), hashedtransactions=sha2_256(b'0'), reveal_hash='genesis', vote_hash='genesis', fee_reward=0) return self
def test_get_token_metadata(self): with set_qrl_dir('no_data'): with State() as state: token_txhash = bytes(sha2_256(b'alpha')) token_metadata = TokenMetadata.create(token_txhash, [bytes(sha2_256(b'delta')), bytes(sha2_256(b'gamma'))]) state._db.get_raw = MagicMock(return_value=token_metadata.serialize()) self.assertEqual(state.get_token_metadata(token_txhash).to_json(), token_metadata.to_json())
def setUp(self): self.blockheader = Mock(name='mock BlockHeader', autospec=BlockHeader, block_number=5, headerhash=bytes(sha2_256(b'mock headerhash')), prev_headerhash=bytes(sha2_256(b'test'))) self.block = Block.create(block_number=5, prev_headerhash=bytes(sha2_256(b'test')), prev_timestamp=10, transactions=[], miner_address=alice.address) self.block.blockheader = self.blockheader
def _get_hashable_bytes(self): """ This method should return bytes that are to be hashed and represent the transaction :return: hashable bytes :rtype: bytes """ # FIXME: Avoid all intermediate conversions tmptxhash = bin2hstr(tuple(self.hash)) tmptxhash = str2bin(tmptxhash + bin2hstr(self.slave_public_key) + bin2hstr(sha2_256(bytes(self.activation_blocknumber))) + bin2hstr(sha2_256(bytes(self.subtype)))) # FIXME: stringify in standardized way # FIXME: the order in the dict may affect hash return bytes(tmptxhash)
def mining_hash(self): representation = "{0}{1}{2}{3}{4}{5}{6}{7}".format( self.PK, self.epoch, self.block_reward, self.fee_reward, self.timestamp, self.block_number, self.prev_hash, self.tx_merkle_root) # Add the nonce placeholder (4 bytes) to the beginning of the Block representation. return "00000000" + bin2hstr(bytes(sha2_256(str2bin(representation))))
def generate_headerhash(self): # FIXME: This is using strings... fix data = "{0}{1}{2}{3}{4}{5}{6}{7}{8}".format( self.stake_selector, self.epoch, self.block_reward, self.fee_reward, self.timestamp, self.block_number, self.prev_blockheaderhash, self.tx_merkle_root, self.reveal_hash) return bytes(sha2_256(str2bin(data)))
def get_message_hash(self): msg_hash = (str(self._data.msg_id).encode() + str(self._data.ttl).encode() + str(self._data.ttr).encode() + str(self._data.nonce).encode() + self._data.channel.enc_aes256_symkey + self._data.payload) return bytes(sha2_256(msg_hash))
def hash(self, nonce, preview=False): # nonce (already a hexstring) + mining_hash (already a hexstring) blob_with_new_nonce = nonce + self.blockheader.mining_hash[8:] blockhash = bin2hstr(bytes(sha2_256(hstr2bin(blob_with_new_nonce)))) if not preview: self.blockheader.hash = blockhash return blockhash
def test_mining_blob(self): alice_xmss = get_alice_xmss() block = Block.create(block_number=5, prevblock_headerhash=bytes(sha2_256(b'test')), transactions=[], miner_address=alice_xmss.address) block.set_nonces(mining_nonce=5, extra_nonce=4) mining_blob = block.mining_blob self.assertEqual(len(mining_blob), config.dev.mining_blob_size) mining_nonce_bytes = mining_blob[config.dev.mining_nonce_offset:config. dev.mining_nonce_offset + 4] extra_nonce_bytes = mining_blob[config.dev.extra_nonce_offset:config. dev.extra_nonce_offset + 8] mining_nonce = int.from_bytes(mining_nonce_bytes, byteorder='big', signed=False) extra_nonce = int.from_bytes(extra_nonce_bytes, byteorder='big', signed=False) self.assertEqual(mining_nonce, 5) self.assertEqual(extra_nonce, 4)
def test_verify_blob(self): alice_xmss = get_alice_xmss() block = Block.create(block_number=5, prevblock_headerhash=bytes(sha2_256(b'test')), transactions=[], miner_address=alice_xmss.address) mining_blob = block.mining_blob self.assertTrue(block.blockheader.verify_blob(mining_blob))
def _process_XMSS(self, txfrom, txhash, xmss): self.ots_key = xmss.get_index() self.pubhash = self.generate_pubhash(xmss.pk(), self.ots_key) self.txhash = sha2_256(txhash + self.pubhash) self.txfrom = txfrom self.PK = xmss.pk() self.signature = xmss.SIGN(self.txhash)
def dilithium_sign(self, msg_id, ttl, ttr, enc_aes256_symkey, nonce, sender_dilithium): ephemeral_hash = (msg_id + str(ttl).encode() + str(ttr).encode() + enc_aes256_symkey + self.addr_from + str(self.prf512_seed).encode() + str(nonce).encode() + self.data) self._data.dilithium_signature = bytes( sender_dilithium.sign(bytes(sha2_256(ephemeral_hash))))
def setUp(self): self.block = Block.create(dev_config=config.dev, block_number=5, prev_headerhash=bytes(sha2_256(b'test')), prev_timestamp=10, transactions=[], miner_address=alice.address, seed_height=0, seed_hash=None)
def calc_addr_ots_hash(tx): addr = tx.master_addr if not addr: addr = bytes(QRLHelper.getAddress(tx.PK)) addr_ots_hash = sha2_256( addr + tx.ots_key.to_bytes(8, byteorder='big', signed=False)) return addr_ots_hash
def _get_hashable_bytes(self): """ This method should return bytes that are to be hashed and represent the transaction :return: hashable bytes :rtype: bytes """ # FIXME: Avoid all intermediate conversions tmptxhash = str2bin(bin2hstr(sha2_256(bytes(self.subtype)))) return bytes(tmptxhash)
def get_message_hash(self): msg_hash = ( str(self._data.msg_id).encode() + str(self._data.ttl).encode() + str(self._data.ttr).encode() + str(self._data.nonce).encode() + self._data.channel.enc_aes256_symkey + self._data.payload ) return bytes(sha2_256(msg_hash))
def mining_hash(self): data = "{0}{1}{2}{3}{4}{5}{6}{7}".format(self.PK, self.epoch, self.block_reward, self.fee_reward, self.timestamp, self.block_number, self.prev_blockheaderhash, self.tx_merkle_root) return bytes(sha2_256(str2bin(data)))
def check_sha_result(self, data_text, expected): hex_in_before = pyqrllib.bin2hstr(pyqrllib.str2bin(data_text)) data_out = pyqrllib.sha2_256(pyqrllib.str2bin(data_text)) # This is just to keep as an example. Things could be compared without converting to hex hex_in = pyqrllib.bin2hstr(pyqrllib.str2bin(data_text)) hex_out = pyqrllib.bin2hstr(data_out) self.assertEqual(hex_in_before, hex_in) self.assertEqual(expected, hex_out)
def test_sign(): dev = LedgerQRL() dev.connect() signature = dev.sign(get_tx(0)) assert signature is not None # verify signature hashed_msg = sha2_256(get_tx(0)[2 + 39:]) pk = dev.pk_raw assert XmssFast.verify(hashed_msg, signature, pk) == True
def generate_headerhash(self): # FIXME: This is using strings... fix data = "{0}{1}{2}{3}{4}{5}{6}{7}{8}".format(self.PK, self.epoch, self.block_reward, self.fee_reward, self.timestamp, self.block_number, self.prev_blockheaderhash, self.tx_merkle_root, self.mining_nonce) return bytes(sha2_256(str2bin(data)))
def sha256(message): """ :param message: :type message: Union[str, unicode] :return: :rtype: str >>> bin2hstr(sha256(b"test")) '9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08' >>> bin2hstr(sha256(b"another string")) '81e7826a5821395470e5a2fed0277b6a40c26257512319875e1d70106dcb1ca0' """ return sha2_256(message)
def dilithium_sign(self, msg_id, ttl, ttr, enc_aes256_symkey, nonce, sender_dilithium): ephemeral_hash = ( msg_id + str(ttl).encode() + str(ttr).encode() + enc_aes256_symkey + self.addr_from + str(self.prf512_seed).encode() + str(nonce).encode() + self.data ) self._data.dilithium_signature = bytes(sender_dilithium.sign(bytes(sha2_256(ephemeral_hash))))
def test_set_mining_nonce_from_blob(self): alice_xmss = get_alice_xmss() block = Block.create(block_number=5, prevblock_headerhash=bytes(sha2_256(b'test')), transactions=[], miner_address=alice_xmss.address) current_mining_nonce = block.mining_nonce current_headerhash = block.headerhash mining_blob = block.mining_blob block.blockheader.set_mining_nonce_from_blob(mining_blob) self.assertEqual(block.blockheader.mining_nonce, current_mining_nonce) self.assertEqual(block.headerhash, current_headerhash) self.assertEqual(block.blockheader.mining_blob, mining_blob)
def sha256(message: bytes) -> bytes: """ :param message: :type message: Union[str, unicode] :return: :rtype: str >>> bin2hstr(sha256(b"test")) '9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08' >>> bin2hstr(sha256(b"another string")) '81e7826a5821395470e5a2fed0277b6a40c26257512319875e1d70106dcb1ca0' """ return bytes(sha2_256(message))
def test_update_mining_address(self): alice_xmss = get_alice_xmss() bob_xmss = get_bob_xmss() block = Block.create(block_number=5, prev_headerhash=bytes(sha2_256(b'test')), prev_timestamp=10, transactions=[], miner_address=alice_xmss.address) block.update_mining_address(mining_address=bob_xmss.address) coinbase_tx = Transaction.from_pbdata(block.transactions[0]) self.assertTrue(isinstance(coinbase_tx, CoinBase)) self.assertEqual(coinbase_tx.addr_to, bob_xmss.address) hashedtransactions = [] for tx in block.transactions: hashedtransactions.append(tx.transaction_hash) self.assertEqual(block.blockheader.tx_merkle_root, merkle_tx_hash(hashedtransactions))
def test_verify_known_sig(): tx = get_tx(0)[2 + 39:] # need to skip metadata and source address msg = sha2_256(tx) pk = hstr2bin( "000400" "106D0856A5198967360B6BDFCA4976A433FA48DEA2A726FDAF30EA8CD3FAD211" "3191DA3442686282B3D5160F25CF162A517FD2131F83FBF2698A58F9C46AFC5D") sig = hstr2bin(expected_sig_tc0_idx0) # Generate identical tree to confirm signature xmss = XmssFast([0] * 48, 8, SHA2_256) pk2 = xmss.getPK() sig2 = xmss.sign(msg) assert bin2hstr(pk2).upper() == bin2hstr(pk).upper() assert XmssFast.verify(msg, sig2, pk) == True assert bin2hstr(sig2).upper() == bin2hstr(sig).upper() assert XmssFast.verify(msg, sig, pk) == True
def gen_blocks(block_count, state, miner_address): blocks = [] with mock.patch('qrl.core.misc.ntp.getTime') as time_mock: time_mock.return_value = 1615270948 prev_hash = bytes(sha2_256(b'test')) addresses_state = dict() for i in range(0, block_count): if i == 0: block = GenesisBlock() for genesis_balance in GenesisBlock().genesis_balance: bytes_addr = genesis_balance.address addresses_state[bytes_addr] = AddressState.get_default( bytes_addr) addresses_state[ bytes_addr]._data.balance = genesis_balance.balance else: block = Block.create(block_number=i, prevblock_headerhash=prev_hash, transactions=[], miner_address=miner_address) addresses_set = state.prepare_address_list(block) for address in addresses_set: addresses_state[address] = state.get_address_state(address) for tx_protobuf in block.transactions: tx = Transaction.from_pbdata(tx_protobuf) tx.apply_on_state(addresses_state) block.set_nonces(10, 0) blocks.append(block) metadata = BlockMetadata() metadata.set_block_difficulty(256) state.put_block_metadata(block.headerhash, metadata, None) state.put_block(block, None) bm = qrl_pb2.BlockNumberMapping( headerhash=block.headerhash, prev_headerhash=block.prev_headerhash) state.put_block_number_mapping(block.block_number, bm, None) state.update_mainchain_height(block.block_number, None) state.put_addresses_state(addresses_state) prev_hash = bytes(block.headerhash) return blocks
def gen_blocks(block_count, state, miner_address): blocks = [] with mock.patch('qrl.core.misc.ntp.getTime') as time_mock: time_mock.return_value = 1615270948 prev_hash = bytes(sha2_256(b'test')) for i in range(0, block_count): block = Block.create(block_number=i, prevblock_headerhash=prev_hash, transactions=[], miner_address=miner_address) block.set_nonces(10, 0) blocks.append(block) metadata = BlockMetadata() metadata.set_block_difficulty(256) state.put_block_metadata(block.headerhash, metadata, None) state.put_block(block, None) prev_hash = bytes(block.headerhash) return blocks
def setUp(self): self.alice = get_alice_xmss() self.bob = get_bob_xmss() self.slave = get_slave_xmss() self.tx1 = TransferTransaction.create(addrs_to=[self.bob.address], amounts=[10], fee=1, xmss_pk=self.alice.pk) self.tx2 = TransferTransaction.create(addrs_to=[self.bob.address], amounts=[10], fee=1, xmss_pk=self.slave.pk, master_addr=self.alice.address) # self.tx1 = Mock(autospec=TransferTransaction, addrs_to=[self.bob.address], amounts=[10], fee=1, # xmss_pk=self.alice.pk) # self.tx2 = Mock(autospec=TransferTransaction, addrs_to=[self.bob.address], amounts=[10], fee=1, # xmss_pk=self.slave.pk, master_addr=self.alice.address) self.tx1._data.nonce = 3 self.tx2._data.nonce = 6 self.tx1.sign(self.alice) self.tx2.sign(self.slave) self.block_attrs = { "block_number": 5, "prev_headerhash": bytes(sha2_256(b'test')), "prev_timestamp": 10, "transactions": [self.tx1, self.tx2], "miner_address": self.alice.address } self.alice_addrstate_attrs = { 'nonce': 2, 'ots_key_reuse.return_value': False } self.slave_addrstate_attrs = { 'nonce': 5, 'ots_key_reuse.return_value': False }
def setUp(self): with set_qrl_dir('no_data'): self.state = State() self.chain_manager = ChainManager(self.state) self.alice = get_alice_xmss() self.bob = get_bob_xmss() self.slave = get_slave_xmss() self.tx1 = TransferTransaction.create(addrs_to=[self.bob.address], amounts=[10], message_data=None, fee=1, xmss_pk=self.alice.pk) self.tx2 = TransferTransaction.create(addrs_to=[self.bob.address], amounts=[10], message_data=None, fee=1, xmss_pk=self.slave.pk, master_addr=self.alice.address) self.tx1._data.nonce = 3 self.tx2._data.nonce = 6 self.tx1.sign(self.alice) self.tx2.sign(self.slave) self.block_attrs = { "dev_config": config.dev, "block_number": 5, "prev_headerhash": bytes(sha2_256(b'test')), "prev_timestamp": 10, "transactions": [self.tx1, self.tx2], "miner_address": self.alice.address, "seed_height": 0, "seed_hash": None, } self.coinbase_addrstate_attrs = OptimizedAddressState.get_default(config.dev.coinbase_address) self.coinbase_addrstate_attrs.update_balance(None, int(config.dev.coin_remaining_at_genesis * config.dev.shor_per_quanta)) self.bob_addrstate_attrs = OptimizedAddressState.get_default(self.bob.address) self.bob_addrstate_attrs.update_balance(None, 20) self.alice_addrstate_attrs = OptimizedAddressState.get_default(self.alice.address) self.alice_addrstate_attrs.update_balance(None, 100) self.alice_addrstate_attrs.pbdata.nonce = 2 self.slave_addrstate_attrs = OptimizedAddressState.get_default(self.slave.address) self.slave_addrstate_attrs.pbdata.nonce = 5
def calculate_txhash(self): return bytes(sha2_256(self._get_hashable_bytes() + self.pubhash))
def _get_txhash(self, tmptxhash, pubhash): # FIXME: Review this. Leon? self.pubhash = pubhash return sha2_256(tmptxhash + self.pubhash)
def _generate_tx_merkle_root(transactions): result = str2bin("".join(tx.hash for tx in transactions)) return bin2hstr(sha2_256(result))