Exemple #1
0
    def test_validate_slave_signing_xmss_state_has_no_slave_permissions_in_state(
            self, m_logger):
        bob = get_bob_xmss()
        # Let's say Alice is Bob's master.
        self.params["master_addr"] = self.alice.address
        self.params["xmss_pk"] = bob.pk

        # We need to add extra data to the mock AddressState.
        tx = MessageTransaction.create(**self.params)
        tx.sign(self.alice)
        state_container = StateContainer(addresses_state=dict(),
                                         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)
        result = tx.validate_slave(state_container)
        self.assertFalse(result)
Exemple #2
0
    def test_revert_message_txn(self):
        tx = MessageTransaction.create(**self.params)
        tx.sign(self.alice)
        addresses_state = dict(self.addresses_state)

        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)
        tx.apply(self.state, state_container)
        tx.revert(self.state, state_container)

        self.assertEqual(addresses_state[self.alice.address].balance, 100)
        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(
            [], state_container.paginated_tx_hash.key_value[storage_key])
Exemple #3
0
    def test_revert_coinbase_txn(self, m_logger):
        """
        Alice earned some coins. Undo this.
        """
        tx = CoinBase.create(config.dev, self.amount, self.alice.address, self.mock_blockheader.block_number)
        addresses_state = {
            config.dev.coinbase_address: OptimizedAddressState.get_default(config.dev.coinbase_address),
            self.alice.address: OptimizedAddressState.get_default(self.alice.address),
        }
        addresses_state[config.dev.coinbase_address].pbdata.balance = 1000000

        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=self.mock_blockheader.block_number,
                                         total_coin_supply=100,
                                         current_dev_config=config.dev,
                                         write_access=True,
                                         my_db=self.state._db,
                                         batch=None)
        tx.apply(self.state, state_container)
        tx.revert(self.state, state_container)

        self.assertEqual(1000000, addresses_state[config.dev.coinbase_address].balance)

        storage_key = state_container.paginated_tx_hash.generate_key(config.dev.coinbase_address, 1)
        self.assertEqual([], state_container.paginated_tx_hash.key_value[storage_key])
        self.assertEqual(0, addresses_state[self.alice.address].balance)

        storage_key = state_container.paginated_tx_hash.generate_key(config.dev.coinbase_address, 1)
        self.assertEqual([], state_container.paginated_tx_hash.key_value[storage_key])
