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)
Example #2
0
    def test_get_mini_transactions_by_address(self, mock_get_tx_metadata,
                                              mock_get_optimized_address_state,
                                              mock_get_paginated_data):
        """
        xrdNode.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.xrdnode.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)
Example #3
0
    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 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_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_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))
Example #7
0
    def broadcast_tx(self, tx: TransferTransaction):
        logger.info('<<<Transmitting TX: %s', bin2hstr(tx.txhash))

        if isinstance(tx, MessageTransaction):
            legacy_type = xrdlegacy_pb2.LegacyMessage.MT
        elif isinstance(tx, TransferTransaction):
            legacy_type = xrdlegacy_pb2.LegacyMessage.TX
        elif isinstance(tx, TokenTransaction):
            legacy_type = xrdlegacy_pb2.LegacyMessage.TK
        elif isinstance(tx, TransferTokenTransaction):
            legacy_type = xrdlegacy_pb2.LegacyMessage.TT
        elif isinstance(tx, SlaveTransaction):
            legacy_type = xrdlegacy_pb2.LegacyMessage.SL
        elif isinstance(tx, LatticeTransaction):
            legacy_type = xrdlegacy_pb2.LegacyMessage.LT
        elif isinstance(tx, MultiSigCreate):
            legacy_type = xrdlegacy_pb2.LegacyMessage.MC
        elif isinstance(tx, MultiSigSpend):
            legacy_type = xrdlegacy_pb2.LegacyMessage.MS
        elif isinstance(tx, MultiSigVote):
            legacy_type = xrdlegacy_pb2.LegacyMessage.MV
        else:
            raise ValueError('Invalid Transaction Type')
        self.register_and_broadcast(legacy_type, tx.get_message_hash(),
                                    tx.pbdata)
Example #8
0
    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_create(self, m_logger):
     # Alice sending coins to Bob
     tx = TransferTransaction.create(addrs_to=[self.bob.address],
                                     amounts=[100],
                                     message_data=None,
                                     fee=1,
                                     xmss_pk=self.alice.pk)
     self.assertTrue(tx)
Example #10
0
def create_tx(addrs_to, amounts, signing_xmss, nonce):
    tx = TransferTransaction.create(addrs_to=addrs_to,
                                    amounts=amounts,
                                    message_data=None,
                                    fee=0,
                                    xmss_pk=signing_xmss.pk)
    tx.sign(signing_xmss)
    tx._data.nonce = nonce
    return tx
    def test_to_json(self, m_logger):
        tx = TransferTransaction.create(addrs_to=[self.bob.address],
                                        amounts=[100],
                                        message_data=None,
                                        fee=1,
                                        xmss_pk=self.alice.pk)
        txjson = tx.to_json()

        self.assertEqual(json.loads(test_json_Simple), json.loads(txjson))
Example #12
0
 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)
Example #13
0
    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_xrd_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_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 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_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)
Example #17
0
    def test_getTransaction(self):
        db_state = Mock(spec=State)
        db_state.get_tx_metadata = MagicMock(return_value=None)
        db_state.get_block = MagicMock(return_value=None)

        p2p_factory = Mock(spec=P2PFactory)
        p2p_factory.pow = Mock(spec=POW)

        chain_manager = ChainManager(db_state)

        xrdnode = xrdNode(mining_address=b'')
        xrdnode.set_chain_manager(chain_manager)
        xrdnode._p2pfactory = p2p_factory
        xrdnode._pow = p2p_factory.pow
        xrdnode._peer_addresses = ['127.0.0.1', '192.168.1.1']

        service = PublicAPIService(xrdnode)

        # Find an address
        bob_xmss = get_bob_xmss()

        # Find a transaction
        alice_xmss = get_alice_xmss()
        db_state.address_used = MagicMock(return_value=False)
        tx1 = TransferTransaction.create(
            addrs_to=[bob_xmss.address],
            amounts=[125],
            message_data=None,
            fee=19,
            xmss_pk=bob_xmss.pk,
            master_addr=alice_xmss.address)

        chain_manager.tx_pool.transaction_pool = [(0, TransactionInfo(tx1, 0))]

        context = Mock(spec=ServicerContext)
        request = xrd_pb2.GetTransactionReq()
        request.tx_hash = tx1.txhash
        response = service.GetTransaction(request=request, context=context)
        context.set_code.assert_not_called()
        self.assertIsNotNone(response.tx)
        self.assertEqual('transfer', response.tx.WhichOneof('transactionType'))
        self.assertEqual(alice_xmss.address, response.tx.master_addr)
        self.assertEqual(bob_xmss.pk, response.tx.public_key)
        self.assertEqual(tx1.txhash, response.tx.transaction_hash)
        self.assertEqual(b'', response.tx.signature)

        self.assertEqual(bob_xmss.address, response.tx.transfer.addrs_to[0])
        self.assertEqual(125, response.tx.transfer.amounts[0])
        self.assertEqual(19, response.tx.fee)
    def test_validate_tx2(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)

        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_revert_transfer_txn_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:
            OptimizedAddressState.get_default(self.alice.address),
            self.bob.address:
            OptimizedAddressState.get_default(self.bob.address)
        }
        addresses_state[self.alice.address].pbdata.balance = 200

        tx = TransferTransaction.create(addrs_to=[self.alice.address],
                                        amounts=[100],
                                        message_data=None,
                                        fee=1,
                                        xmss_pk=self.alice.pk)
        tx.sign(self.alice)
        ots_key = self.alice.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.alice.address,
                                                       ots_key)
        state_container.paginated_bitfield.put_addresses_bitfield(None)

        self.assertTrue(
            state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse(
                self.alice.address, ots_key))
        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, ots_key))

        self.assertEqual(200, addresses_state[self.alice.address].balance)
        self.assertEqual(0, addresses_state[self.bob.address].balance)
    def test_affected_address(self, m_logger):
        # The default transaction params involve only two addresses.
        affected_addresses = set()
        self.tx.set_affected_address(affected_addresses)
        self.assertEqual(2, len(affected_addresses))

        # This transaction should involve 3 addresses.
        affected_addresses = set()
        tx = TransferTransaction.create(
            addrs_to=[self.bob.address, self.slave.address],
            amounts=[100, 100],
            message_data=None,
            fee=1,
            xmss_pk=self.alice.pk)
        tx.set_affected_address(affected_addresses)
        self.assertEqual(3, len(affected_addresses))
    def test_apply_transfer_txn_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:
            OptimizedAddressState.get_default(self.alice.address),
            self.bob.address:
            OptimizedAddressState.get_default(self.bob.address),
            self.slave.address:
            OptimizedAddressState.get_default(self.slave.address)
        }
        addresses_state[self.alice.address].pbdata.balance = 200

        tx = TransferTransaction.create(addrs_to=[self.alice.address],
                                        amounts=[100],
                                        message_data=None,
                                        fee=1,
                                        xmss_pk=self.alice.pk)
        tx.sign(self.alice)
        ots_key = self.alice.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.alice.address, ots_key))
        tx.apply(self.state, state_container)
        self.assertTrue(
            state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse(
                self.alice.address, ots_key))

        self.assertEqual(199, addresses_state[self.alice.address].balance)
        storage_key = state_container.paginated_tx_hash.generate_key(
            self.alice.address, 1)
        self.assertIn(tx.txhash,
                      state_container.paginated_tx_hash.key_value[storage_key])
    def test_apply_transfer_txn_multi_send(self, m_logger):
        """
        Test that apply_state_changes() also works with multiple recipients.
        """
        addresses_state = {
            self.alice.address:
            OptimizedAddressState.get_default(self.alice.address),
            self.bob.address:
            OptimizedAddressState.get_default(self.bob.address),
            self.slave.address:
            OptimizedAddressState.get_default(self.slave.address)
        }
        addresses_state[self.alice.address].pbdata.balance = 200

        tx_multisend = TransferTransaction.create(
            addrs_to=[self.bob.address, self.slave.address],
            amounts=[20, 20],
            message_data=None,
            fee=1,
            xmss_pk=self.alice.pk)
        tx_multisend.sign(self.alice)
        ots_key = self.alice.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.alice.address, ots_key))
        tx_multisend.apply(self.state, state_container)
        self.assertTrue(
            state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse(
                self.alice.address, ots_key))

        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)
    def test_update_tx_metadata(self):
        alice_xmss = get_alice_xmss()
        tx = 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_number = 5
        TransactionMetadata.put_tx_metadata(self.state, tx, block_number,
                                            10000, None)

        tx_metadata = TransactionMetadata.get_tx_metadata(
            self.state, tx.txhash)
        self.assertEqual(tx_metadata[0].to_json(), tx.to_json())
        self.assertEqual(tx_metadata[1], block_number)
Example #24
0
    def create_send_tx(self,
                       addrs_to: list,
                       amounts: list,
                       message_data: bytes,
                       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,
                                          message_data=message_data,
                                          fee=fee,
                                          xmss_pk=xmss_pk,
                                          master_addr=master_addr)
Example #25
0
    def relay_transfer_txn(self, qaddresses_to: list, amounts: list, fee: int,
                           master_qaddress, signer_address: str,
                           ots_index: int):
        self.authenticate()
        index, xmss = self._get_wallet_index_xmss(signer_address, ots_index)
        self.verify_ots(signer_address, xmss, user_ots_index=ots_index)

        tx = TransferTransaction.create(
            addrs_to=self.qaddresses_to_address(qaddresses_to),
            amounts=amounts,
            message_data=None,
            fee=fee,
            xmss_pk=xmss.pk,
            master_addr=self.qaddress_to_address(master_qaddress))

        self.sign_and_push_transaction(tx, xmss, index)

        return self.to_plain_transaction(tx.pbdata)
Example #26
0
    def relay_transfer_txn_by_slave(self, qaddresses_to: list, amounts: list,
                                    fee: int, master_qaddress):
        self.authenticate()
        index, group_index, slave_index, slave_xmss = self.get_slave_xmss(
            master_qaddress)
        if slave_index == -1:
            raise Exception("No Slave Found")

        tx = TransferTransaction.create(
            addrs_to=self.qaddresses_to_address(qaddresses_to),
            amounts=amounts,
            message_data=None,
            fee=fee,
            xmss_pk=slave_xmss.pk,
            master_addr=self.qaddress_to_address(master_qaddress))

        self.sign_and_push_transaction(tx, slave_xmss, index, group_index,
                                       slave_index)

        return self.to_plain_transaction(tx.pbdata)
 def test_validate_transaction_pool(self, m_logger):
     """
     Two TransferTransactions. Although they're the same, they are signed with different OTS indexes.
     Therefore they should not conflict when they are both in the TransactionPool.
     :return:
     """
     tx = self.tx
     tx2 = TransferTransaction.create(addrs_to=[self.bob.address],
                                      amounts=[100],
                                      message_data=None,
                                      fee=1,
                                      xmss_pk=self.alice.pk)
     tx.sign(self.alice)
     tx2.sign(self.alice)
     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.assertTrue(result)
Example #28
0
    def test_remove_last_tx(self):
        # Test Case: When there is no last txns
        self.assertEqual(LastTransactions.get_last_txs(self.state), [])

        alice_xmss = get_alice_xmss()

        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)

        self.assertEqual(last_txns[0].to_json(), tx1.to_json())

        LastTransactions._remove_last_tx(self.state, block, None)
        last_txns = LastTransactions.get_last_txs(self.state)
        self.assertEqual(last_txns, [])
Example #29
0
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,
                                    message_data=None,
                                    fee=fee,
                                    xmss_pk=xmss.pk,
                                    master_addr=payment_slaves[0])

    tx.sign(xmss)

    response = stub.PushTransaction(request=xrd_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_different_pk_same_ots_index(
            self, m_logger):
        """
        Two TransferTransactions. They are signed with the same OTS indexes, but from different public keys.
        Therefore they should NOT conflict.
        :return:
        """
        tx = self.tx
        tx2 = TransferTransaction.create(addrs_to=[self.bob.address],
                                         amounts=[100],
                                         message_data=None,
                                         fee=1,
                                         xmss_pk=self.bob.pk)

        tx.sign(self.alice)
        tx2.sign(self.bob)

        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.assertTrue(result)