def test_from_json(self): tx = Transaction.from_json(test_json_Token) tx.sign(self.alice) self.assertIsInstance(tx, TokenTransaction) # Test that common Transaction components were copied over. self.assertEqual( '010300a1da274e68c88b0ccf448e0b1916fa789b01eb2ed4e9ad565ce264c9390782a9c61ac02f', bin2hstr(tx.addr_from)) self.assertEqual( '01030038ea6375069f8272cc1a6601b3c76c21519455603d370036b97c779ada356' '5854e3983bd564298c49ae2e7fa6e28d4b954d8cd59398f1225b08d6144854aee0e', bin2hstr(tx.PK)) self.assertEqual(b'QRL', tx.symbol) self.assertEqual(b'Quantum Resistant Ledger', tx.name) self.assertEqual( '010317463dcd581b679b4754f46c6425125489a2826894e3c42a590efb6806450ce6bf52716c', bin2hstr(tx.owner)) self.assertEqual( 'ff84da605e9c9cd04d68503be7922110b4cc147837f8687ad18aa54b7bc5632d', bin2hstr(tx.txhash)) self.assertEqual(10, tx.ots_key) self.assertEqual(test_signature_Token, bin2hstr(tx.signature)) total_supply = 0 for initial_balance in tx.initial_balances: total_supply += initial_balance.amount self.assertEqual(600000000, total_supply) self.assertEqual(1, tx.fee)
def test_from_json(self): tx = Transaction.from_json(test_json_Simple) tx.sign(self.alice) self.assertIsInstance(tx, TransferTransaction) # Test that common Transaction components were copied over. self.assertEqual(0, tx.nonce) self.assertEqual( '010300a1da274e68c88b0ccf448e0b1916fa789b01eb2ed4e9ad565ce264c9390782a9c61ac02f', bin2hstr(tx.addr_from)) self.assertEqual( '01030038ea6375069f8272cc1a6601b3c76c21519455603d370036b97c779ada356' '5854e3983bd564298c49ae2e7fa6e28d4b954d8cd59398f1225b08d6144854aee0e', bin2hstr(tx.PK)) self.assertEqual( '554f546305d4aed6ec71c759942b721b904ab9d65eeac3c954c08c652181c4e8', bin2hstr(tx.txhash)) self.assertEqual(10, tx.ots_key) self.assertEqual(test_signature_Simple, bin2hstr(tx.signature)) # Test that specific content was copied over. self.assertEqual( '0103001d65d7e59aed5efbeae64246e0f3184d7c42411421eb385ba30f2c1c005a85ebc4419cfd', bin2hstr(tx.addrs_to[0])) self.assertEqual(100, tx.total_amount) self.assertEqual(1, tx.fee)
def test_from_json(self): tx = Transaction.from_json(test_json_Simple) self.assertIsInstance(tx, TransferTransaction) self.assertEqual(tx.subtype, qrl_pb2.Transaction.TRANSFER) # 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( '986299314d1489f0c23d70b689639c9c0059588563582cb7b21439b61583a5c0', bin2hstr(tx.txhash)) self.assertEqual(10, tx.ots_key) self.assertEqual(b'', tx.signature) self.assertEqual( 'e2e3d8b08e65b25411af455eb9bb402827fa7b600fa0b36011d62e26899dfa05', bin2hstr(tx.pubhash)) # Test that specific content was copied over. self.assertEqual( b'Qfd5d64455903b8e500a14cafb1c4ea95a1f97562aaaa24d83e5b9dc3861a47386ce9ad15', tx.txto) self.assertEqual(100, tx.amount) self.assertEqual(1, tx.fee)
def test_from_json(self): tx = Transaction.from_json(test_json_TransferToken) tx.sign(self.alice) self.assertIsInstance(tx, TransferTokenTransaction) # Test that common Transaction components were copied over. self.assertEqual( '010300a1da274e68c88b0ccf448e0b1916fa789b01eb2ed4e9ad565ce264c9390782a9c61ac02f', bin2hstr(tx.addr_from)) self.assertEqual( '01030038ea6375069f8272cc1a6601b3c76c21519455603d370036b97c779ada356' '5854e3983bd564298c49ae2e7fa6e28d4b954d8cd59398f1225b08d6144854aee0e', bin2hstr(tx.PK)) self.assertEqual(b'000000000000000', tx.token_txhash) self.assertEqual(200000, tx.total_amount) self.assertEqual( '390b159b34cffd29d4271a19679ff227df2ccd471078f177a7b58ca5f5d999f0', bin2hstr(tx.txhash)) self.assertEqual(10, tx.ots_key) # z = bin2hstr(tx.signature) # print('"', end='') # for i in range(len(z)): # print(z[i], end='') # if (i + 1) % 64 == 0: # print('" \\', end='') # print('') # print(' ' * len('test_signature_TransferToken = '), end='') # print('"', end='') self.assertEqual(test_signature_TransferToken, bin2hstr(tx.signature)) self.assertEqual(1, tx.fee)
def test_from_json(self): tx = Transaction.from_json(test_json_Stake) self.assertIsInstance(tx, StakeTransaction) # 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( '06b0fcaf2e2ca69299a8a2ce32f0c05cd14cd61e25a9e324ffad8abc5a88aa7f', bin2hstr(tx.txhash)) self.assertEqual(10, tx.ots_key) self.assertEqual(b'', tx.signature) self.assertEqual( 'e2e3d8b08e65b25411af455eb9bb402827fa7b600fa0b36011d62e26899dfa05', bin2hstr(tx.pubhash)) # Test that specific content was copied over. self.assertEqual(2, tx.activation_blocknumber) self.assertEqual( '380793debf8f72e70ef7351ee5005df6c7ca2320ff49e0ead0c40b19c7bb1cc1' '496e19a482c06350bdc054e4ed52a24ec8c994c44f9341d01190a81ab093ade8', bin2hstr(tx.slave_public_key)) self.assertEqual( '1f93603db53bfad5c92390f735d0cbb8617b4ab8214ae91c5664a3d1e9b009c8', bin2hstr(tx.hash))
def test_from_json(self): tx = Transaction.from_json(test_json_Token) self.assertIsInstance(tx, TokenTransaction) self.assertEqual(tx.subtype, qrl_pb2.Transaction.TOKEN) # Test that common Transaction components were copied over. self.assertEqual( b'Q223bc5e5b78edfd778b1bf72702061cc053010711ffeefb9d969318be5d7b86b021b73c2', tx.txfrom) self.assertEqual( '3c523f9cc26f800863c003524392806ff6df373acb4d47cc607b62365fe4ab77' 'cf3018d321df7dcb653c9f7968673e43d12cc26e3461b5f425fd5d977400fea5', bin2hstr(tx.PK)) self.assertEqual(b'QRL', tx.symbol) self.assertEqual(b'Quantum Resistant Ledger', tx.name) self.assertEqual( b'Q223bc5e5b78edfd778b1bf72702061cc053010711ffeefb9d969318be5d7b86b021b73c2', tx.owner) self.assertEqual( 'f6d115628207da9c1bffec208aea7fb196d39433062b18f43619106c43cff4e9', bin2hstr(tx.txhash)) self.assertEqual(10, tx.ots_key) self.assertEqual(b'', tx.signature) self.assertEqual( 'e2e3d8b08e65b25411af455eb9bb402827fa7b600fa0b36011d62e26899dfa05', bin2hstr(tx.pubhash)) total_supply = 0 for initial_balance in tx.initial_balances: total_supply += initial_balance.amount self.assertEqual(600000000, total_supply) self.assertEqual(1, tx.fee)
def test_from_json(self): tx = Transaction.from_json(test_json_TransferToken) self.assertIsInstance(tx, TransferTokenTransaction) self.assertEqual(tx.subtype, qrl_pb2.Transaction.TRANSFERTOKEN) # Test that common Transaction components were copied over. self.assertEqual( b'Q223bc5e5b78edfd778b1bf72702061cc053010711ffeefb9d969318be5d7b86b021b73c2', tx.txfrom) self.assertEqual( '3c523f9cc26f800863c003524392806ff6df373acb4d47cc607b62365fe4ab77' 'cf3018d321df7dcb653c9f7968673e43d12cc26e3461b5f425fd5d977400fea5', bin2hstr(tx.PK)) self.assertEqual(b'000000000000000', tx.token_txhash) self.assertEqual(200000, tx.amount) self.assertEqual( '712ec52c483d1e513b83fd4d1210fd943903ae88e0c8048058b06d4e28a8727b', bin2hstr(tx.txhash)) self.assertEqual(10, tx.ots_key) self.assertEqual(b'', tx.signature) self.assertEqual( 'e2e3d8b08e65b25411af455eb9bb402827fa7b600fa0b36011d62e26899dfa05', bin2hstr(tx.pubhash)) self.assertEqual(1, tx.fee)
def DT(self, data): """ Duplicate Transaction This function processes whenever a Transaction having subtype DT is received. :return: """ try: duplicate_txn = Transaction.from_json(data) except Exception as e: logger.error('DT rejected') logger.exception(e) self.transport.loseConnection() return if not self.factory.master_mr.isRequested( duplicate_txn.get_message_hash(), self): return if duplicate_txn.get_message_hash( ) in self.factory.buffered_chain.tx_pool.duplicate_tx_pool: return # TODO: State validate for duplicate_txn is pending if duplicate_txn.validate(): self.factory.buffered_chain.tx_pool.add_tx_to_duplicate_pool( duplicate_txn) else: logger.debug('>>>Invalid DT txn %s', bin2hstr(duplicate_txn.get_message_hash())) return self.factory.register_and_broadcast('DT', duplicate_txn.get_message_hash(), duplicate_txn.to_json())
def get_tx_metadata(db, state_code, txhash: bytes): try: tx_metadata = db.get(str(state_code) + bin2hstr(txhash)) except Exception: return None if tx_metadata is None: return None txn_json, block_number, _ = tx_metadata return Transaction.from_json(txn_json), block_number
def get_tx_metadata(self, txhash: bytes): try: tx_metadata = self._db.get(bin2hstr(txhash)) except Exception: return None if tx_metadata is None: return None txn_json, block_number, _ = tx_metadata return Transaction.from_json(txn_json), block_number
def valid_mining_permission(self): if self._master_address == self._mining_xmss.address: return True addr_state = self.state.get_address(self._master_address) access_type = addr_state.get_slave_permission(self._mining_xmss.pk) if access_type == -1: logger.warning('Slave is not authorized yet for mining') logger.warning('Added Slave Txn') slave_tx = Transaction.from_json(self._slaves[2]) self._add_unprocessed_txn_fn(slave_tx, None) return None return True
def valid_mining_permission(self): if self._master_address == self._mining_xmss.get_address(): return True addr_state = self.state.get_address(self._master_address) access_type = addr_state.get_slave_permission(self._mining_xmss.pk()) if access_type == -1: logger.warning('Slave is not authorized yet for mining') logger.warning('Added Slave Txn') slave_tx = Transaction.from_json(self._slaves[2]) self._add_unprocessed_txn_fn(slave_tx, None) return None return True
def TT(self, data): """ Vote Transaction This function processes whenever a Transaction having subtype VOTE is received. :return: """ try: message_tx = Transaction.from_json(data) except Exception as e: logger.info( 'Transfer Token Txn rejected - unable to decode serialised data - closing connection' ) logger.exception(e) self.transport.loseConnection() return if not self.factory.master_mr.isRequested( message_tx.get_message_hash(), self): return if message_tx.txhash in self.prev_txpool_hashes or message_tx.txhash in self.factory.buffered_chain.tx_pool.pending_tx_pool_hash: return del self.prev_txpool_hashes[0] self.prev_txpool_hashes.append(message_tx.txhash) # duplicate tx already received, would mess up nonce.. for t in self.factory.buffered_chain.tx_pool.transaction_pool: if message_tx.txhash == t.txhash: return self.factory.buffered_chain.tx_pool.update_pending_tx_pool( message_tx, self) self.factory.master_mr.register('TT', message_tx.get_message_hash(), data) self.factory.broadcast(message_tx.get_message_hash(), 'TT') # FIXME: This is tx processor related.. if not self.factory.txn_processor_running: # FIXME: TxnProcessor breaks tx_pool encapsulation txn_processor = TxnProcessor( buffered_chain=self.factory.buffered_chain, pending_tx_pool=self.factory.buffered_chain.tx_pool. pending_tx_pool, transaction_pool=self.factory.buffered_chain.tx_pool. transaction_pool) task_defer = TxnProcessor.create_cooperate( txn_processor).whenDone() task_defer.addCallback(self.factory.reset_processor_flag) \ .addErrback(self.factory.reset_processor_flag_with_err) self.factory.txn_processor_running = True
def valid_payment_permission(public_stub, master_address_state, payment_xmss, json_slave_txn): access_type = master_address_state.get_slave_permission(payment_xmss.pk) if access_type == -1: tx = Transaction.from_json(json_slave_txn) public_stub.PushTransaction(request=qrl_pb2.PushTransactionReq(transaction_signed=tx.pbdata)) return None if access_type == 0: return True return False
def get_last_txs(self): try: last_txn = self._db.get('last_txn') except: # noqa return [] txs = [] for tx_metadata in last_txn: tx_json, block_num, block_ts = tx_metadata tx = Transaction.from_json(tx_json) txs.append(tx) return txs
def get_last_txs(self): try: last_txn = self._db.get(b'last_txn') except: # noqa return [] txs = [] for tx_metadata in last_txn: tx_json, block_num, block_ts = tx_metadata tx = Transaction.from_json(tx_json) txs.append(tx) return txs
def get_last_txs(db, state_code) -> list: try: last_txn = db.get(state_code + b'last_txn') except: # noqa return [] txs = [] for tx_metadata in last_txn: tx_json, block_num, block_ts = tx_metadata tx = Transaction.from_json(tx_json) txs.append(tx) return txs
def DST(self, data): """ Destake Transaction This function processes whenever a Transaction having subtype DESTAKE is received. :return: """ try: destake_txn = Transaction.from_json(data) except Exception as e: logger.error( 'de stake rejected - unable to decode serialised data - closing connection' ) logger.exception(e) self.transport.loseConnection() return if not self.factory.master_mr.isRequested( destake_txn.get_message_hash(), self): return for t in self.factory.buffered_chain.tx_pool.transaction_pool: if destake_txn.get_message_hash() == t.get_message_hash(): return txfrom = destake_txn.txfrom height = self.factory.buffered_chain.height + 1 stake_validators_tracker = self.factory.buffered_chain.get_stake_validators_tracker( height) if txfrom not in stake_validators_tracker.sv_dict and txfrom not in stake_validators_tracker.future_stake_addresses: logger.debug( 'P2P Dropping destake txn as %s not found in stake validator list', txfrom) return tx_state = self.factory.buffered_chain.get_stxn_state( blocknumber=height, addr=txfrom) if destake_txn.validate() and destake_txn.validate_extended( tx_state=tx_state): self.factory.buffered_chain.tx_pool.add_tx_to_pool(destake_txn) else: logger.debug('>>>Destake %s invalid state validation failed..', txfrom) return self.factory.register_and_broadcast('DST', destake_txn.get_message_hash(), destake_txn.to_json())
def _receive_tx(self, json_tx_obj): try: tx = Transaction.from_json(json_tx_obj) except Exception as e: logger.info( 'tx rejected - unable to decode serialised data - closing connection' ) logger.exception(e) self.transport.loseConnection() return if not self.factory.master_mr.isRequested(tx.get_message_hash(), self): return if tx.txhash in self.prev_txpool_hashes or tx.txhash in self.factory.buffered_chain.tx_pool.pending_tx_pool_hash: return del self.prev_txpool_hashes[0] self.prev_txpool_hashes.append(tx.txhash) # duplicate tx already received, would mess up nonce.. for t in self.factory.buffered_chain.tx_pool.transaction_pool: if tx.txhash == t.txhash: return self.factory.buffered_chain.tx_pool.update_pending_tx_pool(tx, self) self.factory.master_mr.register('TX', tx.get_message_hash(), json_tx_obj) self.factory.broadcast(tx.get_message_hash(), 'TX') # FIXME: This is tx processor related.. if not self.factory.txn_processor_running: # FIXME: TxnProcessor breaks tx_pool encapsulation txn_processor = TxnProcessor( buffered_chain=self.factory.buffered_chain, pending_tx_pool=self.factory.buffered_chain.tx_pool. pending_tx_pool, transaction_pool=self.factory.buffered_chain.tx_pool. transaction_pool) task_defer = TxnProcessor.create_cooperate( txn_processor).whenDone() task_defer.addCallback(self.factory.reset_processor_flag) \ .addErrback(self.factory.reset_processor_flag_with_err) self.factory.txn_processor_running = True
def remove_last_tx(self, block, batch): if len(block.transactions) == 0: return try: last_txn = self._db.get(b'last_txn') except: # noqa return for protobuf_txn in block.transactions: txn = Transaction.from_pbdata(protobuf_txn) i = 0 while i < len(last_txn): tx = Transaction.from_json(last_txn[i][0]) if txn.txhash == tx.txhash: del last_txn[i] break i += 1 self._db.put(b'last_txn', last_txn, batch)
def LT(self, data): """ Receives Lattice Public Key Transaction :param data: :return: """ try: lattice_public_key_txn = Transaction.from_json(data) except Exception as e: logger.error( 'lattice_public_key rejected - unable to decode serialised data - closing connection' ) logger.exception(e) self.transport.loseConnection() return if not self.factory.master_mr.isRequested( lattice_public_key_txn.get_message_hash(), self): return if lattice_public_key_txn.validate(): self.factory.buffered_chain.add_lattice_public_key( lattice_public_key_txn) else: logger.warning( '>>>Lattice Public Key %s invalid state validation failed..', lattice_public_key_txn.hash) return # TODO: This need to be moved to add_block before next hard fork self.factory.buffered_chain.add_lattice_public_key( lattice_public_key_txn) self.factory.register_and_broadcast( 'LT', lattice_public_key_txn.get_message_hash(), lattice_public_key_txn.to_json())
def test_from_json(self): tx = Transaction.from_json(test_json_MessageTransaction) tx.sign(self.alice) self.assertIsInstance(tx, MessageTransaction) # Test that common Transaction components were copied over. self.assertEqual( '010300a1da274e68c88b0ccf448e0b1916fa789b01eb2ed4e9ad565ce264c9390782a9c61ac02f', bin2hstr(tx.addr_from)) self.assertEqual( '01030038ea6375069f8272cc1a6601b3c76c21519455603d370036b97c779ada356' '5854e3983bd564298c49ae2e7fa6e28d4b954d8cd59398f1225b08d6144854aee0e', bin2hstr(tx.PK)) self.assertEqual(b'Test Message', tx.message_hash) self.assertEqual( 'cbe7c40a86e82b8b6ac4e7df812f882183bd85d60f335cd83483d6831e61f4ec', bin2hstr(tx.txhash)) self.assertEqual(10, tx.ots_key) self.assertEqual(test_signature_MessageTransaction, bin2hstr(tx.signature)) self.assertEqual(1, tx.fee)
def test_from_json(self): tx = Transaction.from_json(test_json_Simple) tx.sign(self.alice) self.assertIsInstance(tx, TransferTransaction) # Test that common Transaction components were copied over. self.assertEqual(0, tx.nonce) self.assertEqual( '010300a1da274e68c88b0ccf448e0b1916fa789b01eb2ed4e9ad565ce264c9390782a9c61ac02f', bin2hstr(tx.addr_from)) self.assertEqual( '01030038ea6375069f8272cc1a6601b3c76c21519455603d370036b97c779ada356' '5854e3983bd564298c49ae2e7fa6e28d4b954d8cd59398f1225b08d6144854aee0e', bin2hstr(tx.PK)) self.assertEqual( '536c35bb536d324bd6abd8ebe951b010157b95b8c72ece24d562939930f70a4e', bin2hstr(tx.txhash)) self.assertEqual(10, tx.ots_key) # z = bin2hstr(tx.signature) # print('"', end='') # for i in range(len(z)): # print(z[i], end='') # if (i + 1) % 64 == 0: # print('" \\', end='') # print('') # print('"', end='') self.assertEqual(test_signature_Simple, bin2hstr(tx.signature)) # Test that specific content was copied over. self.assertEqual( '0103001d65d7e59aed5efbeae64246e0f3184d7c42411421eb385ba30f2c1c005a85ebc4419cfd', bin2hstr(tx.addrs_to[0])) self.assertEqual(100, tx.total_amount) self.assertEqual(1, tx.fee)
def test_from_json(self): tx = Transaction.from_json(test_json_TransferToken) tx.sign(self.alice) self.assertIsInstance(tx, TransferTokenTransaction) # Test that common Transaction components were copied over. self.assertEqual( '010300a1da274e68c88b0ccf448e0b1916fa789b01eb2ed4e9ad565ce264c9390782a9c61ac02f', bin2hstr(tx.addr_from)) self.assertEqual( '01030038ea6375069f8272cc1a6601b3c76c21519455603d370036b97c779ada356' '5854e3983bd564298c49ae2e7fa6e28d4b954d8cd59398f1225b08d6144854aee0e', bin2hstr(tx.PK)) self.assertEqual(b'000000000000000', tx.token_txhash) self.assertEqual(200000, tx.total_amount) self.assertEqual( '2a862e2715683ede4f177f928b558fdb6c1a1bac5c17a34faa57b5ca2c0a9f3f', bin2hstr(tx.txhash)) self.assertEqual(10, tx.ots_key) self.assertEqual(test_signature_TransferToken, bin2hstr(tx.signature)) self.assertEqual(1, tx.fee)
def VT(self, data): """ Vote Transaction This function processes whenever a Transaction having subtype VOTE is received. :return: """ try: vote = Transaction.from_json(data) except Exception as e: logger.error( 'Vote Txn rejected - unable to decode serialised data - closing connection' ) logger.exception(e) self.transport.loseConnection() return if not self.factory.master_mr.isRequested(vote.get_message_hash(), self): return if self.factory.buffered_chain.add_vote(vote): self.factory.register_and_broadcast('VT', vote.get_message_hash(), vote.to_json())
def ST(self, data): """ Stake Transaction This function processes whenever a Transaction having subtype ST is received. :return: """ try: st = Transaction.from_json(data) except Exception as e: logger.error( 'st rejected - unable to decode serialised data - closing connection' ) logger.exception(e) self.transport.loseConnection() return if not self.factory.master_mr.isRequested(st.get_message_hash(), self): return if len(self.factory.buffered_chain._chain.blockchain) == 1 and \ st.activation_blocknumber > self.factory.buffered_chain.height + config.dev.blocks_per_epoch: return height = self.factory.buffered_chain.height + 1 stake_validators_tracker = self.factory.buffered_chain.get_stake_validators_tracker( height) if st.txfrom in stake_validators_tracker.future_stake_addresses: logger.debug( 'P2P dropping st as staker is already in future_stake_address %s', st.txfrom) return if st.txfrom in stake_validators_tracker.sv_dict: expiry = stake_validators_tracker.sv_dict[ st.txfrom].activation_blocknumber + config.dev.blocks_per_epoch if st.activation_blocknumber < expiry: logger.debug( 'P2P dropping st txn as it is already active for the given range %s', st.txfrom) return if st.activation_blocknumber > height + config.dev.blocks_per_epoch: logger.debug( 'P2P dropping st as activation_blocknumber beyond limit') return False for t in self.factory.buffered_chain.tx_pool.transaction_pool: if st.get_message_hash() == t.get_message_hash(): return tx_state = self.factory.buffered_chain.get_stxn_state( blocknumber=self.factory.buffered_chain.height + 1, addr=st.txfrom) if st.validate() and st.validate_extended(tx_state=tx_state): self.factory.buffered_chain.tx_pool.add_tx_to_pool(st) else: logger.warning('>>>ST %s invalid state validation failed..', bin2hstr(tuple(st.hash))) return self.factory.register_and_broadcast('ST', st.get_message_hash(), st.to_json())