示例#1
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)
示例#2
0
 def generate_slave_tx(self,
                       signer_pk: bytes,
                       slave_pk_list: list,
                       master_addr=None):
     return SlaveTransaction.create(slave_pks=slave_pk_list,
                                    access_types=[0] * len(slave_pk_list),
                                    fee=0,
                                    xmss_pk=signer_pk,
                                    master_addr=master_addr)
示例#3
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)
示例#4
0
 def create_slave_tx(slave_pks: list,
                     access_types: list,
                     fee: int,
                     xmss_pk: bytes,
                     master_addr: bytes) -> SlaveTransaction:
     return SlaveTransaction.create(slave_pks=slave_pks,
                                    access_types=access_types,
                                    fee=fee,
                                    xmss_pk=xmss_pk,
                                    master_addr=master_addr)
示例#5
0
    def test_validate_custom(self, m_logger):
        """
        SlaveTransaction._validate_custom() checks for the following things:
        1. if you specify more than 100 slave_pks at once
        2. if len(slave_pks) != len(access_types)
        3. access_types can only be 0, 1
        """
        # Unequal length slave_pks and access_types
        params = self.params.copy()
        params["slave_pks"] = [self.slave.pk]
        params["access_types"] = [0, 1]
        with self.assertRaises(ValueError):
            SlaveTransaction.create(**params)

        # access_type is a weird, undefined number
        params = self.params.copy()
        params["access_types"] = [5]
        with self.assertRaises(ValueError):
            SlaveTransaction.create(**params)
示例#6
0
    def test_validate_tx(self, m_logger):
        tx = SlaveTransaction.create(**self.params)
        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()
示例#7
0
def slave_tx_generate(ctx, src, master, number_of_slaves, access_type, fee, pk, ots_key_index):
    """
    Generates Slave Transaction for the wallet
    """
    try:
        _, src_xmss = _select_wallet(ctx, src)

        ots_key_index = validate_ots_index(ots_key_index, src_xmss)
        src_xmss.set_ots_index(ots_key_index)

        if src_xmss:
            address_src_pk = src_xmss.pk
        else:
            address_src_pk = pk.encode()

        master_addr = None
        if master:
            master_addr = parse_qaddress(master)
        fee_shor = _quanta_to_shor(fee)
    except Exception as e:
        click.echo("Error validating arguments: {}".format(e))
        quit(1)

    slave_xmss = []
    slave_pks = []
    access_types = []
    slave_xmss_seed = []
    if number_of_slaves > 100:
        click.echo("Error: Max Limit for the number of slaves is 100")
        quit(1)

    for i in range(number_of_slaves):
        print("Generating Slave #" + str(i + 1))
        xmss = XMSS.from_height(config.dev.xmss_tree_height)
        slave_xmss.append(xmss)
        slave_xmss_seed.append(xmss.extended_seed)
        slave_pks.append(xmss.pk)
        access_types.append(access_type)
        print("Successfully Generated Slave %s/%s" % (str(i + 1), number_of_slaves))

    try:
        tx = SlaveTransaction.create(slave_pks=slave_pks,
                                     access_types=access_types,
                                     fee=fee_shor,
                                     xmss_pk=address_src_pk,
                                     master_addr=master_addr)
        tx.sign(src_xmss)
        with open('slaves.json', 'w') as f:
            json.dump([bin2hstr(src_xmss.address), slave_xmss_seed, tx.to_json()], f)
        click.echo('Successfully created slaves.json')
        click.echo('Move slaves.json file from current directory to the mining node inside ~/.xrd/')
    except Exception as e:
        click.echo("Unhandled error: {}".format(str(e)))
        quit(1)
示例#8
0
    def relay_slave_txn(self, slave_pks: list, access_types: 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 = SlaveTransaction.create(
            slave_pks=slave_pks,
            access_types=access_types,
            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)
示例#9
0
def get_slaves(alice_ots_index, txn_nonce):
    # [master_address: bytes, slave_seeds: list, slave_txn: json]

    slave_xmss = get_slave_xmss()
    alice_xmss = get_alice_xmss()

    alice_xmss.set_ots_index(alice_ots_index)
    slave_txn = SlaveTransaction.create([slave_xmss.pk], [1], 0, alice_xmss.pk)
    slave_txn._data.nonce = txn_nonce
    slave_txn.sign(alice_xmss)

    slave_data = json.loads(
        json.dumps([
            bin2hstr(alice_xmss.address), [slave_xmss.extended_seed],
            slave_txn.to_json()
        ]))
    slave_data[0] = bytes(hstr2bin(slave_data[0]))
    return slave_data
示例#10
0
    def relay_slave_txn_by_slave(self, slave_pks: list, access_types: 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 = SlaveTransaction.create(
            slave_pks=slave_pks,
            access_types=access_types,
            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)
示例#11
0
    def create_block(self, prev_hash, mining_address=None):
        if not mining_address:
            mining_address = self.alice_xmss.address
        transactions = []
        block_prev = self.xrdnode.get_block_from_hash(prev_hash)
        block_idx = block_prev.block_number + 1

        if block_idx == 1:
            slave_tx = SlaveTransaction.create(slave_pks=[self.bob_xmss.pk],
                                               access_types=[0],
                                               fee=0,
                                               xmss_pk=self.alice_xmss.pk)
            slave_tx.sign(self.alice_xmss)
            slave_tx._data.nonce = 1
            transactions = [slave_tx]

        time_offset = 60
        if block_idx % 2 == 0:
            time_offset += 2

        self.time_mock.return_value = self.time_mock.return_value + time_offset
        self.ntp_mock.return_value = self.ntp_mock.return_value + time_offset

        block_new = Block.create(dev_config=config.dev,
                                 block_number=block_idx,
                                 prev_headerhash=block_prev.headerhash,
                                 prev_timestamp=block_prev.timestamp,
                                 transactions=transactions,
                                 miner_address=mining_address,
                                 seed_height=0,
                                 seed_hash=None)

        dev_config = self.xrdnode._chain_manager.get_config_by_block_number(
            block_new.block_number)
        while not self.xrdnode._chain_manager.validate_mining_nonce(
                blockheader=block_new.blockheader, dev_config=dev_config):
            block_new.set_nonces(config.dev, block_new.mining_nonce + 1, 0)

        return block_new
示例#12
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))
示例#13
0
 def test_create_validate(self, m_logger):
     """Default self.params should result in a valid SlaveTransaction"""
     tx = SlaveTransaction.create(**self.params)
     tx.sign(self.alice)
     result = tx.validate_or_raise()
     self.assertTrue(result)