示例#1
0
def get_mining_address(mining_address: str):
    try:
        if not mining_address:
            return bytes(hstr2bin(config.user.mining_address[1:]))

        mining_address = bytes(hstr2bin(mining_address[1:]))
        if AddressState.address_is_valid(mining_address):
            return mining_address
    except Exception:
        logger.info('Exception in validate_mining_address')

    return None
示例#2
0
def tx_transfertoken(ctx, src, master, token_txhash, dst, amounts, 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

    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
        src_xmss.set_ots_index(int(ots_key_index))
        addresses_dst = []
        for addr in dst.split(' '):
            addresses_dst.append(bytes(hstr2bin(addr[1:])))

        shor_amounts = []
        for amount in amounts.split(' '):
            shor_amounts.append(int(float(amount) * (10**int(decimals))))

        bin_token_txhash = bytes(hstr2bin(token_txhash))
        # FIXME: This could be problematic. Check
        fee_shor = int(fee * 1.e9)
    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 = TransferTokenTransaction.create(token_txhash=bin_token_txhash,
                                             addrs_to=addresses_dst,
                                             amounts=amounts,
                                             fee=fee_shor,
                                             xmss_pk=address_src_pk,
                                             master_addr=master.encode())
        tx.sign(src_xmss)

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

        print(pushTransactionResp.error_code)
    except Exception as e:
        print("Error {}".format(str(e)))
示例#3
0
    def test_exception(self):
        i = 0
        try:
            x = pyqrllib.hstr2bin('Z')
        except Exception as e:
            i = 1
        self.assertEqual(i, 1)

        i = 0
        try:
            x = pyqrllib.hstr2bin('Z0')
        except Exception as e:
            i = 1
        self.assertEqual(i, 1)
示例#4
0
def get_mining_address(mining_address: str):
    try:
        if not mining_address:
            mining_address = bytes(hstr2bin(config.user.mining_address[1:]))
        else:
            mining_address = bytes(hstr2bin(mining_address[1:]))

        if not AddressState.address_is_valid(mining_address):
            raise ValueError('Mining Address Validation Failed')

        return mining_address
    except Exception as e:
        logger.info('Failed Parsing Mining Address %s', e)

    return None
    def test_getNodeInfo(self):
        with set_qrl_dir("wallet_ver1"):
            walletd = WalletD()
            service = WalletAPIService(walletd)

            block_last_hash_str = 'c23f47a10a8c53cc5ded096369255a32c4a218682a961d0ee7db22c500000000'

            version = "1.0.0"
            num_connections = 10
            num_known_peers = 200
            uptime = 10000
            block_height = 102345
            block_last_hash = bytes(hstr2bin(block_last_hash_str))
            network_id = "network id"
            node_info = qrl_pb2.NodeInfo(version=version,
                                         num_connections=num_connections,
                                         num_known_peers=num_known_peers,
                                         uptime=uptime,
                                         block_height=block_height,
                                         block_last_hash=block_last_hash,
                                         network_id=network_id)
            walletd._public_stub.GetNodeState = Mock(
                return_value=qrl_pb2.GetNodeStateResp(info=node_info))

            resp = service.GetNodeInfo(qrlwallet_pb2.NodeInfoReq(), context=None)

            self.assertEqual(resp.version, version)
            self.assertEqual(resp.num_connections, str(num_connections))
            self.assertEqual(resp.num_known_peers, str(num_known_peers))
            self.assertEqual(resp.uptime, uptime)
            self.assertEqual(resp.block_height, block_height)
            self.assertEqual(resp.block_last_hash, block_last_hash_str)
            self.assertEqual(resp.network_id, network_id)
    def test_relaySlaveTxnBySlave(self):
        with set_qrl_dir("wallet_ver1"):
            walletd = WalletD()
            walletd._public_stub.PushTransaction = Mock(
                return_value=qrl_pb2.PushTransactionResp(error_code=qrl_pb2.PushTransactionResp.SUBMITTED))

            service = WalletAPIService(walletd)

            resp = service.AddNewAddressWithSlaves(qrlwallet_pb2.AddNewAddressWithSlavesReq(), context=None)
            qaddress = resp.address
            addr_state = AddressState.get_default(walletd.qaddress_to_address(qaddress))
            slaves = walletd.get_slave_list(qaddress)

            addr_state.add_slave_pks_access_type(bytes(hstr2bin(slaves[0][0].pk)), 0)
            walletd._public_stub.GetAddressState = Mock(
                return_value=qrl_pb2.GetAddressStateResp(state=addr_state.pbdata))

            alice_xmss = get_alice_xmss(4)
            slave_pks = [alice_xmss.pk]
            access_types = [0]

            resp = service.RelaySlaveTxnBySlave(
                qrlwallet_pb2.RelaySlaveTxnBySlaveReq(slave_pks=slave_pks,
                                                      access_types=access_types,
                                                      fee=100000000,
                                                      master_address=qaddress), context=None)

            self.assertEqual(resp.code, 0)
            self.assertIsNotNone(resp.tx)
    def test_relayTokenTxnBySlave(self):
        with set_qrl_dir("wallet_ver1"):
            walletd = WalletD()
            walletd._public_stub.PushTransaction = Mock(
                return_value=qrl_pb2.PushTransactionResp(error_code=qrl_pb2.PushTransactionResp.SUBMITTED))

            service = WalletAPIService(walletd)

            resp = service.AddNewAddressWithSlaves(qrlwallet_pb2.AddNewAddressWithSlavesReq(), context=None)
            qaddress = resp.address
            addr_state = AddressState.get_default(walletd.qaddress_to_address(qaddress))
            slaves = walletd.get_slave_list(qaddress)

            addr_state.add_slave_pks_access_type(bytes(hstr2bin(slaves[0][0].pk)), 0)
            walletd._public_stub.GetAddressState = Mock(
                return_value=qrl_pb2.GetAddressStateResp(state=addr_state.pbdata))

            alice_xmss = get_alice_xmss(4)
            bob_xmss = get_bob_xmss(4)
            qaddresses = [alice_xmss.qaddress, bob_xmss.qaddress]
            amounts = [1000000000, 1000000000]

            resp = service.RelayTokenTxnBySlave(
                qrlwallet_pb2.RelayTokenTxnBySlaveReq(symbol=b'QRL',
                                                      name=b'Quantum Resistant Ledger',
                                                      owner=alice_xmss.qaddress,
                                                      decimals=5,
                                                      addresses=qaddresses,
                                                      amounts=amounts,
                                                      fee=100000000,
                                                      master_address=qaddress), context=None)

            self.assertEqual(resp.code, 0)
            self.assertIsNotNone(resp.tx)
示例#8
0
def send_eph_message(ctx, msg_id, ttl, ttr, enc_aes256_symkey, nonce, payload):
    """
    Creates & Push Ephemeral Message
    :param ctx:
    :param msg_id:
    :param ttl:
    :param ttr:
    :param enc_aes256_symkey:
    :param nonce:
    :param payload:
    :return:
    """
    if not ctx.obj.remote:
        click.echo('This command is unsupported for local wallets')
        return

    stub = qrl_pb2_grpc.PublicAPIStub(ctx.obj.channel_public)

    if len(enc_aes256_symkey):
        enc_aes256_symkey = enc_aes256_symkey.encode()

    payload = payload.encode()

    encrypted_ephemeral_msg = EncryptedEphemeralMessage.create(
        bytes(hstr2bin(msg_id)), ttl, ttr, nonce, payload, enc_aes256_symkey)

    try:
        ephemeralMessageReq = qrl_pb2.PushEphemeralMessageReq(
            ephemeral_message=encrypted_ephemeral_msg.pbdata)
        ephemeralMessageResp = stub.PushEphemeralMessage(ephemeralMessageReq,
                                                         timeout=5)

        print(ephemeralMessageResp.error_code)
    except Exception as e:
        print("Error {}".format(str(e)))
示例#9
0
def collect(ctx, msg_id):
    """
    Collects and returns the list of encrypted ephemeral message corresponding to msg_id
    :param ctx:
    :param msg_id:
    :return:
    """
    if not ctx.obj.remote:
        click.echo('This command is unsupported for local wallets')
        return

    stub = qrl_pb2_grpc.PublicAPIStub(ctx.obj.channel_public)

    try:
        collectEphemeralMessageReq = qrl_pb2.CollectEphemeralMessageReq(
            msg_id=bytes(hstr2bin(msg_id)))
        collectEphemeralMessageResp = stub.CollectEphemeralMessage(
            collectEphemeralMessageReq, timeout=5)

        print(
            len(collectEphemeralMessageResp.ephemeral_metadata.
                encrypted_ephemeral_message_list))
        for message in collectEphemeralMessageResp.ephemeral_metadata.encrypted_ephemeral_message_list:
            print('%s' % (message.payload, ))
    except Exception as e:
        print("Error {}".format(str(e)))
示例#10
0
def _select_wallet(ctx, src):
    try:
        config.user.wallet_dir = ctx.obj.wallet_dir
        wallet = Wallet()
        if not wallet.addresses:
            click.echo('This command requires a local wallet')
            return

        if src.isdigit():
            src = int(src)
            try:
                # FIXME: This should only return pk and index
                xmss = wallet.get_xmss_by_index(src)
                return wallet.addresses[src], xmss
            except IndexError:
                click.echo('Wallet index not found', color='yellow')
                quit(1)

        elif src.startswith('Q'):
            for i, addr_item in enumerate(wallet.address_items):
                if src == addr_item.address:
                    xmss = wallet.get_xmss_by_address(wallet.addresses[i])
                    return wallet.addresses[i], xmss
            click.echo('Source address not found in your wallet',
                       color='yellow')
            quit(1)

        return bytes(hstr2bin(src)), None
    except Exception as e:
        click.echo("Error selecting wallet")
        quit(1)
示例#11
0
def _public_get_address_balance(ctx, address):
    address = address[1:]
    stub = qrl_pb2_grpc.PublicAPIStub(ctx.obj.channel_public)
    getAddressStateReq = qrl_pb2.GetAddressStateReq(
        address=bytes(hstr2bin(address)))
    getAddressStateResp = stub.GetAddressState(getAddressStateReq, timeout=1)
    return getAddressStateResp.state.balance
示例#12
0
def get_migration_transactions(signing_xmss, filename):
    transactions = []

    with open(filename, 'r') as f:
        json_data = json.load(f)

    count = 1
    addrs_to = []
    amounts = []
    output_limit = config.dev.transaction_multi_output_limit

    for addr in json_data:
        try:
            addrs_to.append(bytes(hstr2bin(addr[1:])))
        except:  # noqa
            print("Invalid Address ", addr)
            raise Exception
        amounts.append(json_data[addr])

        count += 1
        if count % output_limit == 0:
            transactions.append(create_tx(addrs_to, amounts, signing_xmss, count // output_limit))

            addrs_to = []
            amounts = []

    if addrs_to:
        transactions.append(create_tx(addrs_to, amounts, signing_xmss, (count // output_limit) + 1))

    return transactions
示例#13
0
    def test_getTransaction(self):
        with set_qrl_dir("wallet_ver1"):
            walletd = WalletD()
            service = WalletAPIService(walletd)

            tx = qrl_pb2.Transaction()
            tx.fee = 10
            tx.transaction_hash = b'1234'
            tx.message.message_hash = b'hello'
            pk = '01020016ecb9f39b9f4275d5a49e232346a15ae2fa8c50a2927daeac189b8c5f2d1' \
                 '8bc4e3983bd564298c49ae2e7fa6e28d4b954d8cd59398f1225b08d6144854aee0e'
            tx.public_key = bytes(hstr2bin(pk))

            walletd._public_stub.GetTransaction = Mock(
                return_value=qrl_pb2.GetTransactionResp(tx=tx,
                                                        confirmations=10))

            resp = service.GetTransaction(
                qrlwallet_pb2.TransactionReq(tx_hash=tx.transaction_hash),
                context=None)

            self.assertEqual(resp.code, 0)
            self.assertIsNotNone(resp.tx)
            self.assertEqual(bin2hstr(tx.transaction_hash),
                             resp.tx.transaction_hash)
示例#14
0
def transfer(destinations, fee, mixin, unlock_time):
    if len(destinations) > config.dev.transaction_multi_output_limit:
        return None

    addrs_to = []
    amounts = []

    for tx in destinations:
        addrs_to.append(bytes(hstr2bin(tx['address'][1:])))  # Skipping 'Q'
        amounts.append(tx['amount'])

    stub = get_public_stub()

    xmss = get_unused_payment_xmss(stub)
    if not xmss:
        return None

    tx = TransferTransaction.create(addr_from=payment_slaves[0],
                                    addrs_to=addrs_to,
                                    amounts=amounts,
                                    fee=fee,
                                    xmss_pk=xmss.pk)

    tx.sign(xmss)

    response = stub.PushTransaction(request=qrl_pb2.PushTransactionReq(
        transaction_signed=tx.pbdata))

    if response.error_code != 3:
        return None

    response = {'tx_hash': bin2hstr(tx.txhash)}

    return response
示例#15
0
文件: cli.py 项目: younesmovic/QRL
def recover(seed_type):
    """
    Recover Wallet using hexseed or mnemonic (32 words)
    """
    seed = click.prompt('Please enter your %s' % (seed_type, ))
    seed = seed.lower().strip()

    if seed_type == 'mnemonic':
        words = seed.split()
        if len(words) != 32:
            print('You have entered %s words' % (len(words), ))
            print('Mnemonic seed must contain only 32 words')
            return
        bin_seed = mnemonic2bin(seed)
    else:
        if len(seed) != 96:
            print('You have entered hexseed of %s characters' % (len(seed), ))
            print('Hexseed must be of only 96 characters.')
            return
        bin_seed = hstr2bin(seed)

    walletObj = get_wallet_obj()
    addrBundle = walletObj.get_new_address(seed=bin_seed)
    print('Recovered Wallet Address : %s' % (addrBundle.address.decode(), ))
    for addr in walletObj.address_bundle:
        if addrBundle.address == addr.address:
            print('Wallet Address is already in the wallet list')
            return

    if click.confirm('Do you want to save the recovered wallet?'):
        walletObj.address_bundle.append(addrBundle)
        click.echo('Saving...')
        walletObj.save_wallet()
        click.echo('Done')
示例#16
0
def token_list(ctx, owner):
    """
    Fetch the list of tokens owned by an address.
    """
    try:
        owner_address = parse_qaddress(owner)
    except Exception as e:
        click.echo("Error validating arguments: {}".format(e))
        quit(1)

    try:
        stub = ctx.obj.get_stub_public_api()
        address_state_req = qrl_pb2.GetAddressStateReq(address=owner_address)
        address_state_resp = stub.GetAddressState(address_state_req,
                                                  timeout=CONNECTION_TIMEOUT)

        for token_hash in address_state_resp.state.tokens:
            get_object_req = qrl_pb2.GetObjectReq(
                query=bytes(hstr2bin(token_hash)))
            get_object_resp = stub.GetObject(get_object_req,
                                             timeout=CONNECTION_TIMEOUT)

            click.echo('Hash: %s' % (token_hash, ))
            click.echo(
                'Symbol: %s' %
                (get_object_resp.transaction.tx.token.symbol.decode(), ))
            click.echo('Name: %s' %
                       (get_object_resp.transaction.tx.token.name.decode(), ))
            click.echo('Balance: %s' %
                       (address_state_resp.state.tokens[token_hash], ))

    except Exception as e:
        print("Error {}".format(str(e)))
示例#17
0
    def test_monitor_chain_state_peer_with_higher_difficulty_found(
            self, mock_get_block_metadata):
        """
        QRLNode.monitor_chain_state() basically:
        1. Tells P2PPeerManager to clean the list of channels/P2PProtocols, i.e. remove any we haven't heard
        from for a long time, and make sure our list of channels and the list of their statuses is in sync.
        2. Gets the last block from the State
        3. Broadcasts our State based on the last Block to our peers
        4. Ask P2PPeerManager to return the channel (if any) who has a higher difficulty than our chain.
        If a channel with a higher difficulty is found, get its list of headerhashes.
        """
        m_block = Mock(autospec=Block,
                       name='mock last Block',
                       block_number=2,
                       headerhash=b'deadbeef')
        m_block_metadata = Mock(autospec=BlockMetadata,
                                cumulative_difficulty=hstr2bin('01'))
        m_channel = Mock(autospec=P2PProtocol, addr_remote='1.1.1.1')
        self.qrlnode.peer_manager.get_better_difficulty.return_value = m_channel
        mock_get_block_metadata.return_value = m_block_metadata
        self.chain_manager._last_block = m_block

        self.qrlnode.monitor_chain_state()

        self.qrlnode.peer_manager.monitor_chain_state.assert_called_once()
        self.qrlnode.peer_manager.get_better_difficulty.assert_called_once()
        m_channel.send_get_headerhash_list.assert_called_once()
示例#18
0
def submitblock(blob):
    stub = get_mining_stub()
    request = qrlmining_pb2.SubmitMinedBlockReq(blob=bytes(hstr2bin(blob)))
    response = stub.SubmitMinedBlock(request=request, timeout=10)
    if response.error:
        raise Exception  # Mining pool expected exception when block submission fails
    return MessageToJson(response, sort_keys=True)
示例#19
0
文件: grpcProxy.py 项目: zeta1999/QRL
def submitblock(blob):
    stub = get_mining_stub()
    request = qrlmining_pb2.SubmitMinedBlockReq(blob=bytes(hstr2bin(blob)))
    response = stub.SubmitMinedBlock(request=request, timeout=10)
    if response.error:
        raise Exception  # Mining pool expected exception when block submission fails
    return {'status': 'OK', 'error': 0}
示例#20
0
 def test_parse_buffer_works(self):
     self.channel._buffer = bytes(
         hstr2bin(
             '000000191a170a0776657273696f6e120c67656e657369735f68617368' +
             '000000191a170a0776657273696f6e120c67656e657369735f68617368'))
     messages = self.channel._parse_buffer([0])
     self.assertEqual(2, len(list(messages)))
示例#21
0
 def test_getAddress(self):
     self.assertEqual(
         'Qbceef655b5a034911f1c3718ce056531b45ef03b4c7b1f15629e867294011a7ddfae185d',
         pyqrllib.getAddress('Q', pyqrllib.hstr2bin('aa')))
     self.assertEqual(
         'Q039058c6f2c0cb492c533b0a4d14ef77cc0f78abccced5287d84a1a2011cfb81cef41416',
         pyqrllib.getAddress('Q', tuple([1, 2, 3])))
示例#22
0
 def hash(self, nonce, preview=False):
     # nonce (already a hexstring) + mining_hash (already a hexstring)
     blob_with_new_nonce = nonce + self.blockheader.mining_hash[8:]
     blockhash = bin2hstr(bytes(sha2_256(hstr2bin(blob_with_new_nonce))))
     if not preview:
         self.blockheader.hash = blockhash
     return blockhash
示例#23
0
    def test_GetAddressFromPK(self):
        db_state = Mock(spec=State)
        p2p_factory = Mock(spec=P2PFactory)
        p2p_factory.sync_state = SyncState()
        p2p_factory.connections = 23
        p2p_factory.pow = Mock()

        chain_manager = Mock(spec=ChainManager)
        chain_manager.height = 0

        qrlnode = QRLNode(db_state, mining_address=b'')
        qrlnode.set_chain_manager(chain_manager)
        qrlnode._p2pfactory = p2p_factory
        qrlnode._pow = p2p_factory.pow

        service = PublicAPIService(qrlnode)
        pk = hstr2bin(
            '01060057ac9cb6085a8135631dcf018dff46d9c368a0b64d508f512e584199b6800'
            'f8cfcb672b931398a023680fe0308ed4b6ec75877d684bc2ccf11703e8369f064e7'
        )
        request = qrl_pb2.GetAddressFromPKReq(pk=bytes(pk))
        response = service.GetAddressFromPK(request=request, context=None)
        self.assertEqual(
            '010600b56d161c7de8aa741962e3e49b973b7e53456fa47f2443d69f17c632f29c8b1aab7d2491',
            bin2hstr(response.address))
示例#24
0
def parse_hexblob(blob: str) -> bytes:
    """
    Binary conversions from hexstring are handled by bytes(hstr2bin()).
    :param blob:
    :return:
    """
    return bytes(hstr2bin(blob))
示例#25
0
def generate_slave_from_input(slaves_filename):
    # FIXME: Refactor and improve error handling
    extended_seed = ''
    logger.warning('No Slave Seeds found!!')
    logger.warning('It is highly recommended to use the slave for mining')
    try:
        ans = input('Do you want to use main wallet for mining? (Y/N) ')
        if ans == 'N':
            quit(0)
        extended_seed = input(
            'Enter hex or mnemonic seed of mining wallet ').encode()
    except KeyboardInterrupt:
        quit(0)

    bin_extended_seed = None
    if len(extended_seed) == 102:  # hexseed
        bin_extended_seed = hstr2bin(extended_seed.decode())
    elif len(extended_seed.split()) == 34:
        bin_extended_seed = mnemonic2bin(extended_seed.decode())

    if bin_extended_seed is None:
        logger.warning('Invalid XMSS seed')
        quit(1)

    addrBundle = XMSS.from_extended_seed(bin_extended_seed)
    slaves = [
        bin2hstr(addrBundle.xmss.address), [addrBundle.xmss.extended_seed],
        None
    ]
    write_slaves(slaves_filename, slaves)
示例#26
0
    def get_block_to_mine(self,
                          wallet_address,
                          tx_pool,
                          last_block,
                          last_block_difficulty) -> list:
        dev_config = self._chain_manager.get_config_by_block_number(last_block.block_number + 1)
        try:
            mining_address = bytes(hstr2bin(wallet_address[1:].decode()))

            if not OptimizedAddressState.address_is_valid(mining_address):
                raise ValueError("[get_block_to_mine] Invalid Wallet Address %s", wallet_address)
        except Exception as e:
            raise ValueError("Error while decoding wallet address %s", e)

        if self._mining_block:
            if last_block.headerhash == self._mining_block.prev_headerhash:
                if self._mining_block.transactions[0].coinbase.addr_to == mining_address:
                    return [bin2hstr(self._mining_block.mining_blob(dev_config)),
                            int(bin2hstr(self._current_difficulty), 16)]
                else:
                    self._mining_block.update_mining_address(dev_config, mining_address)  # Updates only Miner Address

        self.prepare_next_unmined_block_template(mining_address,
                                                 tx_pool,
                                                 last_block,
                                                 last_block_difficulty,
                                                 dev_config=dev_config)

        return [bin2hstr(self._mining_block.mining_blob(dev_config)),
                int(bin2hstr(self._current_difficulty), 16)]
示例#27
0
def transfer(destinations, fee, mixin, unlock_time):
    if len(destinations) > config.dev.transaction_multi_output_limit:
        raise Exception('Payment Failed: Amount exceeds the allowed limit')

    addrs_to = []
    amounts = []

    for tx in destinations:
        addrs_to.append(bytes(hstr2bin(tx['address'][1:])))  # Skipping 'Q'
        amounts.append(tx['amount'])

    stub = get_public_stub()

    xmss = get_unused_payment_xmss(stub)
    if not xmss:
        raise Exception('Payment Failed: No Unused Payment XMSS found')

    tx = TransferTransaction.create(addrs_to=addrs_to,
                                    amounts=amounts,
                                    fee=fee,
                                    xmss_pk=xmss.pk,
                                    master_addr=payment_slaves[0])

    tx.sign(xmss)

    response = stub.PushTransaction(request=qrl_pb2.PushTransactionReq(
        transaction_signed=tx.pbdata))

    if response.error_code != 3:
        raise Exception('Transaction Submission Failed, Response Code: %s',
                        response.error_code)

    response = {'tx_hash': bin2hstr(tx.txhash)}

    return response
示例#28
0
def get_migration_transactions(signing_xmss):
    transactions = []

    with open('data/token_migration.json', 'r') as f:
        json_data = json.load(f)

    count = 1
    addrs_to = []
    amounts = []
    # output_limit = config.dev.transaction_multi_output_limit
    output_limit = 4  # Overriding output limit to 4, to get multiple txns and better testing scenario
    for addr in json_data:
        addrs_to.append(bytes(hstr2bin(addr[1:])))
        amounts.append(json_data[addr])

        count += 1
        if count % output_limit == 0:
            transactions.append(
                create_tx(addrs_to, amounts, signing_xmss,
                          count // output_limit))

            addrs_to = []
            amounts = []

    if addrs_to:
        transactions.append(create_tx(addrs_to, amounts, signing_xmss, count))

    return transactions
示例#29
0
 def addresses(self) -> List[bytes]:
     """
     Returns all address items in the wallet
     :return:
     """
     return [
         bytes(hstr2bin(item.qaddress[1:])) for item in self._address_items
     ]
示例#30
0
文件: main.py 项目: amitkumarj441/QRL
def get_mining_credit_wallet(mining_credit_wallet: str):
    try:
        mining_credit_wallet = bytes(hstr2bin(mining_credit_wallet[1:]))
        if AddressState.address_is_valid(mining_credit_wallet):
            return mining_credit_wallet
    except Exception:
        logger.info('Exception in validate_mining_credit_wallet')

    return None
示例#31
0
    def GetTransferTokenTxn(self, request: qrl_pb2.TransferTokenTxnReq, context) -> qrl_pb2.TransferCoinsResp:
        logger.debug("[PublicAPI] GetTransferTokenTxn")
        bin_token_txhash = bytes(hstr2bin(request.token_txhash.decode()))
        tx = self.qrlnode.create_transfer_token_txn(addr_from=request.address_from,
                                                    addr_to=request.address_to,
                                                    token_txhash=bin_token_txhash,
                                                    amount=request.amount,
                                                    fee=request.fee,
                                                    xmss_pk=request.xmss_pk,
                                                    xmss_ots_index=request.xmss_ots_index)

        return qrl_pb2.TransferCoinsResp(transaction_unsigned=tx.pbdata)
示例#32
0
文件: cli.py 项目: fanff/QRL
def tx_sign(ctx, src, txblob):
    """
    Sign a tx blob
    """
    txbin = bytes(hstr2bin(txblob))
    pbdata = qrl_pb2.Transaction()
    pbdata.ParseFromString(txbin)
    tx = Transaction.from_pbdata(pbdata)

    address_src, address_xmss = _select_wallet(ctx, src)
    tx.sign(address_xmss)

    txblob = bin2hstr(tx.pbdata.SerializeToString())
    print(txblob)
示例#33
0
文件: cli.py 项目: fanff/QRL
def tx_inspect(ctx, txblob):
    """
    Inspected a transaction blob
    """
    tx = None
    try:
        txbin = bytes(hstr2bin(txblob))
        pbdata = qrl_pb2.Transaction()
        pbdata.ParseFromString(txbin)
        tx = Transaction.from_pbdata(pbdata)
    except Exception as e:
        click.echo("tx blob is not valid")
        quit(1)

    tmp_json = tx.to_json()
    # FIXME: binary fields are represented in base64. Improve output
    print(tmp_json)
示例#34
0
文件: cli.py 项目: fanff/QRL
def tx_transfertoken(ctx, src, token_txhash, dst, amount, 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

    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_dst = dst.encode()
        bin_token_txhash = bytes(hstr2bin(token_txhash))
        # FIXME: This could be problematic. Check
        amount = int(amount * (10**int(decimals)))
        fee_shor = int(fee * 1.e9)
    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 = TransferTokenTransaction.create(addr_from=address_src,
                                             token_txhash=bin_token_txhash,
                                             addr_to=address_dst,
                                             amount=amount,
                                             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)))
示例#35
0
文件: misc.py 项目: fanff/QRL
def merkle_tx_hash(hashes):
    # TODO: Clean this, move to C++
    # FIXME: Review and consider (CVE-2012-2459) and bitcoin source code
    """
    merkle tree root hash of tx from pool for next POW block
    :param hashes:
    :return:

    >>> bin2hstr(merkle_tx_hash([b'0', b'1']) ) # FIXME: This input is not realistic
    '938db8c9f82c8cb58d3f3ef4fd250036a48d26a712753d2fde5abd03a85cabf4'
    >>> merkle_tx_hash(['938db8c9f82c8cb58d3f3ef4fd250036a48d26a712753d2fde5abd03a85cabf4'])
    '938db8c9f82c8cb58d3f3ef4fd250036a48d26a712753d2fde5abd03a85cabf4'
    >>> bin2hstr(merkle_tx_hash('938db8c9f82c8cb58d3f3ef4fd250036a48d26a712753d2fde5abd03a85cabf4'))
    '938db8c9f82c8cb58d3f3ef4fd250036a48d26a712753d2fde5abd03a85cabf4'
    >>> bin2hstr(merkle_tx_hash([b'0', b'938db8c9f82c8cb58d3f3ef4fd250036a48d26a712753d2fde5abd03a85cabf4']))  # FIXME: This input is not realistic
    '40243e694d9c015d5097590bcc9df82683d8ba4006d58c6abb5e1a6bee5ec6dc'
    """
    if isinstance(hashes, str):
        # it is a single hash string rather than a list..
        return hstr2bin(hashes)

    if isinstance(hashes, list) and len(hashes) == 1:
        # it is a single hash string rather than a list..
        return hashes[0]

    j = int(ceil(log(len(hashes), 2)))
    l_array = [hashes]
    for x in range(j):
        next_layer = []
        i = len(l_array[x]) % 2 + len(l_array[x]) // 2
        z = 0
        for _ in range(i):
            if len(l_array[x]) == z + 1:
                next_layer.append(l_array[x][z])
            else:
                next_layer.append(sha256(l_array[x][z] + l_array[x][z + 1]))
            z += 2
        l_array.append(next_layer)

    # if len(l_array[-1]) == 1:
    #     return tuple(l_array[-1])

    res = bytes(itertools.chain(*l_array[-1]))

    return res
示例#36
0
文件: cli.py 项目: fanff/QRL
def wallet_recover(ctx, seed_type):
    """
    Recovers a wallet from a hexseed or mnemonic (32 words)
    """
    if ctx.obj.remote:
        click.echo('This command is unsupported for remote wallets')
        return

    seed = click.prompt('Please enter your %s' % (seed_type,))
    seed = seed.lower().strip()

    if seed_type == 'mnemonic':
        words = seed.split()
        if len(words) != 32:
            print('You have entered %s words' % (len(words),))
            print('Mnemonic seed must contain only 32 words')
            return
        bin_seed = mnemonic2bin(seed)
    else:
        if len(seed) != 96:
            print('You have entered hexseed of %s characters' % (len(seed),))
            print('Hexseed must be of only 96 characters.')
            return
        bin_seed = hstr2bin(seed)

    config.user.wallet_dir = ctx.obj.wallet_dir
    walletObj = Wallet()
    addrBundle = walletObj.get_new_address(seed=bin_seed)
    print('Recovered Wallet Address : %s' % (addrBundle.address.decode(),))
    for addr in walletObj.address_bundle:
        if addrBundle.address == addr.address:
            print('Wallet Address is already in the wallet list')
            return

    if click.confirm('Do you want to save the recovered wallet?'):
        walletObj.address_bundle.append(addrBundle)
        click.echo('Saving...')
        walletObj.save_wallet()
        click.echo('Done')
示例#37
0
文件: main.py 项目: fanff/QRL
def mining_wallet_checks(args):
    slaves_filename = os.path.join(config.user.wallet_dir, config.user.slaves_filename)

    if args.randomizeSlaveXMSS:
        addrBundle = Wallet.get_new_address()
        slaves = [addrBundle.xmss.get_address(), [addrBundle.xmss.get_seed()], None]
        write_slaves(slaves_filename, slaves)

    try:
        slaves = read_slaves(slaves_filename)
    except FileNotFoundError:
        logger.warning('No Slave Seeds found!!')
        logger.warning('It is highly recommended to use the slave for mining')
        try:
            ans = input('Do you want to use main wallet for mining? (Y/N) ')
            if ans == 'N':
                quit(0)
            seed = input('Enter hex or mnemonic seed of mining wallet ').encode()
        except KeyboardInterrupt:
            quit(0)
        if len(seed) == 96:  # hexseed
            bin_seed = hstr2bin(seed.decode())
        elif len(seed.split()) == 32:
            bin_seed = mnemonic2bin(seed.decode())
        else:
            logger.warning('Invalid XMSS seed')
            quit(1)

        addrBundle = Wallet.get_new_address(seed=bin_seed)
        slaves = [addrBundle.xmss.get_address(), [addrBundle.xmss.get_seed()], None]
        write_slaves(slaves_filename, slaves)
        slaves = read_slaves(slaves_filename)
    except KeyboardInterrupt:
        quit(1)
    except Exception as e:
        logger.error('Exception %s', e)
        quit(1)

    return slaves
示例#38
0
文件: cli.py 项目: fanff/QRL
def tx_push(ctx, txblob):
    tx = None
    try:
        txbin = bytes(hstr2bin(txblob))
        pbdata = qrl_pb2.Transaction()
        pbdata.ParseFromString(txbin)
        tx = Transaction.from_pbdata(pbdata)
    except Exception as e:
        click.echo("tx blob is not valid")
        quit(1)

    tmp_json = tx.to_json()
    # FIXME: binary fields are represented in base64. Improve output
    print(tmp_json)
    if (len(tx.signature) == 0):
        click.echo('Signature missing')
        quit(1)

    channel = grpc.insecure_channel(ctx.obj.node_public_address)
    stub = qrl_pb2_grpc.PublicAPIStub(channel)
    pushTransactionReq = qrl_pb2.PushTransactionReq(transaction_signed=tx.pbdata)
    pushTransactionResp = stub.PushTransaction(pushTransactionReq, timeout=5)
    print(pushTransactionResp.some_response)
示例#39
0
文件: known_values.py 项目: fanff/QRL
# coding=utf-8

# FIXME: These values are based on current implementation. There are known issues and these values are subject to change
from pyqrllib.pyqrllib import hstr2bin

S1 = hstr2bin('7bf1e7c1c84be2c820211572d990c0430e09401053ce2af489ee3e4d030c027464d9cac1fff449a2405b7f3fc63018a4')
S1_Pub = hstr2bin('6b424d99242a1a3f40f60bf565b1a63aed94464b26ad022eed800ec3384f11fe40c46dc60cdf80d60dc75b4c908b4afa')
S1_Pri = hstr2bin('2c4147cd5c75622220054bd8923ba565999931634499fc096c0b9cedf8f4f32daaa7b50f313b3c93743a00f027af0551')

S1_Mne = 'law bruise screen lunar than loft but franc strike asleep dwarf tavern dragon alarm snack queen ' \
         'meadow thing far cotton add emblem strive probe zurich edge peer alight libel won corn medal'

S1_PK = ['18e9198ac177807cc249e29b3d0cdda14b688d2cb8387e782239c0a565faee35',
         ['6fb23184bce2fe956d4996f582f9981abef4d2577124490fec021108f9c9b1fd',
          '6d6a6eae1bf5ca84d6bb0290f829f0896aa01d3a0dfbc8c937cd7158901182bc'],
         ['e101a4902a5090ab19f655791eb735a81e07d7282b58fce2c9a597209c29ce51',
          '6cb7f6b8a0b4e9797d6826096879f23a2feba90932892e27ad7cc984d908b336',
          'f8920b0716c163f5df4c128585ffa806185b940d1e0f5c3cde981bc1c47804c6',
          '523680e0dc7b9849c698cae32e6ecaafdc81c4f9c7122cc7a8b2b09fb62b41c7',
          '5d34a509f71e74ef3dc59ba327d6a49da321c5a7c01d243f1861554ff1e74456',
          '3d1f93175aa8b1dc5f7263fc8d53615e25a3f29b4866426195840a5dbd4fe752',
          'eeb56bcbd28a6e51f7f4d63dc584afe333ec037f6cd2b0bd05c808ab25b978f0',
          'c5d48dee1eb76147ca1423fc4dc47a089c668232f985643140fd8d323e1425fd',
          '00b09fdb2dd3bb5d882b30d2aebdef010cccd06c0891d481ea44b2177d9b73d9',
          'c93cd5cbd16d5ce80c12013bbf850bb72f11493382e8307191898d1d30769e8e',
          '95f11edd37c0c79e188aa3b50fae08b0d361ea0bf478bfd76896992f0ba954a5',
          'd7c9a1fc3240517feed3f42591edff8b5a24699d95a12f0fef79c577ba464ab0',
          'fe7d0181f05df53df1d8f4a9a039971bbf933ab0b6995855f5860fd699d662c4',
          'f8dfd075baec6e8ba69bcf64fc33b2719eeb22952180f2819a67bf84e3a0e34e']]

S1_PKsh = ['18e9198ac177807cc249e29b3d0cdda14b688d2cb8387e782239c0a565faee35',
示例#40
0
文件: doctest_data.py 项目: fanff/QRL
xmss_test_seed1 = '0' * 48
xmss_test_seed2 = '31' * 24

new_keys_expected = ('000000000000000000000000000000000000000000000000',
                     '\x83\xa9\x1aMzV\n\xbdA\xea\x95\xf4\x12\xcd\xe9\x8e\xda\x03v\x9dr\xb5u[\xb7\xc4\xabt3\xe750 ?\xa6p\xa4\xc6\xd4\xf2\xadZ\xc0\xf8\xf0\xce0\xa7', "2\xee\xe8\x08\xdc|]\xfe&\xfdHY\xb4\x15\xe5\xa7\x13\xbdv@6\xbb\xee\xfdzT\x1d\xa9\xa1\xcc{\x9f\xca\xf1}\xa09\xa6'V\xb685\xde\x17i\xe0^")

xmss_pk_expected1 = '26b3bcc104d686ecfd9fdea7b1963384339121430fbe056cab7c3048ea3e4c4e51ec21420dd061739e4637fd74517a46f86f89e0fb83f2526fafafe356e564ff'

xmss_pk_expected2 = 'ad904af119d215bdc8eeba2cad0c4016e65a180fbe3f6a13589db5d395eef773df2355c48096f2351e4d04db57b326c355345552d31b75a65ac18b1f6d7c7875'

xmss_sk_expected1 = '000000005f2eb95ccf6a0e3e7f472c32d234340c20b3fd379dc28b710affcc0cb2afa57b3aa40c0f99459afe7efe72eb9517ee8ded49ccd51dab72ebf6bc37d73240bb3a51ec21420dd061739e4637fd74517a46f86f89e0fb83f2526fafafe356e564ff26b3bcc104d686ecfd9fdea7b1963384339121430fbe056cab7c3048ea3e4c4e'

xmss_sk_expected2 = '00000000ad70ef34f316aaadcbf16a64b1b381db731eb53d833745c0d3eaa1e24cf728a221e00f865b3457b6f9a95deff8326d07bbdd59f37feffb06b7fc7e8f881fb36adf2355c48096f2351e4d04db57b326c355345552d31b75a65ac18b1f6d7c7875ad904af119d215bdc8eeba2cad0c4016e65a180fbe3f6a13589db5d395eef773'

xmss_mnemonic_seed1 = '6b6c5c1c859079864060ff38e67940394bb4439fddafa6fc716731dec13a0f29ca9b9001527e8daf0851245cbf738435'
xmss_mnemonic_seed2 = '4493ca509e5550a50af4c5a357c041b7bb4d15f77662d0bfe04d4c2ee1eff87a0580c7bc6878c468257a977fd167378e'
xmss_mnemonic_test1 = 'honey shell brass fund lance hairy greedy villa told nearer defect row ease writer radius influx inter jacket tank beauty away oven organ abbey flick train quote magic career slope java earl'
xmss_mnemonic_test2 = 'editor digit fine tight finish finish voice galley friend agency ridge render bet kin guide aside tecum star common budget wheel patron lobe leaky helm mildew heir fridge noun worthy heart lad'

xmss_sign_expected1 = '000000001a214b567518ed5e9564784b5727ebf20faa02018db436fa3fc548f0cd5a6385ad8689b5c2b26f94066be2e0d6f084c7b75e8db58a56a5d2bd97597f3b94838aec868b5223910a13633806488a968ab76d4b6a1d29dff5af7c6e6dc8da4333f7fe5b4456c59c7a6bf93489b747c2a2cc24c8ec6756888e84fa9df219eaa4168b570f9618e65c686d33530c11f5275e4cfb604c83088de8f760f02d5ef67ca3d4f438ca95602777e0355af654e186ac74ecfa3287e2eb92ca99139d4badbc3758efd69c3c84af219f7f340f3b2fa3d28dbd1d21b037be4e3a54fe2fae5e7c41def958ed0160765e650679bd0c4f07eea7ec27934ff8738327434269a2cef4f6613ecff06098952e36f6e0bbc679392c8c6656c725c6c66694871276af3e33911ed736137ee9872402382f509f77db45153fe627c17ee392b5ba7a9593d048a71861405fb706929379d9039634ba8fdb0acc19bd6d60dd5f5adf867fe8b68489bb7a20f005c430321f2a858b05048f5cb7cc896186459d0be38a96f5f31423c79fbc037007d08ba9cd4425de2f644e8dafd18199dec224ec023fcb9eb510daaca49f2b79df4efc7f7cc3560aacabbe17bcfc8dae536e3c8450fd5c442b50da52eadeec2b368698714b19451317a65abbb427a875126c7d306d84635d2ba9db3ea8482a78a60d0983c994e207e4854bbc97f8b79257d29cd4a9cda4b2e2522cabf172ad55afa42300b5b449a780f203e5fbbc20b08f5de93d5352d440bc3668e5c0109d400175ae6236012af3549cdf59489ff63a48caae649d35564932026d7f2fcf40b1c5da69e75d5f0c21864c628201189014d40037dcacb48d38068b825c17ec83435701c995e290e71f37bda6c3e8da68528b98c75d8f2b48fcf7fb08cd6c14544daff0afacfdeafb57c38c8c91236155acee4ea99682081c0a24a1426e345552fb30a211c7e3031155aec2ebccbf200c91c74901703b86d3d4461aa5529238f74e952990ec92eda0e1537a456e3e95f704b150dda732e34d39d7c4b954c7d4aa0ef25eb10978cb106a23811b74f36c8665bf5af3f02a1c9c727f81d359ef3be2f697383de0a6e97929eb8a992ee9313bb9cd954e1957e960f37f096696bb05470f3ec116c80c885b44cc1bceefaf7e273b95bf02f3f3973eef294e31f4c75380ff515d85a5d3519f5e9b7cf8d788de0bc3891883e9f24817898b4fcf53beff0ba4cfcebf55c7d6e1d33e077081e8f77d9f8691650648861b722af954a7042d42cc96e455ae9f0ed71e38ea7ccf405ff54a2dba58dfe40c72d41db80ed9b43f753f3e4bfb9d0f23e5dce9ec254259cee9138550ff7696cbcb03a19495c0d3cfefdf4d66596261d7b70eb9f3a0f3489674b5acaed61b4b5c03b714aba1dbd9c37cb5faa4fcdadc4937bdc627c3424f48486ce4ae47f005bb493390dab4df3ca66052693dae794458e2401ba1196464bd6ed67c3a8dd0138223ef87d2de5dadd3409da70577e0628e2e522e08f718223a2d1917033bde934187727bc7c5e77581b31d3352023184ab4a1145186a1119fee986f4cec6feb7312a98398f9ff5d94e240473c5c02e820671c2e2edc4511ca9c45c909d7560c5bc9385e52adfb0cfbec47fbeb546e8192b7acc39843f98433b7d0c54c761d921490ffe76b22df7de2c52837be92950225b354637cdce10ca2f215f949be584e0208a7d5941543f00ce62d18145de257aa4e89ea7e1a7a15485ef0ad21feb141fda8e0b11f284d7fbe52a962b872ee268c04466e52217af05fea5d120af5fad776fc91f7a4ad64ebe05b373e6b6bc9926e93c5963c43243c099f6eb610f0de3b7f363a9c2d787564cec547d6be10c7d985bd287ef4d379aa8cc6c7df4475bc8d7c25bb8ed6a18006f3f725741aba384a01329b3f81d59b2a072d9e1a416e6424e55bbf1662a54a03bc5f3779416cc0261d8a72eabe2e73a161ca4ebe0715ada9ede5206a7f5517db10191036ae820f606fc8c5b49a4544d17bbf838a05acf9f853a7fa38af9749f54d57de25cc192287746c4bf8798523f751106f7a751454cda89bba679620eed54575208526885e8fdade8ba82f46e453fd3d8bbfe47bceeadd9dd2f67017216f027e8471a78f5ae0c2261a29f947aaa5e64cae27c3da6b6071bc0f49312bbb31739aa57e6897a98d7286c393490811a5612bac96d6d421a107128089df8d05b2750c7d00d371b4ec78a05a5292514a6c339fa93c0fdaba9b414017f6c6b73db4c4aaf33cd0df73f201eaf2f95b595f1af19113ce0d491238a97818232b988065482a736e99d8c920938c463765e46ec616e9bd1d7f80826dec6ae9a1ff3564bfa3a575a70405d93646c1b7277d44b4a2191f631792dd583836d29c6e71a04ecddb4629e6e850ba2144b55f5a1f432c1443224714bf9f0300e32147b862af274345b7366b16ff0951260f6b09c2692164e6f585712ee5d6d7bc3fbc306920653d664f9ee375dd31011778c8db963d53a4b0f7cb9f3db9d29f302b2585fa9ca064e60c19c668b757c069e5cf892f7f5e5140b7c4d3cf0dddaff5329e02188325e659e324d6be8a40bca2b0b164dcfbdcaed85872ac974e9cf9c7af3dc3446c25e58ba1e29d8e6653d4d561a1b7b1518f6397f861e04aab012bfbde4623cf7bea437d2e65c979c9b154ac1ad71f4fbf033782ac2fdbd53997936843374d7631dc4c97908ce2d6df63d75eda564c52669a84b6ebb82301d572e0f15744d110cacca683d2d154bbf4f978b6a1c590a74138c95929123d67f0f56da7c65bf6c99e2180d141611e24d602e48a4ef1dbd396437930026e108015b3d8ef13149e6f4ddcbeb3d46cf812d2149de3d5a2a0faf24b882666da4bd455d5b4c2db966744778c0fc21710209fbab82d700eda3374b0b541c796074d5c4dabad32d21f2574bea0f713c44147623caba4b34c0e5a23662bd6c3090d9b67d9349c47a7d79fc246018eb7c3b341c5ab4ed05a5d858a372a344a494208651ec2fa2458b22dc49b1d4c4095c3e8cfda558968baf71511d2b8dea748255d8bf9ed7b534464fb857ba299f648b475b2835812d81fedf94ff3f141e44bc0953369f49e5a68be2b4a616141f7f2965121c64e463bfc741ba8718dad5ca295ecb968ef6021ceb954881997718603ed89cc8b4b6600eb15864b2d7babf6adbbb8405d03760874868570260ac7bab582d6deaa0125a8b50e05230bf61405ec6b1fc7aa61a6d517ec5a48bd9b2ddd0'
xmss_sign_expected1_h = 4

xmss_sign_expected2 = '00000000688affc5a80cdbe2de8f681ed06ad21b2da842e123ee4ac8df2b7c7ca2992b05b5a861167631876064d5f9bcf907f6c4a7a58000481888e037798147c9def1bd5d6f00959a6875805c8dfdf9d7e67c95ef33c6babb7e475986971605479e437caace1bbd1a190f6f37cb0063023b8ca2d540bcfaeb838fd153e7d1e80f2ade89474088218d5f883d1a6e6b197a0ec6deeba4c0502a43467ac2a6e3bb4cec71fdec1dc050a338d7031d1d5e3b8e307a331e80023bdd63bfb7fe6dc7d1d68e6473835a491eab2a4fcd4bd8f60e151b26d035989dbe2d8148a30459c371e955f5692fd6873804637435a39ea28f36bd81b4040cb1a5c4e4cb1c91a43a1e57839f4cd42b56ee903eb4180f73e65706a00856a71708c8ea514993a58faa7001026f0cfd1df70687f853d9b8f46aacba52903bdd717af79385a1e9924589b568f44ef86e4b60cfe80fa9a634b66f12083003045d0b83fd109dcd57d21569f6ae82fafab8f119d665162fe94e0785e2bf32ae4e9146d99e9b26c6f89ae1848220f7819440c3109098201880e04109a7b61b85ea9ef069bc5f522f8ad6f08f77421153da79b5dc9cf5c2cb640124ee4e9c664f04ba19b4fa140ab97eda96db28f6019c89dd8e23f2da0aca066b422425ab204e98d336206eab9bad338266cf97ebbea9b06d1c5f1f547522a1d4e0abe9491af2317ab99c65a004282a86a7d1b6b9965e62066f494eb5afaf6bb2df41422dfadbfab137f4ce65782f42c80ba6622fbe3c203cf60ad54ed92b97cc81132a9e08eb451dbba97382ec5b24f476954f7a112efe7f2e6c8bcda1f4a875dc8c8c08486994b6ad824724c6dbc0f5bb674ac193051a63f8299392816835201edaaaa9da74ad55cbf2e668bf045ed4ccb063a47810bdc7ff13b253963247a895ceac4a9bc19abd45d44e4cec36ff178c559844b9d8c59868be5c684c7fef7f15e23ac4c7988f19a121d2187142f80b8b2ed4e3a37855501ce1292606dbe847d1f32baeed18ee8ea6dee245f6c204879231d11260f75cf569e0049606220260bc495da851e03b9fea66b4af266450ff8a61349d959d53b6f35250816dd28ce9ed787873f5e7c5727c9e6fb4e49d70413c1e1ebd920c7e7fa6e52f51d63ee460b0ae9de6a38e60a52d893e887cd977b4b78c7a1bad8b1e05d90cf770835751be21708ac38c5233c4e90d21a56fe2ca6f78590ff053a27cbea5cbc777c987ee352f9f8b3977ebd2637f52da686a031f848cc551c1772a84a55a274f99d7bb84e0b76b0d1966c22aafaeda0c6f6af6a4e9b2e11a58d0b0a627132410bd2fa0de0cc5c8b7055ce455dcbaf4d75bc665a708e7fe6842f5684a28c1c0cd1746dbc3c7a1acd456d6a0a41ab958a868739637153f5f364f8ef92aa7479524d36b438fb8c4b07e76ecd1f421f135f36007e0df7756646cf97f4e127f979ced63ca7de6ffa7d36d549a65984169351d151f3b415e4964fd0535dcfe859936d172dc2e6380255315199c1893e8a6c7daad9e1647d548cea274fe97d45cd50281ae3cb0095aaaa72f00e74f80f9fa9ad69f4516452e6d032a0f4785570713976027c4fc056fdf84dbd562b29cbbf6c7075f7c0389693addb08e97d63ae864b861c086580f5f61fb8de32f36dd6329b0850160044455a6f77a2c36440b612a899a02e716867af2784460d251ae9de17b511bafa12da8a36094d524d97a48262700d7bcd557c8f903ac814a5a823feace683b1e4a134d47dad5c834e212ee877ce6e174973d4690a24583d68b4d03cf7befc237b4ea991d3d205682b363846cd043b27ea7a345d94daee19b4548df1ae3c89cce001802ccc8c716786fc4557fcd1329bf9b42ec5c24e2a48dfaf3c810be5d458e5a42429e1e2eea993755578c469660896fbc081c3983e5d618f02365f1cb1c1a0a9e45629c73926e0f32b13bdb40563bb3a18b7874d44d7d9994119da1116c4ee11c9cbc85237faa2d4ef78b9d95eb3fec09c8e8644c386bfc735ddf90d90f7274c3045d3d4f17f2fc161d700c1101a30ae721c654bc300275e2c4af0f9917cdc2a12dd50ca3d5f676fe634bea494e13b77269a8c0bf56132a13721504c77481730befeae46b3f60d8721d35ca223ffdd6933ef1fe26083b5a21b5b3bfcddfb1d86f6caf4c133737aaf50b57ed336a32c79af5e3bf1bb8c303ac8ab114db490ff43b126f3008045913032f3ccf9065a1f457ac15b3378bae160908b1d2a2c192a6d27c584cbb21657ee9cf895d3929e811eb6a00584c69bda6748770574ef87744477255f5517ef4475b347fc0385def7504fc6807e5eea26f1995738aff1b34eb1061efa9e00ec84977260957287f9e691f132aa1cd436cb02583e4e1ddfaaadb806bef8eae6ee795c6f96b7841e26a4b44207c69083c45b3e04af53df87432dd2a151daedb97744d6ef7573411db8f397ad35731cc40c40047282dcbf32c11bbbc2652a994beb22840846e20a5d4e7087d3f7c2a539a0c2396dbf9dfe7ac9a18337aeb78441c0c7570a2f6a89edbb38b84730dec30c35d605135d0a63bcacade647a69beb9d680886f56791d5b4811ef90c17059a8d12c7d8499f0c74e5d00d7a393588c0bdaae0f77014f8c678a21b6b00ec1d5f2b9461291fbff880966b8d2375186eae3ea2e2c9eb94cb1632ac306a31f5645ca0cf5022d7dd33901ffc1e21056adc2cb7ad405c23f57836514987ec579ea7910f276dab925fe275cc2e0777ebfc1d17dfae6a1450fb7be3946860b358c7321defa7c4e9eadec3a1059f9a190e1ee48bcc9592e68b0827f946f76d7c654944a085822d95d3b0a096060cf18641faa9a04b1cf88f3aec6f1feeee973447ef7198a2a4970ec8bf7070fffea1d1b4cb009315ee674d372948990993c8ef9482b7ceb037a190ed83bc685386ecf48643f0a6a386f188aea573170737832364b01ca400c61ada16140dd1bbbfaa61054699f7de8c0c8ee9b8e2f6b14945dbda1c01ce1821e3a88ea8df362d72bf48c4713b7ede2051593d764074991e5bb1a82af415caa7be5a148c54dd52b1b1773b922baa1ec04a4ae310f555a2b2c982275f2f77c8de85690ce823f0f422abf70afc8acfc6c74afc7e3a7c2092b99201312577698cf0801bacb7f24c0bee985df6fe32491a3619b959f1bdf3f94913f9025aca7c7d277ea49af96e785f73f7634c9410745b7f3aecb110f35a1568c66b396f036ee8dc080ddcd9892a9fb4524d57d996453b4e6c475'
xmss_sign_expected2_h = 4

hashchain_reveal_input = hstr2bin('32eee808dc7c5dfe26fd4859b415e5a713bd764036bbeefd7a541da9a1cc7b9fcaf17da039a62756b63835de1769e05e')

hashchain_reveal_expected1 = '1d607de5dc840ca31b6cdc8aa2a0c5e7158396b27103a3a128c97994d33e3fce'

message_example = 'ff00003030303030303065007b2274797065223a20224d42227d0000ffff00003030303030303261007b2274797065223a2022504c222c202264617461223a20225b5c223137322e31382e302e365c225d227d0000ffff00003030303030303065007b2274797065223a20225645227d0000ffff00003030303030306434007b2274797065223a20224342222c202264617461223a20227b5c22626c6f636b5f6e756d6265725c223a20302c205c22686561646572686173685c223a205b35332c203133302c203136382c2035372c203138332c203231352c203132302c203137382c203230392c2033302c203139342c203232332c203232312c2035382c2037322c203132342c2036322c203134382c203131302c2038312c2031392c203138392c2032372c203234332c203231382c2038372c203231372c203230332c203139382c2039372c2038342c2031395d7d227d0000ffff00003030303030303635007b2274797065223a20225645222c202264617461223a20227b5c2267656e657369735f707265765f686561646572686173685c223a205c2243727970746f6e69756d5c222c205c2276657273696f6e5c223a205c22616c7068612f302e3435615c227d227d0000ff'