Exemplo n.º 1
0
    def relay_token_txn_by_slave(self, symbol: str, name: str,
                                 owner_qaddress: str, decimals: int,
                                 qaddresses: list, amounts: list, fee: int,
                                 master_qaddress):
        self.authenticate()

        if len(qaddresses) != len(amounts):
            raise Exception("Number of Addresses & Amounts Mismatch")

        index, group_index, slave_index, slave_xmss = self.get_slave_xmss(
            master_qaddress)
        if slave_index == -1:
            raise Exception("No Slave Found")

        initial_balances = []
        for idx, qaddress in enumerate(qaddresses):
            initial_balances.append(
                qrl_pb2.AddressAmount(
                    address=self.qaddress_to_address(qaddress),
                    amount=amounts[idx]))
        tx = TokenTransaction.create(
            symbol=symbol.encode(),
            name=name.encode(),
            owner=self.qaddress_to_address(owner_qaddress),
            decimals=decimals,
            initial_balances=initial_balances,
            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_apply_token_txn_signed_by_slave_xmss(self):
        """
        Alice creates a token, gives herself and Bob some tokens.
        But she uses a XMSS slave to sign it.
        """
        initial_balances = [qrl_pb2.AddressAmount(address=self.alice.address, amount=1000),
                            qrl_pb2.AddressAmount(address=self.bob.address, amount=2000)]
        slave = get_slave_xmss()
        self.params["initial_balances"] = initial_balances
        self.params["xmss_pk"] = slave.pk
        self.params["master_addr"] = self.alice.address
        tx = TokenTransaction.create(**self.params)
        tx.sign(slave)

        # Now that we have the Slave XMSS address, we should add it to AddressState so that apply_state_changes()
        # can do something with it
        addresses_state = dict(self.addresses_state)
        addresses_state[slave.address] = OptimizedAddressState.get_default(slave.address)
        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(3, 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])

        storage_key = state_container.paginated_tx_hash.generate_key(slave.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(2, len(state_container.tokens.data))
        self.assertIn((self.bob.address, tx.txhash), state_container.tokens.data)
        self.assertEqual(1000, state_container.tokens.data[(self.alice.address, tx.txhash)].balance)
        self.assertEqual(2000, state_container.tokens.data[(self.bob.address, tx.txhash)].balance)

        self.assertTrue(state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse(slave.address, 0))
        self.assertFalse(state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse(self.alice.address, 0))
        self.assertFalse(state_container.paginated_bitfield.load_bitfield_and_ots_key_reuse(self.bob.address, 0))
Exemplo n.º 3
0
    def test_affected_address(self, m_logger):
        tx = TokenTransaction.create(**self.params)
        # Default params should result in 2 affected addresses
        result = set()
        tx.set_affected_address(result)
        self.assertEqual(2, len(result))

        # If the slave is a recipient of tokens, he should be included too.
        slave = get_slave_xmss()
        result = set()
        self.initial_balances_valid.append(
            qrl_pb2.AddressAmount(address=slave.address, amount=1000))
        tx = TokenTransaction.create(
            symbol=b'QRL',
            name=b'Quantum Resistant Ledger',
            owner=self.alice.address,
            decimals=15,
            initial_balances=self.initial_balances_valid,
            fee=1,
            xmss_pk=self.alice.pk)
        tx.set_affected_address(result)
        self.assertEqual(3, len(result))
    def test_apply_token_txn(self):
        """
        Alice creates a token. Obviously, she gives herself some of this token.
        But she also gives Bob some tokens too.
        """
        initial_balances = [qrl_pb2.AddressAmount(address=self.alice.address, amount=1000),
                            qrl_pb2.AddressAmount(address=self.bob.address, amount=2000)]
        self.params["initial_balances"] = initial_balances

        tx = TokenTransaction.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=1000,
                                         current_dev_config=config.dev,
                                         write_access=True,
                                         my_db=self.state._db,
                                         batch=None)

        # According to the State, Alice has 100 coins, and Bob has 0 coins.
        # After applying the Transaction, Alice and Bob should have 1000 tokens, and Alice's balance should be 99.
        # AddressState.transaction_hashes now also reference the TokenTransaction that created the Tokens.
        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(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(2, len(state_container.tokens.data))
        self.assertIn((self.alice.address, tx.txhash), state_container.tokens.data)
        self.assertEqual(1000, state_container.tokens.data[(self.alice.address, tx.txhash)].balance)
        self.assertIn((self.bob.address, tx.txhash), state_container.tokens.data)
        self.assertEqual(2000, state_container.tokens.data[(self.bob.address, tx.txhash)].balance)
    def test_revert_token_txn_owner_not_in_address_state(self):
        """
        In this case, Alice didn't give herself any tokens. How generous! She gave them all to Bob.
        But we want to revert this.
        """
        initial_balances = [qrl_pb2.AddressAmount(address=self.bob.address, amount=1000)]
        self.params["initial_balances"] = initial_balances

        tx = TokenTransaction.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=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(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([], 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([], 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(0, state_container.tokens.data[(self.bob.address, tx.txhash)].balance)
Exemplo n.º 6
0
 def create_token_txn(symbol: bytes,
                      name: bytes,
                      owner: bytes,
                      decimals: int,
                      initial_balances,
                      fee: int,
                      xmss_pk: bytes,
                      master_addr: bytes):
     return TokenTransaction.create(symbol,
                                    name,
                                    owner,
                                    decimals,
                                    initial_balances,
                                    fee,
                                    xmss_pk,
                                    master_addr)
    def test_validate_tx(self):
        initial_balances = [qrl_pb2.AddressAmount(address=self.alice.address, amount=1000),
                            qrl_pb2.AddressAmount(address=self.bob.address, amount=1000)]
        slave = get_slave_xmss()
        self.params["initial_balances"] = initial_balances
        self.params["xmss_pk"] = slave.pk
        self.params["master_addr"] = self.alice.address
        tx = TokenTransaction.create(**self.params)
        tx.sign(slave)

        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()
Exemplo n.º 8
0
def get_token_transaction(xmss1,
                          xmss2,
                          amount1=400000000,
                          amount2=200000000,
                          fee=1) -> TokenTransaction:
    initial_balances = list()
    initial_balances.append(
        qrl_pb2.AddressAmount(address=xmss1.address, amount=amount1))
    initial_balances.append(
        qrl_pb2.AddressAmount(address=xmss2.address, amount=amount2))

    return TokenTransaction.create(symbol=b'QRL',
                                   name=b'Quantum Resistant Ledger',
                                   owner=xmss1.address,
                                   decimals=4,
                                   initial_balances=initial_balances,
                                   fee=fee,
                                   xmss_pk=xmss1.pk)
Exemplo n.º 9
0
    def test_to_json(self, m_logger):
        initial_balances = list()
        initial_balances.append(
            qrl_pb2.AddressAmount(address=self.alice.address,
                                  amount=400000000))
        initial_balances.append(
            qrl_pb2.AddressAmount(address=self.bob.address, amount=200000000))
        tx = TokenTransaction.create(
            symbol=b'QRL',
            name=b'Quantum Resistant Ledger',
            owner=
            b'\x01\x03\x17F=\xcdX\x1bg\x9bGT\xf4ld%\x12T\x89\xa2\x82h\x94\xe3\xc4*Y\x0e\xfbh\x06E\x0c\xe6\xbfRql',
            decimals=4,
            initial_balances=initial_balances,
            fee=1,
            xmss_pk=self.alice.pk)
        txjson = tx.to_json()

        self.assertEqual(json.loads(test_json_Token), json.loads(txjson))
Exemplo n.º 10
0
    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 = [qrl_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)
Exemplo n.º 11
0
 def make_tx(self, **kwargs):
     self.params.update(kwargs)
     tx = TokenTransaction.create(**self.params)
     return tx
Exemplo n.º 12
0
    def test_validate_extended(self, m_validate_slave, m_logger):
        """
        TokenTransaction.validate_extended checks for:
        1. valid master/slave
        2. from address is valid
        3. owner address is valid
        4. addresses that own the initial balances are valid
        5. that the AddressState has enough coins to pay the Transaction fee (because no coins are being transferred)
        6. OTS key reuse
        """
        tx = TokenTransaction.create(**self.params)

        m_addr_from_state = Mock(autospec=AddressState,
                                 name='addr_from State',
                                 balance=100)
        m_addr_from_pk_state = Mock(autospec=AddressState,
                                    name='addr_from_pk State')
        m_addr_from_pk_state.ots_key_reuse.return_value = False
        tx.sign(self.alice)
        result = tx.validate_extended(m_addr_from_state, m_addr_from_pk_state)
        self.assertTrue(result)

        m_validate_slave.return_value = False
        result = tx.validate_extended(m_addr_from_state, m_addr_from_pk_state)
        self.assertFalse(result)

        m_validate_slave.return_value = True
        with patch('qrl.core.txs.TokenTransaction.TokenTransaction.addr_from',
                   new_callable=PropertyMock) as m_addr_from:
            m_addr_from.return_value = b'Invalid Address'
            result = tx.validate_extended(m_addr_from_state,
                                          m_addr_from_pk_state)
            self.assertFalse(result)

        with patch('qrl.core.txs.TokenTransaction.TokenTransaction.owner',
                   new_callable=PropertyMock) as m_owner:
            m_owner.return_value = b'Invalid Address'
            result = tx.validate_extended(m_addr_from_state,
                                          m_addr_from_pk_state)
            self.assertFalse(result)

        with patch(
                'qrl.core.txs.TokenTransaction.TokenTransaction.initial_balances',
                new_callable=PropertyMock) as m_address_balance:
            m_address_balance.return_value = [
                qrl_pb2.AddressAmount(address=b'Invalid Address 1',
                                      amount=1000),
                qrl_pb2.AddressAmount(address=b'Invalid Address 2',
                                      amount=1000)
            ]
            result = tx.validate_extended(m_addr_from_state,
                                          m_addr_from_pk_state)
            self.assertFalse(result)

        m_addr_from_state.balance = 0
        result = tx.validate_extended(m_addr_from_state, m_addr_from_pk_state)
        self.assertFalse(result)
        m_addr_from_state.balance = 100

        m_addr_from_pk_state.ots_key_reuse.return_value = True
        result = tx.validate_extended(m_addr_from_state, m_addr_from_pk_state)
        self.assertFalse(result)
Exemplo n.º 13
0
def tx_token(ctx, src, master, symbol, name, owner, decimals, fee,
             ots_key_index):
    """
    Create Token Transaction, that results into the formation of new token if accepted.
    """

    initial_balances = []

    if decimals > 19:
        click.echo(
            "The number of decimal cannot exceed 19 under any possible configuration"
        )
        quit(1)

    while True:
        address = click.prompt('Address ', default='')
        if address == '':
            break
        amount = int(click.prompt('Amount ')) * (10**int(decimals))
        initial_balances.append(
            qrl_pb2.AddressAmount(address=parse_qaddress(address),
                                  amount=amount))

    try:
        _, src_xmss = _select_wallet(ctx, src)
        if not src_xmss:
            click.echo("A local wallet is required to sign the transaction")
            quit(1)

        address_src_pk = src_xmss.pk

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

        address_owner = parse_qaddress(owner)
        master_addr = None
        if master:
            master_addr = parse_qaddress(master)
        # FIXME: This could be problematic. Check
        fee_shor = _quanta_to_shor(fee)

        if len(name) > config.dev.max_token_name_length:
            raise Exception("Token name must be shorter than {} chars".format(
                config.dev.max_token_name_length))
        if len(symbol) > config.dev.max_token_symbol_length:
            raise Exception(
                "Token symbol must be shorter than {} chars".format(
                    config.dev.max_token_symbol_length))

    except KeyboardInterrupt:
        click.echo("Terminated by user")
        quit(1)
    except Exception as e:
        click.echo("Error validating arguments: {}".format(e))
        quit(1)

    try:
        stub = ctx.obj.get_stub_public_api()
        tx = TokenTransaction.create(symbol=symbol.encode(),
                                     name=name.encode(),
                                     owner=address_owner,
                                     decimals=decimals,
                                     initial_balances=initial_balances,
                                     fee=fee_shor,
                                     xmss_pk=address_src_pk,
                                     master_addr=master_addr)

        tx.sign(src_xmss)

        push_transaction_req = qrl_pb2.PushTransactionReq(
            transaction_signed=tx.pbdata)
        push_transaction_resp = stub.PushTransaction(
            push_transaction_req, timeout=CONNECTION_TIMEOUT)

        print(push_transaction_resp.error_code)
    except Exception as e:
        print("Error {}".format(str(e)))
Exemplo n.º 14
0
    def test_validate_extended(self, m_validate_slave, m_logger):
        """
        TokenTransaction._validate_extended checks for:
        1. valid master/slave
        2. from address is valid
        3. owner address is valid
        4. addresses that own the initial balances are valid
        5. that the AddressState has enough coins to pay the Transaction fee (because no coins are being transferred)
        6. OTS key reuse
        """
        alice_address_state = OptimizedAddressState.get_default(
            self.alice.address)
        alice_address_state.pbdata.balance = 100

        tx = TokenTransaction.create(**self.params)
        tx.sign(self.alice)
        addresses_state = {alice_address_state.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=1,
                                         total_coin_supply=1000,
                                         current_dev_config=config.dev,
                                         write_access=True,
                                         my_db=self.state._db,
                                         batch=None)
        result = tx._validate_extended(state_container)
        self.assertTrue(result)

        m_validate_slave.return_value = False
        result = tx.validate_all(state_container)
        self.assertFalse(result)
        m_validate_slave.return_value = True

        with patch('qrl.core.txs.TokenTransaction.TokenTransaction.addr_from',
                   new_callable=PropertyMock) as m_addr_from:
            m_addr_from.return_value = b'Invalid Address'
            result = tx._validate_extended(state_container)
            self.assertFalse(result)

        with patch('qrl.core.txs.TokenTransaction.TokenTransaction.owner',
                   new_callable=PropertyMock) as m_owner:
            m_owner.return_value = b'Invalid Address'
            result = tx._validate_extended(state_container)
            self.assertFalse(result)

        with patch(
                'qrl.core.txs.TokenTransaction.TokenTransaction.initial_balances',
                new_callable=PropertyMock) as m_address_balance:
            m_address_balance.return_value = [
                qrl_pb2.AddressAmount(address=b'Invalid Address 1',
                                      amount=1000),
                qrl_pb2.AddressAmount(address=b'Invalid Address 2',
                                      amount=1000)
            ]
            result = tx._validate_extended(state_container)
            self.assertFalse(result)

        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)

        # Token symbol too long
        tx = self.make_tx(symbol=b'QRLSQRLSQRL')
        tx.sign(self.alice)
        self.assertFalse(tx._validate_extended(state_container))

        # Token name too long
        tx = self.make_tx(name=b'Quantum Resistant LedgerQuantum')
        tx.sign(self.alice)
        self.assertFalse(tx._validate_extended(state_container))

        # Token symbol missing
        with self.assertRaises(ValueError):
            tx = self.make_tx(symbol=b'')
            tx.sign(self.alice)
            self.assertFalse(tx._validate_extended(state_container))

        # Token name missing
        with self.assertRaises(ValueError):
            tx = self.make_tx(name=b'')
            tx.sign(self.alice)
            tx._validate_extended(state_container)

        # Empty initial_balances
        with self.assertRaises(ValueError):
            tx = self.make_tx(initial_balances=[])
            tx.sign(self.alice)
            self.assertFalse(tx._validate_extended(state_container))

        # Invalid initial balances... 0!
        with self.assertRaises(ValueError):
            initial_balances_0_0 = [
                qrl_pb2.AddressAmount(address=self.alice.address, amount=0),
                qrl_pb2.AddressAmount(address=self.bob.address, amount=0)
            ]
            tx = self.make_tx(initial_balances=initial_balances_0_0)
            tx.sign(self.alice)
            self.assertFalse(tx._validate_extended(state_container))

        # Fee is -1
        with patch('qrl.core.txs.TokenTransaction.TokenTransaction.fee',
                   new_callable=PropertyMock) as m_fee:
            m_fee.return_value = -1
            with self.assertRaises(ValueError):
                tx = self.make_tx()
                tx.sign(self.alice)