def test_validate_extended(self, m_validate_slave, m_logger): """ SlaveTransaction._validate_extended checks for: 1. valid master/slave 2. negative fee, 3. addr_from has enough funds for the fee 4. addr_from ots_key reuse """ alice_address_state = OptimizedAddressState.get_default( self.alice.address) alice_address_state.pbdata.balance = 100 addresses_state = {alice_address_state.address: alice_address_state} tx = SlaveTransaction.create(**self.params) tx.sign(self.alice) 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=100, 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 result = tx.validate_all(state_container) self.assertFalse(result) m_validate_slave.return_value = True # fee = -1 with patch('qrl.core.txs.SlaveTransaction.SlaveTransaction.fee', new_callable=PropertyMock) as m_fee: m_fee.return_value = -1 result = tx._validate_custom() self.assertFalse(result) # balance = 0, cannot pay the Transaction fee alice_address_state.pbdata.balance = 0 result = tx._validate_extended(state_container) self.assertFalse(result) alice_address_state.pbdata.balance = 100 addresses_state = {self.alice.address: alice_address_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) bob = get_bob_xmss() # Too many slave_pks 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 = 2 state_container.current_dev_config = m_config.dev params = self.params.copy() params["slave_pks"] = [self.alice.pk, bob.pk, self.slave.pk] params["access_types"] = [0, 0, 0] tx = SlaveTransaction.create(**params) self.assertFalse(tx._validate_extended(state_container))
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))