Exemple #4
0
    def test_revert_slave_txn(self):
        tx = SlaveTransaction.create(**self.params)
        tx.sign(self.alice)
        addresses_state = dict(self.addresses_state)
        addresses_state[self.alice.address].pbdata.balance = 100
        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)
        tx.apply(self.state, state_container)
        tx.revert(self.state, state_container)

        self.assertEqual(addresses_state[self.alice.address].balance, 100)
        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(
            [], state_container.paginated_tx_hash.key_value[storage_key])

        self.assertIn((tx.addr_from, tx.slave_pks[0]),
                      state_container.slaves.data)
        data = state_container.slaves.data[(tx.addr_from, tx.slave_pks[0])]
        self.assertIsInstance(data, SlaveMetadata)
        self.assertEqual(tx.access_types[0], data.access_type)
        self.assertEqual(tx.txhash, data.tx_hash)
    def test_apply(self):
        multi_sig_address = MultiSigAddressState.generate_multi_sig_address(
            b'')
        multi_sig_address_state = MultiSigAddressState.create(
            creation_tx_hash=b'',
            balance=100,
            signatories=[self.alice.address, self.bob.address],
            weights=[4, 6],
            threshold=5,
            transaction_hash_count=0)
        alice_address_state = OptimizedAddressState.get_default(
            self.alice.address)
        alice_address_state.pbdata.balance = 5
        bob_address_state = OptimizedAddressState.get_default(self.bob.address)
        addresses_state = {
            self.alice.address: alice_address_state,
            self.bob.address: bob_address_state,
            multi_sig_address: multi_sig_address_state,
        }

        tx = MultiSigSpend.create(multi_sig_address=multi_sig_address,
                                  addrs_to=[self.bob.address],
                                  amounts=[100],
                                  expiry_block_number=15000,
                                  fee=5,
                                  xmss_pk=self.alice.pk)
        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)

        self.assertFalse(
            state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse(
                self.alice.address, tx.ots_key))

        tx.apply(self.state, state_container)

        self.assertTrue(
            state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse(
                self.alice.address, tx.ots_key))
        self.assertIn(tx.txhash, state_container.votes_stats)
        vote_stats = state_container.votes_stats[tx.txhash]
        self.assertEqual(vote_stats.shared_key, tx.txhash)
        self.assertEqual(vote_stats.total_weight, 0)
        self.assertEqual(vote_stats.signatories,
                         multi_sig_address_state.signatories)
    def test_validate_all(self):
        """
        TODO: Check by signing txn from a non signatory address
        """
        multi_sig_address = MultiSigAddressState.generate_multi_sig_address(
            b'')
        tx = MultiSigSpend.create(multi_sig_address=multi_sig_address,
                                  addrs_to=[self.bob.address],
                                  amounts=[100],
                                  expiry_block_number=15000,
                                  fee=5,
                                  xmss_pk=self.random.pk,
                                  master_addr=self.alice.address)
        tx.sign(self.random)
        tx._data.nonce = 1
        alice_address_state = OptimizedAddressState.get_default(
            address=self.alice.address)
        alice_address_state.pbdata.balance = 5
        random_address_state = OptimizedAddressState.get_default(
            address=self.random.address)
        multi_sig_address_state = MultiSigAddressState.create(
            creation_tx_hash=b'',
            balance=100,
            signatories=[self.alice.address, self.bob.address],
            weights=[4, 6],
            threshold=5,
            transaction_hash_count=0)
        addresses_state = {
            self.alice.address: alice_address_state,
            self.random.address: random_address_state,
            multi_sig_address: multi_sig_address_state,
        }
        slaves = Indexer(b'slave', None)
        slaves.data[(self.alice.address,
                     self.random.pk)] = SlaveMetadata(access_type=0)

        state_container = StateContainer(addresses_state=addresses_state,
                                         tokens=Indexer(b'token', None),
                                         slaves=slaves,
                                         lattice_pk=Indexer(
                                             b'lattice_pk', None),
                                         multi_sig_spend_txs=dict(),
                                         votes_stats=dict(),
                                         block_number=10,
                                         total_coin_supply=100,
                                         current_dev_config=config.dev,
                                         write_access=False,
                                         my_db=self.state._db,
                                         batch=None)

        result = tx.validate_all(state_container)
        self.assertTrue(result)

        tx._data.nonce = 2
        result = tx.validate_all(state_container)
        self.assertFalse(result)  # False as nonce is invalid
