mirror of
https://github.com/m2049r/xmrwallet
synced 2025-04-15 11:41:13 +02:00
tweaks for monero v0.14.1.0 (#598)
This commit is contained in:
parent
bf91eaf22f
commit
64d5b3bdea
app
external-libs
@ -139,6 +139,10 @@ add_library(device STATIC IMPORTED)
|
|||||||
set_target_properties(device PROPERTIES IMPORTED_LOCATION
|
set_target_properties(device PROPERTIES IMPORTED_LOCATION
|
||||||
${EXTERNAL_LIBS_DIR}/monero/lib/${ANDROID_ABI}/libdevice.a)
|
${EXTERNAL_LIBS_DIR}/monero/lib/${ANDROID_ABI}/libdevice.a)
|
||||||
|
|
||||||
|
add_library(device_trezor STATIC IMPORTED)
|
||||||
|
set_target_properties(device_trezor PROPERTIES IMPORTED_LOCATION
|
||||||
|
${EXTERNAL_LIBS_DIR}/monero/lib/${ANDROID_ABI}/libdevice_trezor.a)
|
||||||
|
|
||||||
add_library(multisig STATIC IMPORTED)
|
add_library(multisig STATIC IMPORTED)
|
||||||
set_target_properties(multisig PROPERTIES IMPORTED_LOCATION
|
set_target_properties(multisig PROPERTIES IMPORTED_LOCATION
|
||||||
${EXTERNAL_LIBS_DIR}/monero/lib/${ANDROID_ABI}/libmultisig.a)
|
${EXTERNAL_LIBS_DIR}/monero/lib/${ANDROID_ABI}/libmultisig.a)
|
||||||
@ -147,6 +151,10 @@ add_library(version STATIC IMPORTED)
|
|||||||
set_target_properties(version PROPERTIES IMPORTED_LOCATION
|
set_target_properties(version PROPERTIES IMPORTED_LOCATION
|
||||||
${EXTERNAL_LIBS_DIR}/monero/lib/${ANDROID_ABI}/libversion.a)
|
${EXTERNAL_LIBS_DIR}/monero/lib/${ANDROID_ABI}/libversion.a)
|
||||||
|
|
||||||
|
add_library(net STATIC IMPORTED)
|
||||||
|
set_target_properties(net PROPERTIES IMPORTED_LOCATION
|
||||||
|
${EXTERNAL_LIBS_DIR}/monero/lib/${ANDROID_ABI}/libnet.a)
|
||||||
|
|
||||||
#############
|
#############
|
||||||
# System
|
# System
|
||||||
#############
|
#############
|
||||||
@ -166,6 +174,7 @@ target_link_libraries( monerujo
|
|||||||
mnemonics
|
mnemonics
|
||||||
ringct
|
ringct
|
||||||
ringct_basic
|
ringct_basic
|
||||||
|
net
|
||||||
common
|
common
|
||||||
cncrypto
|
cncrypto
|
||||||
blockchain_db
|
blockchain_db
|
||||||
@ -176,6 +185,7 @@ target_link_libraries( monerujo
|
|||||||
blocks
|
blocks
|
||||||
checkpoints
|
checkpoints
|
||||||
device
|
device
|
||||||
|
device_trezor
|
||||||
multisig
|
multisig
|
||||||
version
|
version
|
||||||
|
|
||||||
|
@ -7,8 +7,8 @@ android {
|
|||||||
applicationId "com.m2049r.xmrwallet"
|
applicationId "com.m2049r.xmrwallet"
|
||||||
minSdkVersion 21
|
minSdkVersion 21
|
||||||
targetSdkVersion 28
|
targetSdkVersion 28
|
||||||
versionCode 177
|
versionCode 178
|
||||||
versionName "1.11.7 'Chernushka'"
|
versionName "1.11.8 'Chernushka'"
|
||||||
|
|
||||||
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
||||||
externalNativeBuild {
|
externalNativeBuild {
|
||||||
|
@ -1,88 +0,0 @@
|
|||||||
// Copyright (c) 2017-2018, The Monero Project
|
|
||||||
//
|
|
||||||
// All rights reserved.
|
|
||||||
//
|
|
||||||
// Redistribution and use in source and binary forms, with or without modification, are
|
|
||||||
// permitted provided that the following conditions are met:
|
|
||||||
//
|
|
||||||
// 1. Redistributions of source code must retain the above copyright notice, this list of
|
|
||||||
// conditions and the following disclaimer.
|
|
||||||
//
|
|
||||||
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
|
|
||||||
// of conditions and the following disclaimer in the documentation and/or other
|
|
||||||
// materials provided with the distribution.
|
|
||||||
//
|
|
||||||
// 3. Neither the name of the copyright holder nor the names of its contributors may be
|
|
||||||
// used to endorse or promote products derived from this software without specific
|
|
||||||
// prior written permission.
|
|
||||||
//
|
|
||||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
|
|
||||||
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
|
||||||
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
|
||||||
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
|
||||||
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
||||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
|
||||||
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
|
||||||
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
//
|
|
||||||
|
|
||||||
#if defined(HAVE_MONERUJO)
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C"
|
|
||||||
{
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief LedgerFind - find Ledger Device and return it's name
|
|
||||||
* @param buffer - buffer for name of found device
|
|
||||||
* @param len - length of buffer
|
|
||||||
* @return 0 - success
|
|
||||||
* -1 - no device connected / found
|
|
||||||
* -2 - JVM not found
|
|
||||||
*/
|
|
||||||
int LedgerFind(char *buffer, size_t len);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief LedgerExchange - exchange data with Ledger Device
|
|
||||||
* @param command - buffer for data to send
|
|
||||||
* @param cmd_len - length of send to send
|
|
||||||
* @param response - buffer for received data
|
|
||||||
* @param max_resp_len - size of receive buffer
|
|
||||||
*
|
|
||||||
* @return length of received data in response or -1 if error
|
|
||||||
*/
|
|
||||||
int LedgerExchange(unsigned char *command, unsigned int cmd_len, unsigned char *response, unsigned int max_resp_len);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "device_io.hpp"
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
namespace hw {
|
|
||||||
namespace io {
|
|
||||||
class device_io_monerujo: device_io {
|
|
||||||
public:
|
|
||||||
device_io_monerujo() {};
|
|
||||||
~device_io_monerujo() {};
|
|
||||||
|
|
||||||
void init() {};
|
|
||||||
void release() {};
|
|
||||||
|
|
||||||
void connect(void *params) {};
|
|
||||||
void disconnect() {};
|
|
||||||
bool connected() const {return true;}; // monerujo is always connected before it gets here
|
|
||||||
|
|
||||||
// returns number of bytes read or -1 on error
|
|
||||||
int exchange(unsigned char *command, unsigned int cmd_len, unsigned char *response, unsigned int max_resp_len) {
|
|
||||||
return LedgerExchange(command, cmd_len, response, max_resp_len);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif //#if defined(HAVE_MONERUJO)
|
|
@ -1382,8 +1382,6 @@ Java_com_m2049r_xmrwallet_model_WalletManager_setLogLevel(JNIEnv *env, jclass cl
|
|||||||
// Ledger Stuff
|
// Ledger Stuff
|
||||||
//
|
//
|
||||||
|
|
||||||
#include "device_io_monerujo.hpp"
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief LedgerExchange - exchange data with Ledger Device
|
* @brief LedgerExchange - exchange data with Ledger Device
|
||||||
* @param command - buffer for data to send
|
* @param command - buffer for data to send
|
||||||
@ -1417,7 +1415,7 @@ int LedgerExchange(
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
jsize len = jenv->GetArrayLength(dataRecv);
|
jsize len = jenv->GetArrayLength(dataRecv);
|
||||||
LOGD("LedgerExchange SCARD_S_SUCCESS %ld/%d", cmd_len, len);
|
LOGD("LedgerExchange SCARD_S_SUCCESS %u/%d", cmd_len, len);
|
||||||
if (len <= max_resp_len) {
|
if (len <= max_resp_len) {
|
||||||
jenv->GetByteArrayRegion(dataRecv, 0, len, (jbyte *) response);
|
jenv->GetByteArrayRegion(dataRecv, 0, len, (jbyte *) response);
|
||||||
jenv->DeleteLocalRef(dataRecv);
|
jenv->DeleteLocalRef(dataRecv);
|
||||||
|
@ -17,7 +17,6 @@ monero: toolchain libsodium openssl boost monero_dl openssl_sysroot
|
|||||||
|
|
||||||
monero_dl:
|
monero_dl:
|
||||||
script/monero-fetch.sh
|
script/monero-fetch.sh
|
||||||
# script/monero-patch.sh
|
|
||||||
|
|
||||||
toolchain:
|
toolchain:
|
||||||
script/toolchain-build.sh
|
script/toolchain-build.sh
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
// Copyright (c) 2014-2018, The Monero Project
|
// Copyright (c) 2014-2019, The Monero Project
|
||||||
//
|
//
|
||||||
// All rights reserved.
|
// All rights reserved.
|
||||||
//
|
//
|
||||||
@ -37,6 +37,7 @@
|
|||||||
#include <set>
|
#include <set>
|
||||||
#include <ctime>
|
#include <ctime>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
// Public interface for libwallet library
|
// Public interface for libwallet library
|
||||||
namespace Monero {
|
namespace Monero {
|
||||||
@ -324,6 +325,20 @@ struct MultisigState {
|
|||||||
uint32_t total;
|
uint32_t total;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct DeviceProgress {
|
||||||
|
DeviceProgress(): m_progress(0), m_indeterminate(false) {}
|
||||||
|
DeviceProgress(double progress, bool indeterminate=false): m_progress(progress), m_indeterminate(indeterminate) {}
|
||||||
|
|
||||||
|
virtual double progress() const { return m_progress; }
|
||||||
|
virtual bool indeterminate() const { return m_indeterminate; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
double m_progress;
|
||||||
|
bool m_indeterminate;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Wallet;
|
||||||
struct WalletListener
|
struct WalletListener
|
||||||
{
|
{
|
||||||
virtual ~WalletListener() = 0;
|
virtual ~WalletListener() = 0;
|
||||||
@ -364,6 +379,41 @@ struct WalletListener
|
|||||||
* @brief refreshed - called when wallet refreshed by background thread or explicitly refreshed by calling "refresh" synchronously
|
* @brief refreshed - called when wallet refreshed by background thread or explicitly refreshed by calling "refresh" synchronously
|
||||||
*/
|
*/
|
||||||
virtual void refreshed() = 0;
|
virtual void refreshed() = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief called by device if the action is required
|
||||||
|
*/
|
||||||
|
virtual void onDeviceButtonRequest(uint64_t code) { (void)code; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief called by device if the button was pressed
|
||||||
|
*/
|
||||||
|
virtual void onDeviceButtonPressed() { }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief called by device when PIN is needed
|
||||||
|
*/
|
||||||
|
virtual optional<std::string> onDevicePinRequest() {
|
||||||
|
throw std::runtime_error("Not supported");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief called by device when passphrase entry is needed
|
||||||
|
*/
|
||||||
|
virtual optional<std::string> onDevicePassphraseRequest(bool on_device) {
|
||||||
|
if (!on_device) throw std::runtime_error("Not supported");
|
||||||
|
return optional<std::string>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Signalizes device operation progress
|
||||||
|
*/
|
||||||
|
virtual void onDeviceProgress(const DeviceProgress & event) { (void)event; };
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief If the listener is created before the wallet this enables to set created wallet object
|
||||||
|
*/
|
||||||
|
virtual void onSetWallet(Wallet * wallet) { (void)wallet; };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -375,7 +425,8 @@ struct Wallet
|
|||||||
{
|
{
|
||||||
enum Device {
|
enum Device {
|
||||||
Device_Software = 0,
|
Device_Software = 0,
|
||||||
Device_Ledger = 1
|
Device_Ledger = 1,
|
||||||
|
Device_Trezor = 2
|
||||||
};
|
};
|
||||||
|
|
||||||
enum Status {
|
enum Status {
|
||||||
@ -401,6 +452,8 @@ struct Wallet
|
|||||||
//! returns both error and error string atomically. suggested to use in instead of status() and errorString()
|
//! returns both error and error string atomically. suggested to use in instead of status() and errorString()
|
||||||
virtual void statusWithErrorString(int& status, std::string& errorString) const = 0;
|
virtual void statusWithErrorString(int& status, std::string& errorString) const = 0;
|
||||||
virtual bool setPassword(const std::string &password) = 0;
|
virtual bool setPassword(const std::string &password) = 0;
|
||||||
|
virtual bool setDevicePin(const std::string &pin) { (void)pin; return false; };
|
||||||
|
virtual bool setDevicePassphrase(const std::string &passphrase) { (void)passphrase; return false; };
|
||||||
virtual std::string address(uint32_t accountIndex = 0, uint32_t addressIndex = 0) const = 0;
|
virtual std::string address(uint32_t accountIndex = 0, uint32_t addressIndex = 0) const = 0;
|
||||||
std::string mainAddress() const { return address(0, 0); }
|
std::string mainAddress() const { return address(0, 0); }
|
||||||
virtual std::string path() const = 0;
|
virtual std::string path() const = 0;
|
||||||
@ -649,6 +702,17 @@ struct Wallet
|
|||||||
*/
|
*/
|
||||||
virtual void refreshAsync() = 0;
|
virtual void refreshAsync() = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief rescanBlockchain - rescans the wallet, updating transactions from daemon
|
||||||
|
* @return - true if refreshed successfully;
|
||||||
|
*/
|
||||||
|
virtual bool rescanBlockchain() = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief rescanBlockchainAsync - rescans wallet asynchronously, starting from genesys
|
||||||
|
*/
|
||||||
|
virtual void rescanBlockchainAsync() = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief setAutoRefreshInterval - setup interval for automatic refresh.
|
* @brief setAutoRefreshInterval - setup interval for automatic refresh.
|
||||||
* @param seconds - interval in millis. if zero or less than zero - automatic refresh disabled;
|
* @param seconds - interval in millis. if zero or less than zero - automatic refresh disabled;
|
||||||
@ -936,6 +1000,9 @@ struct Wallet
|
|||||||
* \return Device they are on
|
* \return Device they are on
|
||||||
*/
|
*/
|
||||||
virtual Device getDeviceType() const = 0;
|
virtual Device getDeviceType() const = 0;
|
||||||
|
|
||||||
|
//! cold-device protocol key image sync
|
||||||
|
virtual uint64_t coldKeyImageSync(uint64_t &spent, uint64_t &unspent) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -965,9 +1032,10 @@ struct WalletManager
|
|||||||
* \param password Password of wallet file
|
* \param password Password of wallet file
|
||||||
* \param nettype Network type
|
* \param nettype Network type
|
||||||
* \param kdf_rounds Number of rounds for key derivation function
|
* \param kdf_rounds Number of rounds for key derivation function
|
||||||
|
* \param listener Wallet listener to set to the wallet after creation
|
||||||
* \return Wallet instance (Wallet::status() needs to be called to check if opened successfully)
|
* \return Wallet instance (Wallet::status() needs to be called to check if opened successfully)
|
||||||
*/
|
*/
|
||||||
virtual Wallet * openWallet(const std::string &path, const std::string &password, NetworkType nettype, uint64_t kdf_rounds = 1) = 0;
|
virtual Wallet * openWallet(const std::string &path, const std::string &password, NetworkType nettype, uint64_t kdf_rounds = 1, WalletListener * listener = nullptr) = 0;
|
||||||
Wallet * openWallet(const std::string &path, const std::string &password, bool testnet = false) // deprecated
|
Wallet * openWallet(const std::string &path, const std::string &password, bool testnet = false) // deprecated
|
||||||
{
|
{
|
||||||
return openWallet(path, password, testnet ? TESTNET : MAINNET);
|
return openWallet(path, password, testnet ? TESTNET : MAINNET);
|
||||||
@ -1079,6 +1147,7 @@ struct WalletManager
|
|||||||
* \param restoreHeight restore from start height (0 sets to current height)
|
* \param restoreHeight restore from start height (0 sets to current height)
|
||||||
* \param subaddressLookahead Size of subaddress lookahead (empty sets to some default low value)
|
* \param subaddressLookahead Size of subaddress lookahead (empty sets to some default low value)
|
||||||
* \param kdf_rounds Number of rounds for key derivation function
|
* \param kdf_rounds Number of rounds for key derivation function
|
||||||
|
* \param listener Wallet listener to set to the wallet after creation
|
||||||
* \return Wallet instance (Wallet::status() needs to be called to check if recovered successfully)
|
* \return Wallet instance (Wallet::status() needs to be called to check if recovered successfully)
|
||||||
*/
|
*/
|
||||||
virtual Wallet * createWalletFromDevice(const std::string &path,
|
virtual Wallet * createWalletFromDevice(const std::string &path,
|
||||||
@ -1087,7 +1156,8 @@ struct WalletManager
|
|||||||
const std::string &deviceName,
|
const std::string &deviceName,
|
||||||
uint64_t restoreHeight = 0,
|
uint64_t restoreHeight = 0,
|
||||||
const std::string &subaddressLookahead = "",
|
const std::string &subaddressLookahead = "",
|
||||||
uint64_t kdf_rounds = 1) = 0;
|
uint64_t kdf_rounds = 1,
|
||||||
|
WalletListener * listener = nullptr) = 0;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Closes wallet. In case operation succeeded, wallet object deleted. in case operation failed, wallet object not deleted
|
* \brief Closes wallet. In case operation succeeded, wallet object deleted. in case operation failed, wallet object not deleted
|
||||||
|
@ -77,6 +77,7 @@ for arch in ${archs[@]}; do
|
|||||||
-D OPENSSL_SSL_LIBRARY=$lib_root/openssl/$arch/lib/libssl.so \
|
-D OPENSSL_SSL_LIBRARY=$lib_root/openssl/$arch/lib/libssl.so \
|
||||||
-D CMAKE_POSITION_INDEPENDENT_CODE:BOOL=true \
|
-D CMAKE_POSITION_INDEPENDENT_CODE:BOOL=true \
|
||||||
-D MONERUJO_HIDAPI=ON \
|
-D MONERUJO_HIDAPI=ON \
|
||||||
|
-D USE_DEVICE_TREZOR=OFF \
|
||||||
-D LIBSODIUM_INCLUDE_DIR=$lib_root/libsodium/$arch/include \
|
-D LIBSODIUM_INCLUDE_DIR=$lib_root/libsodium/$arch/include \
|
||||||
$extra_cmake_flags \
|
$extra_cmake_flags \
|
||||||
../..
|
../..
|
||||||
|
@ -7,7 +7,7 @@ source script/env.sh
|
|||||||
cd $EXTERNAL_LIBS_BUILD_ROOT
|
cd $EXTERNAL_LIBS_BUILD_ROOT
|
||||||
|
|
||||||
url="https://github.com/m2049r/monero"
|
url="https://github.com/m2049r/monero"
|
||||||
version="release-v0.14.0-monerujo"
|
version="release-v0.14.1.0-monerujo"
|
||||||
|
|
||||||
if [ ! -d "monero" ]; then
|
if [ ! -d "monero" ]; then
|
||||||
git clone ${url} -b ${version}
|
git clone ${url} -b ${version}
|
||||||
|
@ -1,26 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
source script/build-external-libs/env.sh
|
|
||||||
|
|
||||||
cp script/build-external-libs/wownero/build-all-arch.sh $EXTERNAL_LIBS_BUILD_ROOT/wownero
|
|
||||||
|
|
||||||
cd $EXTERNAL_LIBS_BUILD_ROOT
|
|
||||||
cd wownero
|
|
||||||
|
|
||||||
sed -i 's/-Werror/-Wall/g' CMakeLists.txt
|
|
||||||
sed -i 's/program_options locale/program_options/g' CMakeLists.txt
|
|
||||||
sed -i 's/find_path(ZMQ_INCLUDE_PATH zmq.hpp)//g' CMakeLists.txt
|
|
||||||
sed -i 's/find_library(ZMQ_LIB zmq)//g' CMakeLists.txt
|
|
||||||
sed -i 's/message(FATAL_ERROR "Could not find required header zmq.hpp")//g' CMakeLists.txt
|
|
||||||
sed -i 's/message(FATAL_ERROR "Could not find required libzmq")//g' CMakeLists.txt
|
|
||||||
sed -i 's/bool create_address_file = false/bool create_address_file = true/g' src/wallet/wallet2.h
|
|
||||||
|
|
||||||
sodium_pattern="find_library(SODIUM_LIBRARY sodium)"
|
|
||||||
include_sodium='find_library(SODIUM_LIBRARY sodium)\
|
|
||||||
\
|
|
||||||
message(STATUS "Using SODIUM include dir at ${LIBSODIUM_INCLUDE_DIR}")\
|
|
||||||
include_directories(${LIBSODIUM_INCLUDE_DIR})'
|
|
||||||
|
|
||||||
sed -i "s/${sodium_pattern}/${include_sodium}/g" CMakeLists.txt
|
|
Loading…
x
Reference in New Issue
Block a user