def create(self, chain, reveal_hash, vote_hash, last_block_number=-1): # FIXME: probably this should turn into a constructor reveal_hash = reveal_hash vote_hash = vote_hash data = None if last_block_number == -1: data = chain.block_chain_buffer.get_last_block( ) # m_get_last_block() else: data = chain.block_chain_buffer.get_block_n(last_block_number) last_block_number = data.blockheader.blocknumber prev_blockheaderhash = data.blockheader.headerhash hashedtransactions = [] self.transactions = [None] fee_reward = 0 for tx in chain.transaction_pool: if tx.subtype == TX_SUBTYPE_TX: fee_reward += tx.fee hashedtransactions.append(tx.txhash) self.transactions.append(tx) # copy memory rather than sym link self.duplicate_transactions = [] for tx in chain.duplicate_tx_pool: self.duplicate_transactions.append(chain.duplicate_tx_pool[tx]) if not hashedtransactions: hashedtransactions = [sha256('')] hashedtransactions = merkle_tx_hash(hashedtransactions) self.blockheader = BlockHeader() self.blockheader.create(chain=chain, blocknumber=last_block_number + 1, reveal_hash=reveal_hash, vote_hash=vote_hash, prev_blockheaderhash=prev_blockheaderhash, hashedtransactions=hashedtransactions, fee_reward=fee_reward) coinbase_tx = CoinBase().create( self.blockheader, chain.block_chain_buffer.get_slave_xmss(last_block_number + 1)) # coinbase_tx = CoinBase().create(self.blockheader.block_reward + self.blockheader.fee_reward, # self.blockheader.headerhash, # chain.wallet.address_bundle[0].xmss.get_address(), # chain.block_chain_buffer.get_slave_xmss(last_block_number + 1)) self.transactions[0] = coinbase_tx sv_list = chain.block_chain_buffer.get_stake_validators_list( last_block_number + 1).sv_list coinbase_tx.nonce = sv_list[chain.mining_address].nonce + 1
def test_from_txdict(self): tx = CoinBase.create(self.mock_blockheader, self.alice) self.assertIsInstance(tx, CoinBase) # Test that common Transaction components were copied over. self.assertEqual(0, tx.nonce) self.assertEqual( b'Q223bc5e5b78edfd778b1bf72702061cc053010711ffeefb9d969318be5d7b86b021b73c2', tx.txfrom) self.assertEqual( '3c523f9cc26f800863c003524392806ff6df373acb4d47cc607b62365fe4ab77' 'cf3018d321df7dcb653c9f7968673e43d12cc26e3461b5f425fd5d977400fea5', bin2hstr(tx.PK)) self.assertEqual(11, tx.ots_key) self.assertEqual(b'', tx.signature) self.assertEqual( '1a1274bedfc53287853c3aea5b8a93d64f2e4dff23ddbf96e52c8033f0107154', bin2hstr(tx.pubhash)) self.assertEqual( 'a62a1ef7faedf82aa1f562ff08a8b3cc7b3c4d4f45ef6c7653bf074df2cda122', bin2hstr(tx.txhash)) # Test that specific content was copied over. self.assertEqual( b'Q223bc5e5b78edfd778b1bf72702061cc053010711ffeefb9d969318be5d7b86b021b73c2', tx.txto) self.assertEqual(tx.amount, 90)
def create(staking_address: bytes, block_number: int, reveal_hash: bytes, prevblock_headerhash: bytes, transactions: list, duplicate_transactions: OrderedDict, vote: VoteMetadata, signing_xmss: XMSS, nonce: int): block = Block() block._data.transactions.extend([qrl_pb2.Transaction() ]) # FIXME: Empty for coinbase? # Process transactions hashedtransactions = [] fee_reward = 0 for tx in transactions: if tx.subtype == qrl_pb2.Transaction.TRANSFER: fee_reward += tx.fee hashedtransactions.append(tx.txhash) block._data.transactions.extend( [tx.pbdata]) # copy memory rather than sym link if not hashedtransactions: hashedtransactions = [sha256(b'')] txs_hash = merkle_tx_hash( hashedtransactions) # FIXME: Find a better name, type changes for tx in duplicate_transactions.values( ): # TODO: Add merkle hash for dup txn block._data.duplicate_transactions.extend([tx.pbdata]) for staker in vote.stake_validator_vote: # TODO: Add merkle hash for vote block._data.vote.extend([vote.stake_validator_vote[staker].pbdata]) tmp_blockheader = BlockHeader.create( staking_address=staking_address, blocknumber=block_number, reveal_hash=reveal_hash, prev_blockheaderhash=prevblock_headerhash, hashedtransactions=txs_hash, fee_reward=fee_reward) block._data.header.MergeFrom(tmp_blockheader.pbdata) # Prepare coinbase tx coinbase_tx = CoinBase.create(tmp_blockheader, signing_xmss) coinbase_tx.pbdata.nonce = nonce coinbase_tx.sign(signing_xmss) # Sign after nonce has been set # Replace first tx block._data.transactions[0].CopyFrom(coinbase_tx.pbdata) return block
def test_from_txdict(self): amount = self.mock_blockheader.block_reward + self.mock_blockheader.fee_reward tx = CoinBase.create(amount, self.alice.address, self.mock_blockheader.block_number) self.assertIsInstance(tx, CoinBase) # Test that common Transaction components were copied over. self.assertEqual(self.mock_blockheader.block_number + 1, tx.nonce) self.assertEqual( '010300a1da274e68c88b0ccf448e0b1916fa789b01eb2ed4e9ad565ce264c9390782a9c61ac02f', bin2hstr(tx.addr_to)) self.assertEqual( 'c7f3e1e092e70f49a943a162de8b110899b60ab1dafd0c72625fba6fc1adcd01', bin2hstr(tx.txhash)) self.assertEqual(tx.amount, 90)
def create(block_number: int, prev_block_headerhash: bytes, prev_block_timestamp: int, transactions: list, miner_address: bytes): block = Block() # Process transactions hashedtransactions = [] fee_reward = 0 for tx in transactions: fee_reward += tx.fee # Prepare coinbase tx total_reward_amount = BlockHeader.block_reward_calc( block_number) + fee_reward coinbase_tx = CoinBase.create(total_reward_amount, miner_address, block_number) hashedtransactions.append(coinbase_tx.txhash) block._data.transactions.extend([coinbase_tx.pbdata ]) # copy memory rather than sym link for tx in transactions: hashedtransactions.append(tx.txhash) block._data.transactions.extend( [tx.pbdata]) # copy memory rather than sym link txs_hash = merkle_tx_hash( hashedtransactions) # FIXME: Find a better name, type changes tmp_blockheader = BlockHeader.create( blocknumber=block_number, prev_block_headerhash=prev_block_headerhash, prev_block_timestamp=prev_block_timestamp, hashedtransactions=txs_hash, fee_reward=fee_reward) block.blockheader = tmp_blockheader block._data.header.MergeFrom(tmp_blockheader.pbdata) block.set_nonces(0, 0) return block
def create(block_number: int, prevblock_headerhash: bytes, transactions: list, signing_xmss: XMSS, master_address: bytes, nonce: int): block = Block() block._data.transactions.extend([qrl_pb2.Transaction() ]) # FIXME: Empty for coinbase? # Process transactions hashedtransactions = [] fee_reward = 0 for tx in transactions: fee_reward += tx.fee hashedtransactions.append(tx.txhash) block._data.transactions.extend( [tx.pbdata]) # copy memory rather than sym link if not hashedtransactions: hashedtransactions = [sha256(b'')] txs_hash = merkle_tx_hash( hashedtransactions) # FIXME: Find a better name, type changes tmp_blockheader = BlockHeader.create( blocknumber=block_number, PK=signing_xmss.pk, prev_blockheaderhash=prevblock_headerhash, hashedtransactions=txs_hash, fee_reward=fee_reward) block._data.header.MergeFrom(tmp_blockheader.pbdata) # Prepare coinbase tx coinbase_tx = CoinBase.create(tmp_blockheader, signing_xmss, master_address) coinbase_tx.pbdata.nonce = nonce coinbase_tx.sign(signing_xmss) # Sign after nonce has been set # Replace first tx block._data.transactions[0].CopyFrom(coinbase_tx.pbdata) return block
def block_params(self, msg_hash: bytes, block): if msg_hash not in self.requested_hash: return False params = self.requested_hash[msg_hash].params coinbase_tx = CoinBase.from_pbdata(block.transactions[0]) if coinbase_tx.txfrom != params.stake_selector: return False if block.block_number != params.block_number: return False if block.prev_blockheaderhash != params.prev_headerhash: return False if block.reveal_hash != params.reveal_hash: return False return True
def create(mining_nonce: int, block_number: int, prevblock_headerhash: bytes, transactions: list, signing_xmss: XMSS, master_address: bytes, nonce: int): block = Block() block._data.transactions.extend([qrl_pb2.Transaction()]) # FIXME: Empty for coinbase? # Process transactions hashedtransactions = [] fee_reward = 0 for tx in transactions: fee_reward += tx.fee hashedtransactions.append(tx.txhash) block._data.transactions.extend([tx.pbdata]) # copy memory rather than sym link if not hashedtransactions: hashedtransactions = [sha256(b'')] txs_hash = merkle_tx_hash(hashedtransactions) # FIXME: Find a better name, type changes tmp_blockheader = BlockHeader.create(blocknumber=block_number, mining_nonce=mining_nonce, PK=signing_xmss.pk(), prev_blockheaderhash=prevblock_headerhash, hashedtransactions=txs_hash, fee_reward=fee_reward) block._data.header.MergeFrom(tmp_blockheader.pbdata) # Prepare coinbase tx coinbase_tx = CoinBase.create(tmp_blockheader, signing_xmss, master_address) coinbase_tx.pbdata.nonce = nonce coinbase_tx.sign(signing_xmss) # Sign after nonce has been set # Replace first tx block._data.transactions[0].CopyFrom(coinbase_tx.pbdata) return block
def test_from_txdict(self): tx = CoinBase.create(self.mock_blockheader, self.alice, self.alice.address) tx.sign(self.alice) self.assertIsInstance(tx, CoinBase) # Test that common Transaction components were copied over. self.assertEqual(0, tx.nonce) self.assertEqual( '010300a1da274e68c88b0ccf448e0b1916fa789b01eb2ed4e9ad565ce264c9390782a9c61ac02f', bin2hstr(tx.addr_to)) self.assertEqual( '01030038ea6375069f8272cc1a6601b3c76c21519455603d370036b97c779ada356' '5854e3983bd564298c49ae2e7fa6e28d4b954d8cd59398f1225b08d6144854aee0e', bin2hstr(tx.PK)) self.assertEqual(11, tx.ots_key) self.assertEqual(test_signature_CoinBase, bin2hstr(tx.signature)) self.assertEqual( '92f50f236b2061e12e2bd05616d4334d3956cb1af5287f4bc0afc06280b695f5', bin2hstr(tx.txhash)) self.assertEqual(tx.amount, 90)
def test_to_json(self): amount = self.mock_blockheader.block_reward + self.mock_blockheader.fee_reward tx = CoinBase.create(amount, self.alice.address, self.mock_blockheader.block_number) txjson = tx.to_json() self.assertEqual(json.loads(test_json_CoinBase), json.loads(txjson))
def test_create(self): amount = self.mock_blockheader.block_reward + self.mock_blockheader.fee_reward tx = CoinBase.create(amount, self.alice.address, self.mock_blockheader.block_number) self.assertIsInstance(tx, CoinBase)
def _search_address(self, address): addr = {'transactions': []} txnhash_added = set() # FIXME: breaking encapsulation and accessing DB/cache directly from API if not self.factory.state.state_address_used(address): addr['status'] = 'error' addr['error'] = 'Address not found' addr['parameter'] = address return json_print_telnet(addr) # FIXME: This is a duplicate of balance # FIXME: breaking encapsulation and accessing DB/cache directly from API nonce, balance, pubhash_list = self.factory.state.state_get_address( address) addr['state'] = {} addr['state']['address'] = address addr['state']['balance'] = self._format_qrlamount(balance) addr['state']['nonce'] = nonce for s in self.factory.state.stake_list_get(): if address == s[0]: addr['stake'] = {} addr['stake']['selector'] = s[2] # pubhashes used could be put here.. tmp_transactions = [] for tx in self.factory.chain.transaction_pool: if tx.subtype not in (TX_SUBTYPE_TX, TX_SUBTYPE_COINBASE): continue if tx.txto == address or tx.txfrom == address: logger.info('%s found in transaction pool', address) tmp_txn = { 'subtype': tx.subtype, 'txhash': bin2hstr(tx.txhash), 'block': 'unconfirmed', 'amount': self._format_qrlamount(tx.amount), 'nonce': tx.nonce, 'ots_key': tx.ots_key, 'txto': tx.txto, 'txfrom': tx.txfrom, 'timestamp': 'unconfirmed' } if tx.subtype == TX_SUBTYPE_TX: tmp_txn['fee'] = self._format_qrlamount(tx.fee) tmp_txn.subtype = Transaction.tx_id_to_name(tx.subtype) tmp_transactions.append(tmp_txn) txnhash_added.add(tx.txhash) addr['transactions'] = tmp_transactions my_txn = [] try: my_txn = self.factory.state.db.get('txn_' + address) except: pass for txn_hash in my_txn: txn_metadata = self.factory.state.db.get(txn_hash) dict_txn_metadata = json.loads(txn_metadata[0]) if dict_txn_metadata['subtype'] == TX_SUBTYPE_TX: tx = SimpleTransaction().json_to_transaction(txn_metadata[0]) elif dict_txn_metadata['subtype'] == TX_SUBTYPE_COINBASE: tx = CoinBase().json_to_transaction(txn_metadata[0]) if (tx.txto == address or tx.txfrom == address) and tx.txhash not in txnhash_added: logger.info('%s found in block %s', address, str(txn_metadata[1])) tmp_txn = { 'subtype': tx.subtype, 'txhash': bin2hstr(tx.txhash), 'block': txn_metadata[1], 'timestamp': txn_metadata[2], 'amount': self._format_qrlamount(tx.amount), 'nonce': tx.nonce, 'ots_key': tx.ots_key, 'txto': tx.txto, 'txfrom': tx.txfrom } if tx.subtype == TX_SUBTYPE_TX: tmp_txn['fee'] = self._format_qrlamount(tx.fee) tmp_txn['subtype'] = Transaction.tx_id_to_name( tmp_txn['subtype']) addr['transactions'].append(tmp_txn) txnhash_added.add(tx.txhash) if len(addr['transactions']) > 0: addr['state']['transactions'] = len(addr['transactions']) if addr == {'transactions': {}}: addr = { 'status': 'error', 'error': 'address not found', 'method': 'address', 'parameter': address } else: addr['status'] = 'ok' return json_print_telnet(addr)
def test_to_json(self): tx = CoinBase.create(self.mock_blockheader, self.alice, self.alice.address) txjson = tx.to_json() self.assertEqual(json.loads(test_json_CoinBase), json.loads(txjson))
def test_create(self): tx = CoinBase.create(self.mock_blockheader, self.alice, self.alice.address) self.assertIsInstance(tx, CoinBase)