def __init__(self, *args, **kwargs): super(TestSimpleTransaction, self).__init__(*args, **kwargs) self.alice = get_alice_xmss() self.bob = get_bob_xmss() self.slave = get_slave_xmss() self.alice.set_ots_index(10) self.maxDiff = None
def setUp(self): self.alice = get_alice_xmss() self.slave = get_slave_xmss() self.params = { "slave_pks": [self.slave.pk], "access_types": [0], "fee": 1, "xmss_pk": self.alice.pk }
def test_revert_transfer_token_txn_multi_send(self): """ Alice has 1100 tokens and 100 QRL, Bob and Slave have none. Alice sends some tokens to Bob and Slave. Undo this. """ slave = get_slave_xmss() self.params["addrs_to"] = [self.bob.address, slave.address] self.params["amounts"] = [100, 100] tx = TransferTokenTransaction.create(**self.params) tx.sign(self.alice) addresses_state = dict(self.addresses_state) addresses_state[self.alice.address].pbdata.balance = 100 addresses_state[self.bob.address].pbdata.balance = 0 addresses_state[slave.address] = OptimizedAddressState.get_default( slave.address) tokens = Indexer(b'token', None) tokens.data[(self.alice.address, tx.token_txhash)] = TokenBalance(balance=1100) state_container = StateContainer(addresses_state=addresses_state, tokens=tokens, slaves=Indexer(b'slave', None), lattice_pk=Indexer( b'lattice_pk', None), multi_sig_spend_txs=dict(), votes_stats=dict(), block_number=1, total_coin_supply=1000, current_dev_config=config.dev, write_access=True, my_db=self.state._db, batch=None) state_container.paginated_bitfield.set_ots_key(addresses_state, self.alice.address, 0) self.assertTrue( state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse( self.alice.address, 0)) tx.apply(self.state, state_container) tx.revert(self.state, state_container) self.assertFalse( state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse( self.alice.address, 0)) self.assertEqual(addresses_state[self.alice.address].balance, 100) self.assertEqual(addresses_state[self.bob.address].balance, 0) self.assertEqual(addresses_state[slave.address].balance, 0) self.assertEqual( tokens.data[(self.alice.address, tx.token_txhash)].balance, 1100) self.assertEqual( tokens.data[(self.bob.address, tx.token_txhash)].balance, 0) self.assertEqual(tokens.data[(slave.address, tx.token_txhash)].balance, 0)
def test_state_validate_tx_custom(self, m_logger): """ TransferTokenTransaction._validate_custom() checks for: 1. 0 amounts 2. fee < 0 3. multi-send: too many recipients 4. multi-send: recipient addresses and amounts not the same length 5. invalid addr_from 6. invalid addr_to """ slave = get_slave_xmss() params = self.default_params() tx = TransferTokenTransaction.create(**params) tx.sign(self.alice) result = tx.validate_or_raise() self.assertTrue(result) params = self.default_params() params["addrs_to"] = [self.bob.address, slave.address] params["amounts"] = [1, 0] with self.assertRaises(ValueError): tx = TransferTokenTransaction.create(**params) # Protobuf validation doesn't allow negative fees already params = self.default_params() tx = TransferTokenTransaction.create(**params) tx.sign(self.alice) with patch('xrd.core.txs.Transaction.Transaction.fee', new_callable=PropertyMock) as m_fee: m_fee.return_value = -1 with self.assertRaises(ValueError): tx.validate_or_raise() # TX signing already fails if addrs_to and amounts are unequal length params = self.default_params() tx = TransferTokenTransaction.create(**params) tx.sign(self.alice) with patch( 'xrd.core.txs.TransferTokenTransaction.TransferTokenTransaction.addrs_to', new_callable=PropertyMock) as m_addrs_to: m_addrs_to.return_value = [self.bob.address, slave.address] with self.assertRaises(ValueError): tx.validate_or_raise() params = self.default_params() params["master_addr"] = b'Bad xrd Address' with self.assertRaises(ValueError): tx = TransferTokenTransaction.create(**params) params = self.default_params() params["addrs_to"] = [self.bob.address, b'Bad xrd address'] params["amounts"] = [100, 200] with self.assertRaises(ValueError): tx = TransferTokenTransaction.create(**params)
def test_apply_token_txn_signed_by_slave_xmss(self): """ Alice creates a token, gives herself and Bob some tokens. But she uses a XMSS slave to sign it. """ initial_balances = [qrl_pb2.AddressAmount(address=self.alice.address, amount=1000), qrl_pb2.AddressAmount(address=self.bob.address, amount=2000)] slave = get_slave_xmss() self.params["initial_balances"] = initial_balances self.params["xmss_pk"] = slave.pk self.params["master_addr"] = self.alice.address tx = TokenTransaction.create(**self.params) tx.sign(slave) # Now that we have the Slave XMSS address, we should add it to AddressState so that apply_state_changes() # can do something with it addresses_state = dict(self.addresses_state) addresses_state[slave.address] = OptimizedAddressState.get_default(slave.address) state_container = StateContainer(addresses_state=addresses_state, tokens=Indexer(b'token', None), slaves=Indexer(b'slave', None), lattice_pk=Indexer(b'lattice_pk', None), multi_sig_spend_txs=dict(), votes_stats=dict(), block_number=1, total_coin_supply=1000, current_dev_config=config.dev, write_access=True, my_db=self.state._db, batch=None) tx.apply(self.state, state_container) self.assertEqual(addresses_state[self.alice.address].balance, 99) self.assertEqual(3, len(state_container.paginated_tx_hash.key_value)) storage_key = state_container.paginated_tx_hash.generate_key(self.alice.address, 1) self.assertIn(storage_key, state_container.paginated_tx_hash.key_value) self.assertEqual([tx.txhash], state_container.paginated_tx_hash.key_value[storage_key]) storage_key = state_container.paginated_tx_hash.generate_key(self.bob.address, 1) self.assertIn(storage_key, state_container.paginated_tx_hash.key_value) self.assertEqual([tx.txhash], state_container.paginated_tx_hash.key_value[storage_key]) storage_key = state_container.paginated_tx_hash.generate_key(slave.address, 1) self.assertIn(storage_key, state_container.paginated_tx_hash.key_value) self.assertEqual([tx.txhash], state_container.paginated_tx_hash.key_value[storage_key]) self.assertEqual(2, len(state_container.tokens.data)) self.assertIn((self.bob.address, tx.txhash), state_container.tokens.data) self.assertEqual(1000, state_container.tokens.data[(self.alice.address, tx.txhash)].balance) self.assertEqual(2000, state_container.tokens.data[(self.bob.address, tx.txhash)].balance) self.assertTrue(state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse(slave.address, 0)) self.assertFalse(state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse(self.alice.address, 0)) self.assertFalse(state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse(self.bob.address, 0))
def __init__(self, *args, **kwargs): super(TestSimpleTransaction, self).__init__(*args, **kwargs) with set_qrl_dir('no_data'): self.state = State() self.alice = get_alice_xmss() self.bob = get_bob_xmss() self.slave = get_slave_xmss() self.alice.set_ots_index(10) self.maxDiff = None
def setUp(self): self.alice = get_alice_xmss() self.slave = get_slave_xmss() self.params = { "slave_pks": [self.slave.pk], "access_types": [0], "fee": 1, "xmss_pk": self.alice.pk } self.unused_chain_manager_mock = Mock(autospec=ChainManager, name='unused ChainManager')
def test_set_affected_address(self, m_logger): result = set() params = self.default_params() tx = TransferTokenTransaction.create(**params) tx.set_affected_address(result) self.assertEqual(2, len(result)) params = self.default_params() params["addrs_to"] = [self.bob.address, get_slave_xmss().address] params["amounts"] = [100, 200] tx = TransferTokenTransaction.create(**params) tx.set_affected_address(result) self.assertEqual(3, len(result))
def setUp(self): with set_xrd_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 test_revert_state_changes_multi_send(self, m_logger, m_apply_state_PK, m_revert_state_PK): """ Alice has 1000 tokens and 100 QRL, Bob and Slave have none. Alice sends some tokens to Bob and Slave. Undo this. """ slave = get_slave_xmss() self.params["addrs_to"] = [self.bob.address, slave.address] self.params["amounts"] = [100, 100] tx = TransferTokenTransaction.create(**self.params) tx.sign(self.alice) addresses_state = self.generate_addresses_state(tx) addresses_state[self.alice.address].balance = 99 addresses_state[self.alice.address].tokens[ self.params["token_txhash"]] = 900 addresses_state[self.alice.address].transaction_hashes = [tx.txhash] addresses_state[self.bob.address].balance = 0 addresses_state[self.bob.address].tokens[ self.params["token_txhash"]] = 100 addresses_state[self.bob.address].transaction_hashes = [tx.txhash] addresses_state[slave.address] = Mock( autospec=AddressState, name='slave AddressState', tokens={self.params["token_txhash"]: 100}, transaction_hashes=[tx.txhash], balance=0) tx.revert_state_changes(addresses_state, self.unused_chain_manager_mock) self.assertEqual(addresses_state[self.alice.address].balance, 100) self.assertEqual(addresses_state[self.bob.address].balance, 0) self.assertEqual(addresses_state[slave.address].balance, 0) addresses_state[ self.alice.address].update_token_balance.assert_called_with( b'I declare the TEST token', 200) addresses_state[ self.bob.address].update_token_balance.assert_called_with( b'I declare the TEST token', -100) addresses_state[slave.address].update_token_balance.assert_called_with( b'I declare the TEST token', -100) self.assertEqual( [], addresses_state[self.alice.address].transaction_hashes) self.assertEqual([], addresses_state[self.bob.address].transaction_hashes) self.assertEqual([], addresses_state[slave.address].transaction_hashes) m_revert_state_PK.assert_called_once()
def test_validate_tx(self): initial_balances = [qrl_pb2.AddressAmount(address=self.alice.address, amount=1000), qrl_pb2.AddressAmount(address=self.bob.address, amount=1000)] slave = get_slave_xmss() self.params["initial_balances"] = initial_balances self.params["xmss_pk"] = slave.pk self.params["master_addr"] = self.alice.address tx = TokenTransaction.create(**self.params) tx.sign(slave) self.assertTrue(tx.validate_or_raise()) tx._data.transaction_hash = b'abc' # Should fail, as we have modified with invalid transaction_hash with self.assertRaises(ValueError): tx.validate_or_raise()
def test_affected_address(self, m_logger): tx = TokenTransaction.create(**self.params) # Default params should result in 2 affected addresses result = set() tx.set_affected_address(result) self.assertEqual(2, len(result)) # If the slave is a recipient of tokens, he should be included too. slave = get_slave_xmss() result = set() self.initial_balances_valid.append(xrd_pb2.AddressAmount(address=slave.address, amount=1000)) tx = TokenTransaction.create(symbol=b'xrd', name=b'Quantum Resistant Ledger', owner=self.alice.address, decimals=15, initial_balances=self.initial_balances_valid, fee=1, xmss_pk=self.alice.pk) tx.set_affected_address(result) self.assertEqual(3, len(result))
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.alice = get_alice_xmss() self.slave = get_slave_xmss() alice_address_state = OptimizedAddressState.get_default( self.alice.address) alice_address_state.pbdata.balance = 100 self.addresses_state = { self.alice.address: alice_address_state, self.slave.address: OptimizedAddressState.get_default(self.slave.address) } self.params = { "slave_pks": [self.slave.pk], "access_types": [0], "fee": 1, "xmss_pk": self.alice.pk } self.unused_chain_manager_mock = Mock(autospec=ChainManager, name='unused ChainManager')
from qrl.core.txs.TransferTransaction import TransferTransaction from qrl.core.p2p.p2pprotocol import P2PProtocol from qrl.core.p2p.p2pPeerManager import P2PPeerManager from qrl.core.p2p.p2pChainManager import P2PChainManager from qrl.core.node import POW from qrl.generated import qrl_pb2 from pyqrllib.pyqrllib import hstr2bin from tests.misc.MockHelper.mock_get_tx_metadata import GetTXMetadata from tests.core.test_State import gen_blocks from tests.misc.helper import set_qrl_dir, get_alice_xmss, get_slave_xmss, replacement_getTime, get_random_xmss logger.initialize_default() alice = get_alice_xmss() slave = get_slave_xmss() @patch('qrl.core.misc.ntp.getTime', new=replacement_getTime) class TestQRLNodeReal(TestCase): @patch('qrl.core.misc.ntp.getTime', new=replacement_getTime) def setUp(self): # You have to set_qrl_dir to an empty one, otherwise State will have some Transactions from disk with set_qrl_dir('no_data'): self.db_state = State() self.chainmanager = ChainManager(self.db_state) self.qrlnode = QRLNode(mining_address=b'') self.qrlnode.set_chain_manager(self.chainmanager) @patch('qrl.core.qrlnode.QRLNode.block_height', new_callable=PropertyMock,
def test_validate_extended(self, m_validate_slave, m_logger): """ TransferTokenTransaction._validate_extended checks for: 1. valid master/slave 2. negative fee, negative total token amounts transferred 3. addr_from has enough funds for the fee 4. if addr_from owns any tokens to begin with 5. if addr_from has enough tokens 6. addr_from ots_key reuse """ alice_address_state = OptimizedAddressState.get_default(self.alice.address) alice_address_state.pbdata.balance = 100 params = self.default_params() tx = TransferTokenTransaction.create(**params) tx.sign(self.alice) addresses_state = { alice_address_state.address: alice_address_state } tokens = Indexer(b'token', None) tokens.data[(self.alice.address, tx.token_txhash)] = qrl_pb2.TokenBalance(balance=1000, decimals=0, delete=False) state_container = StateContainer(addresses_state=addresses_state, tokens=tokens, slaves=Indexer(b'slave', None), lattice_pk=Indexer(b'lattice_pk', None), multi_sig_spend_txs=dict(), votes_stats=dict(), block_number=1, total_coin_supply=1000, current_dev_config=config.dev, write_access=True, my_db=self.state._db, batch=None) result = tx._validate_extended(state_container) self.assertTrue(result) # Invalid master XMSS/slave XMSS relationship m_validate_slave.return_value = False state_container.tokens = Indexer(b'token', None) state_container.tokens.data[(self.alice.address, tx.token_txhash)] = qrl_pb2.TokenBalance(balance=1000, decimals=0, delete=False) result = tx.validate_all(state_container) self.assertFalse(result) m_validate_slave.return_value = True # fee = -1 with patch('qrl.core.txs.TransferTokenTransaction.TransferTokenTransaction.fee', new_callable=PropertyMock) as m_fee: m_fee.return_value = -1 tokens = Indexer(b'token', None) tokens.data[(self.alice.address, tx.token_txhash)] = qrl_pb2.TokenBalance(balance=1000, decimals=0, delete=False) state_container.tokens = tokens result = tx._validate_extended(state_container) self.assertFalse(result) # total_amount = -1 with patch('qrl.core.txs.TransferTokenTransaction.TransferTokenTransaction.total_amount', new_callable=PropertyMock) as m_total_amount: m_total_amount.return_value = -100 tokens = Indexer(b'token', None) tokens.data[(self.alice.address, tx.token_txhash)] = qrl_pb2.TokenBalance(balance=1000, decimals=0, delete=False) state_container.tokens = tokens result = tx._validate_extended(state_container) self.assertFalse(result) # balance = 0, cannot pay the Transaction fee alice_address_state.pbdata.balance = 0 tokens = Indexer(b'token', None) tokens.data[(self.alice.address, tx.token_txhash)] = qrl_pb2.TokenBalance(balance=1000, decimals=0, delete=False) state_container.tokens = tokens result = tx._validate_extended(state_container) self.assertFalse(result) alice_address_state.pbdata.balance = 100 # addr_from doesn't have these tokens state_container.tokens = Indexer(b'token', None) result = tx._validate_extended(state_container) self.assertFalse(result) # addr_from doesn't have enough tokens tokens = Indexer(b'token', None) tokens.data[(self.alice.address, tx.token_txhash)] = qrl_pb2.TokenBalance(balance=99, decimals=0, delete=False) state_container.tokens = tokens result = tx._validate_extended(state_container) self.assertFalse(result) # addr_from_pk has used this OTS key before addresses_state = { self.alice.address: alice_address_state } state_container.addresses_state = addresses_state # addr_from_pk has used this OTS key before state_container.paginated_bitfield.set_ots_key(addresses_state, alice_address_state.address, tx.ots_key) result = tx.validate_all(state_container) self.assertFalse(result) slave = get_slave_xmss() params = self.default_params() params["addrs_to"] = [self.bob.address, slave.address, self.alice.address] params["amounts"] = [2, 3, 5] tx = TransferTokenTransaction.create(**params) tx.sign(self.alice) with patch('qrl.core.config', autospec=True) as m_config: m_config.dev = config.dev.create(config.dev.prev_state_key, config.dev.current_state_key, b'', 10, True, True) m_config.dev.pbdata.transaction.multi_output_limit = 1 state_container.current_dev_config = m_config.dev self.assertFalse(tx._validate_extended(state_container=state_container))