Ejemplo n.º 1
0
    def test_validate_tx(self):
        initial_balances = list()
        initial_balances.append(
            qrl_pb2.AddressAmount(address=self.alice.get_address().encode(),
                                  amount=400000000))
        initial_balances.append(
            qrl_pb2.AddressAmount(address=self.bob.get_address().encode(),
                                  amount=200000000))
        tx = TokenTransaction.create(
            addr_from=self.alice.get_address().encode(),
            symbol=b'QRL',
            name=b'Quantum Resistant Ledger',
            owner=
            b'Q223bc5e5b78edfd778b1bf72702061cc053010711ffeefb9d969318be5d7b86b021b73c2',
            decimals=4,
            initial_balances=initial_balances,
            fee=1,
            xmss_pk=self.alice.pk(),
            xmss_ots_index=self.alice.get_index())

        # We must sign the tx before validation will work.
        tx.sign(self.alice)

        # We have not touched the tx: validation should pass.
        self.assertTrue(tx.validate_or_raise())
    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))
Ejemplo n.º 3
0
    def test_create(self, m_logger):
        # Alice creates Token
        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 = self.make_tx(decimals=4, initial_balances=initial_balances)

        self.assertTrue(tx)
Ejemplo n.º 4
0
    def test_validate_tx2(self, m_logger):
        initial_balances = list()
        initial_balances.append(
            qrl_pb2.AddressAmount(address=self.alice.address,
                                  amount=10000000000000000001))
        initial_balances.append(
            qrl_pb2.AddressAmount(address=self.bob.address,
                                  amount=10000000000000000001))

        # Transaction Validation should fail as the decimals is higher than the possible decimals
        with self.assertRaises(ValueError):
            self.make_tx(decimals=4, initial_balances=initial_balances)
    def test_revert_token_txn(self):
        """
        Same setup as in test_apply_state_changes(). This time though, the changes have already been applied,
        and we would like to roll them back.
        """
        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)
        # Apply the changes!
        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)

        # After applying the Transaction, it should be as if Alice had never created the tokens in the first place.
        tx.apply(self.state, state_container)
        tx.revert(self.state, state_container)

        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(2, len(state_container.tokens.data))
        self.assertIn((self.alice.address, tx.txhash), state_container.tokens.data)
        self.assertEqual(0, state_container.tokens.data[(self.alice.address, tx.txhash)].balance)
        self.assertIn((self.bob.address, tx.txhash), state_container.tokens.data)
        self.assertEqual(0, state_container.tokens.data[(self.bob.address, tx.txhash)].balance)
        self.assertEqual(0, addresses_state[self.alice.address].nonce)
Ejemplo n.º 6
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)
    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)
Ejemplo n.º 8
0
    def test_validate_tx(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 = self.make_tx(decimals=4, initial_balances=initial_balances)

        # We must sign the tx before validation will work.
        tx.sign(self.alice)

        # We have not touched the tx: validation should pass.
        self.assertTrue(tx.validate_or_raise())
Ejemplo n.º 9
0
    def setUp(self):
        self.initial_balances_valid = [
            qrl_pb2.AddressAmount(address=self.alice.address, amount=1000),
            qrl_pb2.AddressAmount(address=self.bob.address, amount=1000)
        ]

        self.params = {
            "symbol": b'QRL',
            "name": b'Quantum Resistant Ledger',
            "owner": self.alice.address,
            "decimals": self._decimals,
            "initial_balances": self.initial_balances_valid,
            "fee": 1,
            "xmss_pk": self.alice.pk
        }
Ejemplo n.º 10
0
    def relay_token_txn(self, symbol: str, name: str, owner_qaddress: str,
                        decimals: int, qaddresses: list, amounts: list,
                        fee: int, master_qaddress, signer_address: str,
                        ots_index: int):
        self.authenticate()

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

        index, xmss = self._get_wallet_index_xmss(signer_address, ots_index)

        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=xmss.pk,
            master_addr=self.qaddress_to_address(master_qaddress))

        self._push_transaction(tx, xmss)
        self._wallet.set_ots_index(index, xmss.ots_index)

        return self.to_plain_transaction(tx.pbdata)
