def test_create_negative_fee(self, m_logger): with self.assertRaises(ValueError): TransferTransaction.create(addrs_to=[self.bob.address], amounts=[-100], message_data=None, fee=-1, xmss_pk=self.alice.pk)
def test_check_stale_txn(self, m_is_full_transaction_pool, m_config): """ Stale Transactions are Transactions that were supposed to go into block 5, but for some reason didn't make it. They languish in TransactionPool until check_stale_txn() checks the Pool and updates the tx_info to make them go into a higher block. For each stale transaction, P2PFactory.broadcast_tx() will be called. """ # Redefine at what point should txs be considered stale m_config.user.stale_transaction_threshold = 2 bob_xmss = get_bob_xmss(4) alice_xmss = get_alice_xmss(4) tx1 = TransferTransaction.create(addrs_to=[bob_xmss.address], amounts=[1000000], message_data=None, fee=1, xmss_pk=alice_xmss.pk) tx1.sign(alice_xmss) tx2 = TransferTransaction.create(addrs_to=[bob_xmss.address], amounts=[10000], message_data=None, fee=1, xmss_pk=alice_xmss.pk) tx2.sign(alice_xmss) m_broadcast_tx = Mock( name='Mock Broadcast TX function (in P2PFactory)') self.txpool.add_tx_to_pool(tx1, 5) self.txpool.add_tx_to_pool(tx2, 5) self.txpool.set_broadcast_tx(m_broadcast_tx) with set_qrl_dir('no_data'): state = State() chain_manager = ChainManager(state) self.txpool.check_stale_txn(chain_manager.new_state_container, chain_manager.update_state_container, 8) self.assertEqual(m_broadcast_tx.call_count, 0) m = MockFunction() bob_address_state = OptimizedAddressState.get_default( bob_xmss.address) bob_address_state.pbdata.balance = 1000000000000 m.put(bob_xmss.address, bob_address_state) chain_manager.get_optimized_address_state = m.get tx3 = TransferTransaction.create(addrs_to=[alice_xmss.address], amounts=[10000], message_data=None, fee=1, xmss_pk=bob_xmss.pk) tx3.sign(bob_xmss) self.txpool.add_tx_to_pool(tx3, 5) self.txpool.check_stale_txn(chain_manager.new_state_container, chain_manager.update_state_container, 8) self.assertEqual(m_broadcast_tx.call_count, 1)
def test_get_mini_transactions_by_address(self, mock_get_tx_metadata, mock_get_optimized_address_state, mock_get_paginated_data): """ QRLNode.get_transactions_by_address() returns all the changes in balance caused by a transaction. """ get_tx_metadata = GetTXMetadata() xmss = get_alice_xmss() xmss2 = get_random_xmss() addr_state = OptimizedAddressState.get_default(xmss.address) addr_state.pbdata.balance = 100 addr_state.pbdata.transaction_hash_count = 3 mock_get_optimized_address_state.return_value = addr_state tx1 = CoinBase.create(config.dev, 100, xmss.address, 5) get_tx_metadata.register_tx_metadata(tx1, 1) tx2 = TransferTransaction.create(addrs_to=[xmss2.address], amounts=[10], message_data=None, fee=1, xmss_pk=xmss.pk) tx2.sign(xmss) get_tx_metadata.register_tx_metadata(tx2, 1) tx3 = TransferTransaction.create(addrs_to=[xmss.address], amounts=[100], message_data=None, fee=1, xmss_pk=xmss2.pk) tx3.sign(xmss) get_tx_metadata.register_tx_metadata(tx3, 2) mock_get_paginated_data.return_value = [ tx1.txhash, tx2.txhash, tx3.txhash ] mock_get_tx_metadata.side_effect = get_tx_metadata.get_tx_metadata response = self.qrlnode.get_mini_transactions_by_address( alice.address, 3, 1) result, balance = response.mini_transactions, response.balance self.assertEqual(len(result), 3) self.assertEqual(result[0].amount, 100) self.assertEqual(result[0].out, False) self.assertEqual(result[1].amount, 11) self.assertEqual(result[1].out, True) self.assertEqual(result[2].amount, 100) self.assertEqual(result[2].out, False) self.assertEqual(balance, 100)
def test_create(self, m_logger): # Alice sending coins to Bob tx = TransferTransaction.create(addrs_to=[self.bob.address], amounts=[100], fee=1, xmss_pk=self.alice.pk) self.assertTrue(tx)
def setUp(self): self.tx = TransferTransaction.create(addrs_to=[self.bob.address], amounts=[100], message_data=None, fee=1, xmss_pk=self.alice.pk) self.tx._data.nonce = 1
def test_revert_state_changes_tx_sends_to_self(self, m_logger): """ Alice sent coins to herself, but she still lost the Transaction fee. Undo this. """ addresses_state = { self.alice.address: Mock(autospec=AddressState, name='alice AddressState', transaction_hashes=[self.tx.txhash], balance=199), self.bob.address: Mock(autospec=AddressState, name='bob AddressState', transaction_hashes=[], balance=0), self.slave.address: Mock(autospec=AddressState, name='slave AddressState', transaction_hashes=[], balance=0) } unused_chain_manager_mock = Mock(autospec=ChainManager, name='unused ChainManager') tx = TransferTransaction.create( addrs_to=[self.alice.address], amounts=[100], fee=1, xmss_pk=self.alice.pk ) tx._revert_state_changes_for_PK = Mock(autospec=TransferTransaction._revert_state_changes_for_PK) tx.revert_state_changes(addresses_state, unused_chain_manager_mock) self.assertEqual(200, addresses_state[self.alice.address].balance) self.assertEqual(0, addresses_state[self.bob.address].balance) self.assertEqual([], addresses_state[self.alice.address].transaction_hashes) self.assertEqual([], addresses_state[self.bob.address].transaction_hashes) tx._revert_state_changes_for_PK.assert_called_once()
def test_revert_state_changes_multi_send(self, m_logger): """ Alice has sent 20 coins to Bob and Slave each, using 1 as Transaction fee. Now we need to undo this. """ addresses_state = { self.alice.address: Mock(autospec=AddressState, name='alice AddressState', transaction_hashes=[self.tx.txhash], balance=159), self.bob.address: Mock(autospec=AddressState, name='bob AddressState', transaction_hashes=[self.tx.txhash], balance=20), self.slave.address: Mock(autospec=AddressState, name='slave AddressState', transaction_hashes=[self.tx.txhash], balance=20) } unused_chain_manager_mock = Mock(autospec=ChainManager, name='unused ChainManager') tx_multisend = TransferTransaction.create( addrs_to=[self.bob.address, self.slave.address], amounts=[20, 20], fee=1, xmss_pk=self.alice.pk ) tx_multisend._revert_state_changes_for_PK = Mock(autospec=TransferTransaction._revert_state_changes_for_PK) tx_multisend.revert_state_changes(addresses_state, unused_chain_manager_mock) self.assertEqual(200, addresses_state[self.alice.address].balance) self.assertEqual(0, addresses_state[self.bob.address].balance) self.assertEqual(0, addresses_state[self.slave.address].balance) self.assertEqual([], addresses_state[self.alice.address].transaction_hashes) self.assertEqual([], addresses_state[self.bob.address].transaction_hashes) self.assertEqual([], addresses_state[self.slave.address].transaction_hashes) tx_multisend._revert_state_changes_for_PK.assert_called_once()
def test_apply_state_changes_multi_send(self, m_logger): """ Test that apply_state_changes() also works with multiple recipients. """ addresses_state = { self.alice.address: Mock(autospec=AddressState, name='alice AddressState', transaction_hashes=[], balance=200), self.bob.address: Mock(autospec=AddressState, name='bob AddressState', transaction_hashes=[], balance=0), self.slave.address: Mock(autospec=AddressState, name='slave AddressState', transaction_hashes=[], balance=0) } tx_multisend = TransferTransaction.create( addrs_to=[self.bob.address, self.slave.address], amounts=[20, 20], fee=1, xmss_pk=self.alice.pk ) tx_multisend._apply_state_changes_for_PK = Mock(autospec=TransferTransaction._apply_state_changes_for_PK) tx_multisend.apply_state_changes(addresses_state) # Now Alice should have 159 coins left (200 - 20 - 20 - 1) and Bob should have 100 coins. self.assertEqual(159, addresses_state[self.alice.address].balance) self.assertEqual(20, addresses_state[self.bob.address].balance) self.assertEqual(20, addresses_state[self.slave.address].balance) tx_multisend._apply_state_changes_for_PK.assert_called_once()
def setUp(self): self.tx = TransferTransaction.create( addrs_to=[self.bob.address], amounts=[100], fee=1, xmss_pk=self.alice.pk )
def test_rollback_tx_metadata(self): alice_xmss = get_alice_xmss() tx1 = TransferTransaction.create( addrs_to=[get_some_address(1), get_some_address(2)], amounts=[1, 2], message_data=None, fee=0, xmss_pk=alice_xmss.pk) block = Block.create(dev_config=config.dev, block_number=5, prev_headerhash=b'', prev_timestamp=10, transactions=[tx1], miner_address=b'', seed_height=0, seed_hash=None) TransactionMetadata.update_tx_metadata(self.state, block=block, batch=None) tx_metadata = TransactionMetadata.get_tx_metadata( self.state, tx1.txhash) self.assertEqual(tx_metadata[0].to_json(), tx1.to_json()) TransactionMetadata.rollback_tx_metadata(self.state, block, None) self.assertIsNone( TransactionMetadata.get_tx_metadata(self.state, tx1.txhash))
def test_apply_state_changes_for_PK_master_slave_XMSS(self, m_logger): """ If the TX was signed by a slave XMSS, the slave XMSS's AddressState should be updated (not the master's). :return: """ tx = TransferTransaction.create(addrs_to=[self.bob.address], amounts=[100], fee=1, xmss_pk=self.slave.pk, master_addr=self.alice.address) addr_state = { self.alice.address: Mock(autospec=AddressState, name='alice AddressState'), self.slave.address: Mock(autospec=AddressState, name='slave AddressState') } old_ots_index = self.slave.ots_index tx.sign(self.slave) tx._apply_state_changes_for_PK(addr_state) addr_state[self.slave.address].increase_nonce.assert_called_once() addr_state[self.slave.address].set_ots_key.assert_called_once_with( old_ots_index) addr_state[ self.slave.address].transaction_hashes.append.assert_called_once()
def test_apply_state_changes_tx_sends_to_self(self, m_logger): """ If you send coins to yourself, you should only lose the fee for the Transaction. """ addresses_state = { self.alice.address: Mock(autospec=AddressState, name='alice AddressState', transaction_hashes=[], balance=200), self.bob.address: Mock(autospec=AddressState, name='bob AddressState', transaction_hashes=[], balance=0), self.slave.address: Mock(autospec=AddressState, name='slave AddressState', transaction_hashes=[], balance=0) } tx = TransferTransaction.create(addrs_to=[self.alice.address], amounts=[100], fee=1, xmss_pk=self.alice.pk) tx._apply_state_changes_for_PK = Mock( autospec=TransferTransaction._revert_state_changes_for_PK) tx.apply_state_changes(addresses_state) self.assertEqual(199, addresses_state[self.alice.address].balance) self.assertIn(tx.txhash, addresses_state[self.alice.address].transaction_hashes)
def broadcast_tx(self, tx: TransferTransaction): logger.info('<<<Transmitting TX: %s', bin2hstr(tx.txhash)) if isinstance(tx, MessageTransaction): legacy_type = qrllegacy_pb2.LegacyMessage.MT elif isinstance(tx, TransferTransaction): legacy_type = qrllegacy_pb2.LegacyMessage.TX elif isinstance(tx, TokenTransaction): legacy_type = qrllegacy_pb2.LegacyMessage.TK elif isinstance(tx, TransferTokenTransaction): legacy_type = qrllegacy_pb2.LegacyMessage.TT elif isinstance(tx, SlaveTransaction): legacy_type = qrllegacy_pb2.LegacyMessage.SL elif isinstance(tx, LatticeTransaction): legacy_type = qrllegacy_pb2.LegacyMessage.LT elif isinstance(tx, MultiSigCreate): legacy_type = qrllegacy_pb2.LegacyMessage.MC elif isinstance(tx, MultiSigSpend): legacy_type = qrllegacy_pb2.LegacyMessage.MS elif isinstance(tx, MultiSigVote): legacy_type = qrllegacy_pb2.LegacyMessage.MV else: raise ValueError('Invalid Transaction Type') self.register_and_broadcast(legacy_type, tx.get_message_hash(), tx.pbdata)
def test_prepare_address_list(self): with set_qrl_dir('no_data'): with State() as state: block = Block.create(block_number=10, prev_headerhash=b'', prev_timestamp=10, transactions=[], miner_address=get_some_address(1)) # Test Case: without any transactions of block self.assertEqual(state.prepare_address_list(block), {config.dev.coinbase_address, get_some_address(1)}) alice_xmss = get_alice_xmss() block = Block.create(block_number=10, prev_headerhash=b'', prev_timestamp=10, transactions=[TransferTransaction.create(addrs_to=[get_some_address(2), get_some_address(3)], amounts=[100, 100], fee=0, xmss_pk=alice_xmss.pk)], miner_address=get_some_address(1)) # Test Case, with one Transaction self.assertEqual(state.prepare_address_list(block), {config.dev.coinbase_address, get_some_address(1), get_some_address(2), get_some_address(3), alice_xmss.address})
def transfer(destinations, fee, mixin, unlock_time): if len(destinations) > config.dev.transaction_multi_output_limit: raise Exception('Payment Failed: Amount exceeds the allowed limit') addrs_to = [] amounts = [] for tx in destinations: addrs_to.append(bytes(hstr2bin(tx['address'][1:]))) # Skipping 'Q' amounts.append(tx['amount']) stub = get_public_stub() xmss = get_unused_payment_xmss(stub) if not xmss: raise Exception('Payment Failed: No Unused Payment XMSS found') tx = TransferTransaction.create(addrs_to=addrs_to, amounts=amounts, fee=fee, xmss_pk=xmss.pk, master_addr=payment_slaves[0]) tx.sign(xmss) response = stub.PushTransaction(request=qrl_pb2.PushTransactionReq( transaction_signed=tx.pbdata)) if response.error_code != 3: raise Exception('Transaction Submission Failed, Response Code: %s', response.error_code) response = {'tx_hash': bin2hstr(tx.txhash)} return response
def test_validate_transaction_pool_reusing_ots_index(self, m_logger): """ Two different TransferTransactions. They are signed with the same OTS indexe, from the same public key. Therefore they should conflict. :return: """ tx = self.tx tx2 = TransferTransaction.create(addrs_to=[self.bob.address], amounts=[100], message_data=None, fee=5, xmss_pk=self.alice.pk) # alice_clone's OTS index is still at 10, while self.alice will be at 11 after signing. alice_clone = get_alice_xmss() alice_clone.set_ots_index(10) tx.sign(self.alice) tx2.sign(alice_clone) tx_info = Mock(autospec=TransactionInfo, transaction=tx) tx2_info = Mock(autospec=TransactionInfo, transaction=tx2) transaction_pool = [(replacement_getTime(), tx_info), (replacement_getTime(), tx2_info)] result = tx.validate_transaction_pool(transaction_pool) self.assertFalse(result)
def test_get_transactions_by_address(self): """ QRLNode.get_transactions_by_address() returns all the changes in balance caused by a transaction. """ mock_get_tx_metadata = GetTXMetadata() xmss = get_alice_xmss() xmss2 = get_random_xmss() addr_state = AddressState.get_default(xmss.address) addr_state.pbdata.balance = 100 tx1 = CoinBase.create(100, xmss.address, 5) mock_get_tx_metadata.register_tx_metadata(tx1, 5) addr_state.transaction_hashes.append(tx1.txhash) tx2 = TransferTransaction.create(addrs_to=[xmss2.address], amounts=[10], fee=1, xmss_pk=xmss.pk) tx2.sign(xmss) mock_get_tx_metadata.register_tx_metadata(tx2, 99) addr_state.transaction_hashes.append(tx2.txhash) tx3 = TransferTransaction.create(addrs_to=[xmss.address], amounts=[100], fee=1, xmss_pk=xmss2.pk) tx3.sign(xmss) mock_get_tx_metadata.register_tx_metadata(tx3, 101) addr_state.transaction_hashes.append(tx3.txhash) self.db_state.get_address_state.return_value = addr_state self.db_state.get_tx_metadata = mock_get_tx_metadata.get_tx_metadata result, balance = self.qrlnode.get_transactions_by_address( alice.address) self.assertEqual(len(result), 3) self.assertEqual(result[0].amount, 100) self.assertEqual(result[0].out, False) self.assertEqual(result[1].amount, 11) self.assertEqual(result[1].out, True) self.assertEqual(result[2].amount, 100) self.assertEqual(result[2].out, False) self.assertEqual(balance, 189)
def create_tx(addrs_to, amounts, signing_xmss, nonce): tx = TransferTransaction.create(addrs_to=addrs_to, amounts=amounts, fee=0, xmss_pk=signing_xmss.pk) tx.sign(signing_xmss) tx._data.nonce = nonce return tx
def test_update_last_tx(self): alice_xmss = get_alice_xmss() # Test Case: When there is no last txns self.assertEqual(LastTransactions.get_last_txs(self.state), []) block = Block() tx1 = TransferTransaction.create( addrs_to=[get_some_address(1), get_some_address(2)], amounts=[1, 2], message_data=None, fee=0, xmss_pk=alice_xmss.pk) block._data.transactions.extend([tx1.pbdata]) LastTransactions._update_last_tx(self.state, block, None) last_txns = LastTransactions.get_last_txs(self.state) # Test Case: When there is only 1 last txns self.assertEqual(len(last_txns), 1) self.assertEqual(last_txns[0].to_json(), tx1.to_json()) block = Block() tx2 = TransferTransaction.create( addrs_to=[get_some_address(2), get_some_address(3)], amounts=[1, 2], message_data=None, fee=0, xmss_pk=alice_xmss.pk) tx3 = TransferTransaction.create( addrs_to=[get_some_address(4), get_some_address(5)], amounts=[1, 2], message_data=None, fee=0, xmss_pk=alice_xmss.pk) block._data.transactions.extend([tx2.pbdata, tx3.pbdata]) LastTransactions._update_last_tx(self.state, block, None) last_txns = LastTransactions.get_last_txs(self.state) # Test Case: When there are 3 last txns self.assertEqual(len(last_txns), 3) self.assertEqual(last_txns[0].to_json(), tx3.to_json()) self.assertEqual(last_txns[1].to_json(), tx2.to_json()) self.assertEqual(last_txns[2].to_json(), tx1.to_json())
def test_to_json(self, m_logger): tx = TransferTransaction.create(addrs_to=[self.bob.address], amounts=[100], fee=1, xmss_pk=self.alice.pk) txjson = tx.to_json() self.assertEqual(json.loads(test_json_Simple), json.loads(txjson))
def test_broadcast_tx(self, m_reactor, m_logger): # broadcast_tx() should handle all Transaction Types self.factory.broadcast_tx(MessageTransaction()) self.factory.broadcast_tx(TransferTransaction()) self.factory.broadcast_tx(TokenTransaction()) self.factory.broadcast_tx(TransferTokenTransaction()) self.factory.broadcast_tx(SlaveTransaction()) with self.assertRaises(ValueError): m_tx = Mock(autospec=TransferTransaction, txhash=bhstr2bin('deadbeef')) self.factory.broadcast_tx(m_tx)
def test_update_last_tx(self): with set_qrl_dir('no_data'): with State() as state: alice_xmss = get_alice_xmss() # Test Case: When there is no last txns self.assertEqual(state.get_last_txs(), []) block = Block() tx1 = TransferTransaction.create(addrs_to=[get_some_address(1), get_some_address(2)], amounts=[1, 2], fee=0, xmss_pk=alice_xmss.pk) block._data.transactions.extend([tx1.pbdata]) state._update_last_tx(block, None) last_txns = state.get_last_txs() # Test Case: When there is only 1 last txns self.assertEqual(len(last_txns), 1) self.assertEqual(last_txns[0].to_json(), tx1.to_json()) block = Block() tx2 = TransferTransaction.create(addrs_to=[get_some_address(2), get_some_address(3)], amounts=[1, 2], fee=0, xmss_pk=alice_xmss.pk) tx3 = TransferTransaction.create(addrs_to=[get_some_address(4), get_some_address(5)], amounts=[1, 2], fee=0, xmss_pk=alice_xmss.pk) block._data.transactions.extend([tx2.pbdata, tx3.pbdata]) state._update_last_tx(block, None) last_txns = state.get_last_txs() # Test Case: When there are 3 last txns self.assertEqual(len(last_txns), 3) self.assertEqual(last_txns[0].to_json(), tx3.to_json()) self.assertEqual(last_txns[1].to_json(), tx2.to_json()) self.assertEqual(last_txns[2].to_json(), tx1.to_json())
def test_validate_tx3(self, m_logger): tx = TransferTransaction.create(addrs_to=[self.bob.address], amounts=[100], message_data=None, fee=1, xmss_pk=self.alice.pk) tx.sign(self.alice) tx._data.signature = tx.signature * 4183 + tx.signature[0:104] tx._data.transaction_hash = tx.generate_txhash() with self.assertRaises(ValueError): tx.validate_or_raise()
def create_send_tx(self, addrs_to: list, amounts: list, fee: int, xmss_pk: bytes, master_addr: bytes) -> TransferTransaction: addr_from = self.get_addr_from(xmss_pk, master_addr) balance = self._chain_manager.get_address_balance(addr_from) if sum(amounts) + fee > balance: raise ValueError("Not enough funds in the source address") return TransferTransaction.create(addrs_to=addrs_to, amounts=amounts, fee=fee, xmss_pk=xmss_pk, master_addr=master_addr)
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 test_revert_state_changes_for_PK_master_slave_XMSS(self, m_logger): addresses_state = { self.alice.address: OptimizedAddressState.get_default(self.alice.address), self.slave.address: OptimizedAddressState.get_default(self.slave.address) } addresses_state[self.alice.address].pbdata.balance = 101 addresses_state[self.slave.address].pbdata.nonce = 1 tx = TransferTransaction.create(addrs_to=[self.bob.address], amounts=[100], message_data=None, fee=1, xmss_pk=self.slave.pk, master_addr=self.alice.address) tx.sign(self.slave) ots_key = self.slave.ots_index - 1 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) state_container.paginated_bitfield.set_ots_key(addresses_state, self.slave.address, ots_key) state_container.paginated_bitfield.put_addresses_bitfield(None) self.assertTrue( state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse( self.slave.address, ots_key)) self.assertFalse( state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse( self.alice.address, self.alice.ots_index)) tx._apply_state_changes_for_PK(state_container) tx._revert_state_changes_for_PK(state_container) self.assertFalse( state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse( self.slave.address, ots_key)) self.assertFalse( state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse( self.alice.address, self.alice.ots_index))
def test_validate_tx2(self, m_logger): tx = TransferTransaction.create(addrs_to=[self.bob.address], amounts=[100], fee=1, xmss_pk=self.alice.pk) tx.sign(self.alice) 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_update_tx_metadata(self): with set_qrl_dir('no_data'): with State() as state: alice_xmss = get_alice_xmss() tx = TransferTransaction.create(addrs_to=[get_some_address(1), get_some_address(2)], amounts=[1, 2], fee=0, xmss_pk=alice_xmss.pk) block_number = 5 state.put_tx_metadata(tx, block_number, 10000, None) tx_metadata = state.get_tx_metadata(tx.txhash) self.assertEqual(tx_metadata[0].to_json(), tx.to_json()) self.assertEqual(tx_metadata[1], block_number)
def test_apply_state_changes_for_PK_master_slave_XMSS(self, m_logger): """ If the TX was signed by a slave XMSS, the slave XMSS's AddressState should be updated (not the master's). :return: """ tx = TransferTransaction.create(addrs_to=[self.bob.address], amounts=[100], message_data=None, fee=1, xmss_pk=self.slave.pk, master_addr=self.alice.address) addresses_state = { self.alice.address: OptimizedAddressState.get_default(self.alice.address), self.slave.address: OptimizedAddressState.get_default(self.slave.address) } tx.sign(self.slave) ots_key = self.slave.ots_index - 1 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) self.assertFalse( state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse( self.slave.address, ots_key)) self.assertFalse( state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse( self.alice.address, self.alice.ots_index)) tx._apply_state_changes_for_PK(state_container) self.assertTrue( state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse( self.slave.address, ots_key)) self.assertFalse( state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse( self.alice.address, self.alice.ots_index)) self.assertEqual(1, addresses_state[self.slave.address].nonce) self.assertEqual(0, addresses_state[self.alice.address].nonce)