Exemple #7
0
    def test_revert_transfer_token_txn_multi_send(self):
        """
        Alice has 1100 tokens and 100 xrd, 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_revert_transfer_txn(self, m_logger):
        """
        Alice has sent 100 coins to Bob, using 1 as Transaction fee. Now we need to undo this.
        """
        self.tx.sign(self.alice)
        ots_key = self.alice.ots_index - 1

        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
        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))
        self.tx.apply(self.state, state_container)
        self.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(0, addresses_state[self.alice.address].nonce)

        self.assertEqual(200, addresses_state[self.alice.address].balance)
        self.assertEqual(0, addresses_state[self.bob.address].balance)

        storage_key = state_container.paginated_tx_hash.generate_key(
            self.alice.address, 1)
        self.assertEqual(
            [], state_container.paginated_tx_hash.key_value[storage_key])

        storage_key = state_container.paginated_tx_hash.generate_key(
            self.bob.address, 1)
        self.assertEqual(
            [], state_container.paginated_tx_hash.key_value[storage_key])
    def test_apply_state_changes_owner_not_in_address_state(self):
        """
        In this case, Alice didn't give herself any tokens. How generous! She gave them all to Bob.
        """
        initial_balances = [
            xrd_pb2.AddressAmount(address=self.bob.address, amount=1000)
        ]
        self.params["initial_balances"] = initial_balances

        tx = TokenTransaction.create(**self.params)
        tx.sign(self.alice)

        # Signing the TX also generates the txhash, which we need to generate the AddressState properly.
        addresses_state = dict(self.addresses_state)
        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(addresses_state[self.bob.address].balance, 0)

        self.assertEqual(2, 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])

        self.assertEqual(1, len(state_container.tokens.data))
        self.assertIn((self.bob.address, tx.txhash),
                      state_container.tokens.data)
        self.assertEqual(
            1000,
            state_container.tokens.data[(self.bob.address, tx.txhash)].balance)
    def test_validate_extended(self, m_validate_slave, m_logger):
        """
        Message._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. addr_from ots_key reuse
        """
        m_addr_from_state = Mock(autospec=OptimizedAddressState, name='addr_from State', balance=100)

        m_addr_from_pk_state = Mock(autospec=OptimizedAddressState, name='addr_from_pk State')
        m_addr_from_pk_state.ots_key_reuse.return_value = False

        addresses_state = {
            self.alice.address: m_addr_from_state
        }

        tx = MessageTransaction.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=None,
                                         batch=None)
        result = tx._validate_extended(state_container)
        self.assertTrue(result)

        # fee = -1
        with patch('xrd.core.txs.MessageTransaction.MessageTransaction.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
        m_addr_from_state.balance = 0
        result = tx._validate_extended(state_container)
        self.assertFalse(result)
        m_addr_from_state.balance = 100

        self.params["message_hash"] = b'T' * 81

        # Validation should fail, as we have entered a message of more than 80 lengths
        tx = MessageTransaction.create(**self.params)
        self.assertFalse(tx._validate_extended(state_container))
    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))
Exemple #12
0
 def mock_new_state_container(self):
     addresses_state = {alice.address: self.alice_address_state}
     self.chain_manager.new_state_container.return_value = 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=5,
                                                                          total_coin_supply=0,
                                                                          current_dev_config=config.dev,
                                                                          write_access=False,
                                                                          my_db=None,
                                                                          batch=None)
    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)
    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_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_validate_extended(self, m_logger):
        """
        validate_extended() handles these parts of the validation:
        1. Master/slave
        2. balance, amount + fee from AddressState
        3. OTS key reuse from AddressState
        :return:
        """
        alice_address_state = OptimizedAddressState.get_default(
            self.alice.address)
        addresses_state = {self.alice.address: alice_address_state}
        alice_address_state.pbdata.balance = 200

        self.tx.validate_slave = Mock(autospec=Transaction.validate_slave,
                                      return_value=True)

        self.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 = self.tx.validate_all(state_container)
        self.assertTrue(result)

        # Suppose there was ots key reuse. The function should then return false.
        state_container.paginated_bitfield.set_ots_key(addresses_state,
                                                       self.tx.addr_from,
                                                       self.tx.ots_key)
        result = self.tx.validate_all(state_container)
        self.assertFalse(result)

        # Suppose the address doesn't have enough coins.
        alice_address_state.pbdata.balance = 99
        state_container.paginated_bitfield.set_ots_key(addresses_state,
                                                       self.tx.addr_from,
                                                       self.tx.ots_key)
        result = self.tx.validate_all(state_container)
        self.assertFalse(result)
    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)
Exemple #18
0
    def test_validate_extended(self):
        """
        CoinBase validate_extended() checks for
        1. valid coinbase address (the coinbase address must be config.dev.coinbase_address)
        2. valid addr_to
        then calls _validate_custom()
        """
        tx = MultiSigCreate.create(signatories=self.signatories,
                                   weights=self.weights,
                                   threshold=self.threshold,
                                   fee=5,
                                   xmss_pk=self.alice.pk)
        tx.sign(self.alice)
        alice_address_state = OptimizedAddressState.get_default(
            address=self.alice.address)
        alice_address_state.pbdata.balance = 5

        addresses_state = {
            self.alice.address: alice_address_state,
        }
        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=10,
                                         total_coin_supply=100,
                                         current_dev_config=config.dev,
                                         write_access=True,
                                         my_db=None,
                                         batch=None)

        result = tx._validate_extended(state_container)
        self.assertTrue(result)

        alice_address_state.pbdata.balance = 4
        result = tx._validate_extended(state_container)
        self.assertFalse(
            result)  # False due to insufficient balance to pay the txn fee

        alice_address_state.pbdata.balance = 6
        result = tx._validate_extended(state_container)
        self.assertTrue(result)
Exemple #19
0
    def test_validate_all(self):
        tx = MultiSigCreate.create(signatories=self.signatories,
                                   weights=self.weights,
                                   threshold=self.threshold,
                                   fee=5,
                                   xmss_pk=self.random.pk,
                                   master_addr=self.alice.address)
        tx.sign(self.random)
        tx.pbdata.nonce = 1

        alice_address_state = OptimizedAddressState.get_default(
            address=self.alice.address)
        alice_address_state.pbdata.balance = 5
        random_address_state = OptimizedAddressState.get_default(
            address=self.random.address)

        addresses_state = {
            self.alice.address: alice_address_state,
            self.random.address: random_address_state,
        }
        slaves = Indexer(b'slave', None)
        slaves.data[(self.alice.address,
                     self.random.pk)] = SlaveMetadata(access_type=0)
        state_container = StateContainer(addresses_state=addresses_state,
                                         tokens=Indexer(b'token', None),
                                         slaves=slaves,
                                         lattice_pk=Indexer(
                                             b'lattice_pk', None),
                                         multi_sig_spend_txs=dict(),
                                         votes_stats=dict(),
                                         block_number=10,
                                         total_coin_supply=100,
                                         current_dev_config=config.dev,
                                         write_access=False,
                                         my_db=self.state._db,
                                         batch=None)

        result = tx.validate_all(state_container)
        self.assertTrue(result)

        tx.pbdata.nonce = 2
        result = tx.validate_all(state_container)
        self.assertFalse(result)  # False as nonce is invalid
Exemple #20
0
    def test_revert_transfer_token_txn_send_tokens_to_self(self):
        """
        Alice has 1000 tokens and 100 xrd. She sends some tokens to herself.
        Can we undo this?
        """
        self.params["addrs_to"] = [self.alice.address]
        tx = TransferTokenTransaction.create(**self.params)
        tx.sign(self.alice)
        addresses_state = dict(self.addresses_state)
        addresses_state[self.alice.address].pbdata.balance = 100
        tokens = Indexer(b'token', None)
        tokens.data[(self.alice.address,
                     tx.token_txhash)] = TokenBalance(balance=100)
        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)
        # Unfortunately importing mock.call results in some sort of ValueError so I can't check the arguments.
        self.assertEqual(
            tokens.data[(self.alice.address, tx.token_txhash)].balance, 100)
    def test_apply_transfer_txn(self, m_logger):
        """
        apply_state_changes() is the part that actually updates everybody's balances.
        Then it forwards the addresses_state to _apply_state_changes_for_PK(), which updates everybody's addresses's
        nonce, OTS key index, and associated TX hashes
        If there is no AddressState for a particular Address, nothing is done.
        """
        self.tx.sign(self.alice)
        ots_key = self.alice.ots_index - 1
        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
        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))
        self.tx.apply(self.state, state_container)
        self.assertTrue(
            state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse(
                self.alice.address, ots_key))

        # Now Alice should have 99 coins left (200 - 100 - 1) and Bob should have 100 coins.
        self.assertEqual(99, addresses_state[self.alice.address].balance)
        self.assertEqual(100, addresses_state[self.bob.address].balance)
Exemple #22
0
    def test_apply_transfer_token_txn(self):
        """
        Alice has 1000 tokens and 100 xrd, Bob has none. Alice sends some tokens to Bob.
        """
        tx = TransferTokenTransaction.create(**self.params)
        tx.sign(self.alice)
        addresses_state = dict(self.addresses_state)
        tokens = Indexer(b'token', None)
        tokens.data[(self.alice.address,
                     tx.token_txhash)] = TokenBalance(balance=150)
        tokens.data[(self.bob.address,
                     tx.token_txhash)] = TokenBalance(balance=0)
        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)
        self.assertFalse(
            state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse(
                self.alice.address, 0))
        tx.apply(self.state, state_container)
        self.assertTrue(
            state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse(
                self.alice.address, 0))

        self.assertEqual(addresses_state[self.alice.address].balance, 99)
        self.assertEqual(addresses_state[self.bob.address].balance, 0)

        self.assertEqual(
            tokens.data[(self.alice.address, tx.token_txhash)].balance, 50)
        self.assertEqual(
            tokens.data[(self.bob.address, tx.token_txhash)].balance, 100)
Exemple #23
0
    def test_validate_extended(self, m_logger):
        """
        CoinBase validate_extended() checks for
        1. valid coinbase address (the coinbase address must be config.dev.coinbase_address)
        2. valid addr_to
        then calls _validate_custom()
        """
        tx = CoinBase.create(config.dev, self.amount, self.alice.address, self.mock_blockheader.block_number)
        tx._data.master_addr = self.alice.address

        addresses_state = {
            config.dev.coinbase_address: OptimizedAddressState.get_default(config.dev.coinbase_address),
            self.alice.address: OptimizedAddressState.get_default(self.alice.address),
        }
        addresses_state[config.dev.coinbase_address].pbdata.balance = 1000000

        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=self.mock_blockheader.block_number,
                                         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.assertFalse(result)

        tx._data.master_addr = config.dev.coinbase_address
        with patch('xrd.core.txs.CoinBase.CoinBase.addr_to', new_callable=PropertyMock) as m_addr_to:
            m_addr_to.return_value = b'Fake Address'
            result = tx._validate_extended(state_container)
            self.assertFalse(result)

        result = tx._validate_extended(state_container)
        self.assertTrue(result)
Exemple #24
0
    def test_revert_transfer_token_txn_empty_addresses_state(self):
        """
        If we didn't have any AddressStates for the addresses involved in this test, do nothing
        """
        tx = TransferTokenTransaction.create(**self.params)
        tx.sign(self.alice)
        addresses_state = dict(self.addresses_state)
        tokens = Indexer(b'token', None)
        tokens.data[(self.alice.address,
                     tx.token_txhash)] = TokenBalance(balance=100)
        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(
            100, tokens.data[(self.alice.address, tx.token_txhash)].balance)
        self.assertEqual(
            0, tokens.data[(self.bob.address, tx.token_txhash)].balance)
    def test_apply_state_changes_for_PK(self, m_logger):
        """
        This updates the node's AddressState database with which OTS index a particular address should be on, and what
        tx hashes is this address associated with.
        Curiously enough, if the TX was signed by a master XMSS tree, it doesn't add this tx's txhash to the list of
        txs that address is associated with.
        :return:
        """
        addresses_state = {
            self.alice.address:
            OptimizedAddressState.get_default(self.alice.address)
        }
        self.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))
        self.tx._apply_state_changes_for_PK(state_container)
        self.assertTrue(
            state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse(
                self.alice.address, ots_key))

        self.assertEqual(1, addresses_state[self.alice.address].nonce)
    def test_validate_extended(self):
        """
        TODO: Check by signing txn from a non signatory address
        """
        multi_sig_address = MultiSigAddressState.generate_multi_sig_address(
            b'')
        tx = MultiSigSpend.create(multi_sig_address=multi_sig_address,
                                  addrs_to=[self.bob.address],
                                  amounts=[100],
                                  expiry_block_number=15000,
                                  fee=5,
                                  xmss_pk=self.alice.pk)
        tx.sign(self.alice)

        alice_address_state = OptimizedAddressState.get_default(
            address=self.alice.address)
        alice_address_state.pbdata.balance = 5
        multi_sig_address_state = MultiSigAddressState.create(
            creation_tx_hash=b'',
            balance=100,
            signatories=[self.alice.address, self.bob.address],
            weights=[4, 6],
            threshold=5,
            transaction_hash_count=0)
        addresses_state = {
            self.alice.address: alice_address_state,
            multi_sig_address: multi_sig_address_state,
        }
        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=10,
                                         total_coin_supply=100,
                                         current_dev_config=config.dev,
                                         write_access=True,
                                         my_db=None,
                                         batch=None)

        result = tx._validate_extended(state_container)
        self.assertTrue(result)

        alice_address_state.pbdata.balance = 0
        result = tx._validate_extended(state_container)
        self.assertFalse(result)

        alice_address_state.pbdata.balance = 5
        result = tx._validate_extended(state_container)
        self.assertTrue(result)

        multi_sig_address_state.pbdata.balance = 99
        result = tx._validate_extended(state_container)
        self.assertFalse(result)

        multi_sig_address_state.pbdata.balance = 100
        result = tx._validate_extended(state_container)
        self.assertTrue(result)

        tx.pbdata.multi_sig_spend.expiry_block_number = 10
        result = tx._validate_extended(state_container)
        self.assertFalse(result)

        tx.pbdata.multi_sig_spend.expiry_block_number = 15000
        result = tx._validate_extended(state_container)
        self.assertTrue(result)
Exemple #27
0
    def test_validate_extended(self):
        multi_sig_address = MultiSigAddressState.generate_multi_sig_address(
            b'')
        spend_tx = MultiSigSpend.create(multi_sig_address=multi_sig_address,
                                        addrs_to=[self.alice.address],
                                        amounts=[100],
                                        expiry_block_number=15000,
                                        fee=0,
                                        xmss_pk=self.alice.pk)
        spend_tx.sign(self.alice)
        tx = MultiSigVote.create(shared_key=spend_tx.txhash,
                                 unvote=False,
                                 fee=5,
                                 xmss_pk=self.alice.pk)
        tx.sign(self.alice)

        alice_address_state = OptimizedAddressState.get_default(
            address=self.alice.address)
        alice_address_state.pbdata.balance = 5
        multi_sig_address_state = MultiSigAddressState.create(
            creation_tx_hash=b'',
            balance=100,
            signatories=[self.alice.address, self.bob.address],
            weights=[4, 6],
            threshold=5,
            transaction_hash_count=0)
        addresses_state = {
            self.alice.address: alice_address_state,
            multi_sig_address: multi_sig_address_state,
        }
        vote_stats = {
            spend_tx.txhash:
            VoteStats.create(multi_sig_address=multi_sig_address,
                             shared_key=spend_tx.txhash,
                             signatories=multi_sig_address_state.signatories,
                             expiry_block_number=spend_tx.expiry_block_number),
        }
        multi_sig_spend_txs = {
            spend_tx.txhash: spend_tx,
        }
        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=multi_sig_spend_txs,
            votes_stats=vote_stats,
            block_number=10,
            total_coin_supply=100,
            current_dev_config=config.dev,
            write_access=True,
            my_db=None,
            batch=None)

        result = tx._validate_extended(state_container)
        self.assertTrue(result)

        tx._data.multi_sig_vote.unvote = True
        result = tx._validate_extended(state_container)
        self.assertFalse(result)

        tx._data.multi_sig_vote.unvote = False
        result = tx._validate_extended(state_container)
        self.assertTrue(result)

        alice_address_state.pbdata.balance = 0
        result = tx._validate_extended(state_container)
        self.assertFalse(result)

        alice_address_state.pbdata.balance = 5
        result = tx._validate_extended(state_container)
        self.assertTrue(result)

        state_container.block_number = 15000
        result = tx._validate_extended(state_container)
        self.assertTrue(result)

        state_container.block_number = 15001
        result = tx._validate_extended(state_container)
        self.assertFalse(result)
Exemple #28
0
    def test_validate_all(self):
        """
        Test for Validate Extended when transaction has been signed by slave.
        :return:
        """
        multi_sig_address = MultiSigAddressState.generate_multi_sig_address(
            b'')
        spend_tx = MultiSigSpend.create(multi_sig_address=multi_sig_address,
                                        addrs_to=[self.alice.address],
                                        amounts=[100],
                                        expiry_block_number=15000,
                                        fee=0,
                                        xmss_pk=self.alice.pk)
        spend_tx.sign(self.alice)
        tx = MultiSigVote.create(shared_key=spend_tx.txhash,
                                 unvote=False,
                                 fee=5,
                                 xmss_pk=self.random.pk,
                                 master_addr=self.alice.address)
        tx.sign(self.random)
        tx._data.nonce = 1
        alice_address_state = OptimizedAddressState.get_default(
            address=self.alice.address)
        alice_address_state.pbdata.balance = 5
        random_address_state = OptimizedAddressState.get_default(
            address=self.random.address)
        multi_sig_address_state = MultiSigAddressState.create(
            creation_tx_hash=b'',
            balance=100,
            signatories=[self.alice.address, self.bob.address],
            weights=[4, 6],
            threshold=5,
            transaction_hash_count=0)
        addresses_state = {
            self.alice.address: alice_address_state,
            self.random.address: random_address_state,
            multi_sig_address: multi_sig_address_state,
        }
        vote_stats = {
            spend_tx.txhash:
            VoteStats.create(multi_sig_address=multi_sig_address,
                             shared_key=spend_tx.txhash,
                             signatories=multi_sig_address_state.signatories,
                             expiry_block_number=spend_tx.expiry_block_number),
        }
        multi_sig_spend_txs = {
            spend_tx.txhash: spend_tx,
        }
        slaves = Indexer(b'slave', None)
        slaves.data[(self.alice.address,
                     self.random.pk)] = SlaveMetadata(access_type=0)
        state_container = StateContainer(
            addresses_state=addresses_state,
            tokens=Indexer(b'token', None),
            slaves=slaves,
            lattice_pk=Indexer(b'lattice_pk', None),
            multi_sig_spend_txs=multi_sig_spend_txs,
            votes_stats=vote_stats,
            block_number=10,
            total_coin_supply=100,
            current_dev_config=config.dev,
            write_access=False,
            my_db=self.state._db,
            batch=None)

        result = tx.validate_all(state_container)
        self.assertTrue(result)

        tx._data.nonce = 2
        result = tx.validate_all(state_container)
        self.assertFalse(result)  # False as nonce is invalid
Exemple #29
0
    def test_revert_multi_sig_create_txn(self):
        addresses_state = {
            self.alice.address:
            OptimizedAddressState.get_default(self.alice.address),
            self.bob.address:
            OptimizedAddressState.get_default(self.bob.address),
            self.random.address:
            OptimizedAddressState.get_default(self.random.address),
            self.random_signer.address:
            OptimizedAddressState.get_default(self.random_signer.address),
        }
        addresses_state[self.random_signer.address].pbdata.balance = 200
        tx = MultiSigCreate.create(self.signatories, self.weights,
                                   self.threshold, 1, self.random_signer.pk)
        tx.sign(self.random_signer)

        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.random_signer.address, tx.ots_key))

        tx.apply(self.state, state_container)

        self.assertEqual(200 - tx.fee,
                         addresses_state[self.random_signer.address].balance)

        storage_key = state_container.paginated_tx_hash.generate_key(
            self.random_signer.address, 1)
        self.assertEqual(
            [tx.txhash],
            state_container.paginated_tx_hash.key_value[storage_key])
        for signatory_address in self.signatories:
            storage_key = state_container.paginated_tx_hash.generate_key(
                signatory_address, 1)
            self.assertEqual(
                [tx.txhash],
                state_container.paginated_tx_hash.key_value[storage_key])

        self.assertTrue(
            state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse(
                self.random_signer.address, tx.ots_key))
        AddressState.put_addresses_state(self.state, addresses_state)
        state_container.paginated_multisig_address.put_paginated_data(None)
        multi_sig_addresses_state = MultiSigAddressState.get_multi_sig_address_state_by_address(
            self.state._db,
            MultiSigAddressState.generate_multi_sig_address(tx.txhash))

        self.assertEqual(self.signatories,
                         multi_sig_addresses_state.signatories)
        self.assertEqual(self.weights, multi_sig_addresses_state.weights)
        self.assertEqual(self.threshold, multi_sig_addresses_state.threshold)

        for signatory_address in self.signatories:
            multi_sig_addresses = state_container.paginated_multisig_address.get_paginated_data(
                signatory_address, 1)
            self.assertEqual(len(multi_sig_addresses), 1)

        tx.revert(self.state, state_container)
        state_container.paginated_multisig_address.put_paginated_data(None)
        self.assertFalse(
            state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse(
                self.random_signer.address, tx.ots_key))
        self.assertIsNone(
            MultiSigAddressState.get_multi_sig_address_state_by_address(
                self.state._db,
                MultiSigAddressState.generate_multi_sig_address(tx.txhash)))

        for signatory_address in self.signatories:
            multi_sig_addresses = state_container.paginated_multisig_address.get_paginated_data(
                signatory_address, 1)
            self.assertEqual(len(multi_sig_addresses), 0)
Exemple #30
0
    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('xrd.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('xrd.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))