Ejemplo n.º 11
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)
Ejemplo n.º 12
0
def tx_token(ctx, src, symbol, name, owner, decimals, fee, ots_key_index):
    """
    Create Token Transaction, that results into the formation of new token if accepted.
    """

    if not ctx.obj.remote:
        click.echo('This command is unsupported for local wallets')
        return

    initial_balances = []

    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=address.encode(), amount=amount))

    try:
        address_src, 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()
        src_xmss.set_index(int(ots_key_index))
        address_src_otsidx = src_xmss.get_index()
        address_owner = owner.encode()
        # FIXME: This could be problematic. Check
        fee_shor = int(fee * 1.e8)
    except KeyboardInterrupt as e:
        click.echo("Error validating arguments")
        quit(1)

    try:
        channel = grpc.insecure_channel(ctx.obj.node_public_address)
        stub = qrl_pb2_grpc.PublicAPIStub(channel)

        tx = TokenTransaction.create(addr_from=address_src,
                                     symbol=symbol.encode(),
                                     name=name.encode(),
                                     owner=address_owner,
                                     decimals=decimals,
                                     initial_balances=initial_balances,
                                     fee=fee_shor,
                                     xmss_pk=address_src_pk,
                                     xmss_ots_index=address_src_otsidx)

        tx.sign(src_xmss)

        pushTransactionReq = qrl_pb2.PushTransactionReq(
            transaction_signed=tx.pbdata)
        pushTransactionResp = stub.PushTransaction(pushTransactionReq,
                                                   timeout=5)

        print(pushTransactionResp.some_response)
    except Exception as e:
        print("Error {}".format(str(e)))
Ejemplo n.º 13
0
    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()
Ejemplo n.º 14
0
 def test_create(self):
     # Alice creates Token
     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)
     self.assertTrue(tx)
Ejemplo n.º 15
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))
Ejemplo n.º 16
0
    def test_validate_tx4(self, m_logger):
        initial_balances = list()
        initial_balances.append(
            qrl_pb2.AddressAmount(address=self.alice.address,
                                  amount=1000 * 10**self._decimals))
        initial_balances.append(
            qrl_pb2.AddressAmount(address=self.bob.address,
                                  amount=1000 * 10**self._decimals))

        tx = self.make_tx(initial_balances=initial_balances)

        tx.sign(self.alice)

        self.assertTrue(tx.validate_or_raise())

        tx._data.transaction_hash = b'abc'

        with self.assertRaises(ValueError):
            tx.validate_or_raise()
Ejemplo n.º 17
0
    def test_validate_custom(self, m_logger):
        # Token symbol too long
        with self.assertRaises(ValueError):
            tx = self.make_tx(symbol=b'QRLSQRLSQRL')
            tx.sign(self.alice)

        # Token name too long
        with self.assertRaises(ValueError):
            tx = self.make_tx(name=b'Quantum Resistant LedgerQuantum')
            tx.sign(self.alice)

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

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

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

        # 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)

        # 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)
Ejemplo n.º 18
0
    def test_validate_tx3(self):
        initial_balances = list()
        initial_balances.append(
            qrl_pb2.AddressAmount(address=self.alice.address, amount=1000))
        initial_balances.append(
            qrl_pb2.AddressAmount(address=self.bob.address, amount=1000))
        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=15,
            initial_balances=initial_balances,
            fee=1,
            xmss_pk=self.alice.pk)

        # We must sign the tx before validation will work.
        tx.sign(self.alice)

        # We have not touched the tx: validation should pass.
        self.assertTrue(tx.validate_or_raise())
Ejemplo n.º 19
0
 def test_create(self):
     # Alice creates Token
     initial_balances = list()
     initial_balances.append(
         qrl_pb2.AddressAmount(address=self.alice.get_address().encode(),
                               amount=400000000))
     initial_balances.append(
         qrl_pb2.AddressAmount(address=self.bob.get_address().encode(),
                               amount=200000000))
     tx = TokenTransaction.create(
         addr_from=self.alice.get_address().encode(),
         symbol=b'QRL',
         name=b'Quantum Resistant Ledger',
         owner=
         b'Q223bc5e5b78edfd778b1bf72702061cc053010711ffeefb9d969318be5d7b86b021b73c2',
         decimals=4,
         initial_balances=initial_balances,
         fee=1,
         xmss_pk=self.alice.pk(),
         xmss_ots_index=self.alice.get_index())
     self.assertTrue(tx)
Ejemplo n.º 20
0
    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)
Ejemplo n.º 21
0
    def test_validate_tx2(self):
        initial_balances = list()
        initial_balances.append(
            qrl_pb2.AddressAmount(address=self.alice.address,
                                  amount=10000000000000000000))
        initial_balances.append(
            qrl_pb2.AddressAmount(address=self.bob.address,
                                  amount=10000000000000000000))
        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)

        # We must sign the tx before validation will work.
        tx.sign(self.alice)

        # Transaction Validation should fail as the decimals is higher than the possible decimals
        with self.assertRaises(ValueError):
            self.assertFalse(tx.validate_or_raise())
Ejemplo n.º 22
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)
Ejemplo n.º 23
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))
Ejemplo n.º 24
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)
Ejemplo n.º 25
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)
Ejemplo n.º 26
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)))