txdb: handle state and balance differently.
This commit is contained in:
parent
06a104c34d
commit
2e56a82280
@ -551,18 +551,18 @@ Address.getHash = function getHash(data, enc) {
|
|||||||
if (typeof data === 'string') {
|
if (typeof data === 'string') {
|
||||||
if (data.length === 40 || data.length === 64)
|
if (data.length === 40 || data.length === 64)
|
||||||
return enc === 'hex' ? data : new Buffer(data, 'hex');
|
return enc === 'hex' ? data : new Buffer(data, 'hex');
|
||||||
}
|
|
||||||
|
|
||||||
if (Buffer.isBuffer(data)) {
|
|
||||||
hash = data;
|
|
||||||
} else if (data instanceof Address) {
|
|
||||||
hash = data.hash;
|
|
||||||
} else {
|
|
||||||
try {
|
try {
|
||||||
hash = Address.fromBase58(data).hash;
|
hash = Address.fromBase58(data).hash;
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
} else if (Buffer.isBuffer(data)) {
|
||||||
|
hash = data;
|
||||||
|
} else if (data instanceof Address) {
|
||||||
|
hash = data.hash;
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
return enc === 'hex'
|
return enc === 'hex'
|
||||||
|
|||||||
@ -217,7 +217,6 @@ function TXDB(wallet) {
|
|||||||
|
|
||||||
this.locked = {};
|
this.locked = {};
|
||||||
this.state = null;
|
this.state = null;
|
||||||
this.balance = null;
|
|
||||||
this.pending = null;
|
this.pending = null;
|
||||||
this.events = [];
|
this.events = [];
|
||||||
|
|
||||||
@ -249,15 +248,13 @@ TXDB.prototype.open = co(function* open() {
|
|||||||
this.logger.info('TXDB created for %s.', this.wallet.id);
|
this.logger.info('TXDB created for %s.', this.wallet.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.balance = this.state.balance;
|
|
||||||
|
|
||||||
this.logger.info('TXDB State: tx=%d coin=%s.',
|
this.logger.info('TXDB State: tx=%d coin=%s.',
|
||||||
this.state.tx, this.state.coin);
|
this.state.tx, this.state.coin);
|
||||||
|
|
||||||
this.logger.info(
|
this.logger.info(
|
||||||
'Balance: unconfirmed=%s confirmed=%s.',
|
'Balance: unconfirmed=%s confirmed=%s.',
|
||||||
utils.btc(this.balance.unconfirmed),
|
utils.btc(this.state.unconfirmed),
|
||||||
utils.btc(this.balance.confirmed));
|
utils.btc(this.state.confirmed));
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -312,7 +309,6 @@ TXDB.prototype.commit = co(function* commit() {
|
|||||||
// with our new committed state.
|
// with our new committed state.
|
||||||
if (this.pending.committed) {
|
if (this.pending.committed) {
|
||||||
this.state = this.pending;
|
this.state = this.pending;
|
||||||
this.balance = this.state.balance;
|
|
||||||
|
|
||||||
// Emit buffered events now that
|
// Emit buffered events now that
|
||||||
// we know everything is written.
|
// we know everything is written.
|
||||||
@ -478,7 +474,7 @@ TXDB.prototype.verifyInputs = co(function* verifyInputs(tx) {
|
|||||||
var hash = tx.hash('hex');
|
var hash = tx.hash('hex');
|
||||||
var hasOrphans = false;
|
var hasOrphans = false;
|
||||||
var orphans = [];
|
var orphans = [];
|
||||||
var i, input, prevout, address;
|
var i, input, prevout;
|
||||||
var path, key, coin, spent;
|
var path, key, coin, spent;
|
||||||
|
|
||||||
if (tx.isCoinbase())
|
if (tx.isCoinbase())
|
||||||
@ -494,9 +490,6 @@ TXDB.prototype.verifyInputs = co(function* verifyInputs(tx) {
|
|||||||
spent = yield this.isSpent(prevout.hash, prevout.index);
|
spent = yield this.isSpent(prevout.hash, prevout.index);
|
||||||
|
|
||||||
if (spent) {
|
if (spent) {
|
||||||
if (tx.height === -1)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
coin = yield this.getSpentCoin(spent, prevout);
|
coin = yield this.getSpentCoin(spent, prevout);
|
||||||
assert(coin);
|
assert(coin);
|
||||||
|
|
||||||
@ -523,8 +516,7 @@ TXDB.prototype.verifyInputs = co(function* verifyInputs(tx) {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
address = input.getHash('hex');
|
path = yield this.wallet.hasPath(input.getAddress());
|
||||||
path = yield this.wallet.hasPath(address);
|
|
||||||
|
|
||||||
if (!path)
|
if (!path)
|
||||||
continue;
|
continue;
|
||||||
@ -761,16 +753,17 @@ TXDB.prototype._add = co(function* add(tx, info) {
|
|||||||
|
|
||||||
this.put(layout.s(prevout.hash, prevout.index), spender);
|
this.put(layout.s(prevout.hash, prevout.index), spender);
|
||||||
|
|
||||||
this.pending.balance.unconfirmed -= coin.value;
|
this.pending.unconfirmed -= coin.value;
|
||||||
|
|
||||||
if (tx.height === -1) {
|
if (tx.height === -1) {
|
||||||
this.put(layout.S(prevout.hash, prevout.index), spender);
|
this.put(layout.S(prevout.hash, prevout.index), spender);
|
||||||
this.spentCache.set(key, spender);
|
this.spentCache.set(key, spender);
|
||||||
} else {
|
} else {
|
||||||
this.pending.balance.confirmed -= coin.value;
|
this.pending.confirmed -= coin.value;
|
||||||
this.del(layout.c(prevout.hash, prevout.index));
|
this.del(layout.c(prevout.hash, prevout.index));
|
||||||
this.del(layout.C(path.account, prevout.hash, prevout.index));
|
this.del(layout.C(path.account, prevout.hash, prevout.index));
|
||||||
this.coinCache.remove(key);
|
this.coinCache.remove(key);
|
||||||
|
this.pending.coin--;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.put(layout.d(hash, i), coin.toRaw());
|
this.put(layout.d(hash, i), coin.toRaw());
|
||||||
@ -791,13 +784,14 @@ TXDB.prototype._add = co(function* add(tx, info) {
|
|||||||
coin = Coin.fromTX(tx, i);
|
coin = Coin.fromTX(tx, i);
|
||||||
raw = coin.toRaw();
|
raw = coin.toRaw();
|
||||||
|
|
||||||
this.pending.balance.unconfirmed += coin.value;
|
this.pending.unconfirmed += coin.value;
|
||||||
|
|
||||||
if (tx.height !== -1)
|
if (tx.height !== -1)
|
||||||
this.pending.balance.confirmed += coin.value;
|
this.pending.confirmed += coin.value;
|
||||||
|
|
||||||
this.put(layout.c(hash, i), raw);
|
this.put(layout.c(hash, i), raw);
|
||||||
this.put(layout.C(path.account, hash, i), DUMMY);
|
this.put(layout.C(path.account, hash, i), DUMMY);
|
||||||
|
this.pending.coin++;
|
||||||
|
|
||||||
this.coinCache.set(key, raw);
|
this.coinCache.set(key, raw);
|
||||||
}
|
}
|
||||||
@ -813,7 +807,7 @@ TXDB.prototype._add = co(function* add(tx, info) {
|
|||||||
if (tx.height !== -1)
|
if (tx.height !== -1)
|
||||||
this.emit('confirmed', tx, info);
|
this.emit('confirmed', tx, info);
|
||||||
|
|
||||||
this.emit('balance', this.pending.balance, info);
|
this.emit('balance', this.pending.toBalance(), info);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
@ -1017,7 +1011,7 @@ TXDB.prototype.confirm = co(function* confirm(tx, info) {
|
|||||||
this.put(layout.d(hash, i), coin.toRaw());
|
this.put(layout.d(hash, i), coin.toRaw());
|
||||||
this.put(layout.s(prevout.hash, prevout.index), spender);
|
this.put(layout.s(prevout.hash, prevout.index), spender);
|
||||||
|
|
||||||
this.pending.balance.unconfirmed -= coin.value;
|
this.pending.unconfirmed -= coin.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(coin.height !== -1);
|
assert(coin.height !== -1);
|
||||||
@ -1032,7 +1026,8 @@ TXDB.prototype.confirm = co(function* confirm(tx, info) {
|
|||||||
this.del(layout.c(prevout.hash, prevout.index));
|
this.del(layout.c(prevout.hash, prevout.index));
|
||||||
this.del(layout.C(path.account, prevout.hash, prevout.index));
|
this.del(layout.C(path.account, prevout.hash, prevout.index));
|
||||||
|
|
||||||
this.pending.balance.confirmed -= coin.value;
|
this.pending.coin--;
|
||||||
|
this.pending.confirmed -= coin.value;
|
||||||
|
|
||||||
this.spentCache.remove(key);
|
this.spentCache.remove(key);
|
||||||
this.coinCache.remove(key);
|
this.coinCache.remove(key);
|
||||||
@ -1058,7 +1053,8 @@ TXDB.prototype.confirm = co(function* confirm(tx, info) {
|
|||||||
coin.height = tx.height;
|
coin.height = tx.height;
|
||||||
raw = coin.toRaw();
|
raw = coin.toRaw();
|
||||||
|
|
||||||
this.pending.balance.confirmed += coin.value;
|
this.pending.confirmed += coin.value;
|
||||||
|
this.pending.coin++;
|
||||||
|
|
||||||
this.put(layout.c(hash, i), raw);
|
this.put(layout.c(hash, i), raw);
|
||||||
|
|
||||||
@ -1072,7 +1068,7 @@ TXDB.prototype.confirm = co(function* confirm(tx, info) {
|
|||||||
|
|
||||||
this.emit('tx', tx, info);
|
this.emit('tx', tx, info);
|
||||||
this.emit('confirmed', tx, info);
|
this.emit('confirmed', tx, info);
|
||||||
this.emit('balance', this.pending.balance, info);
|
this.emit('balance', this.pending.toBalance(), info);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
@ -1192,13 +1188,14 @@ TXDB.prototype.__remove = co(function* remove(tx, info) {
|
|||||||
path = info.getPath(coin);
|
path = info.getPath(coin);
|
||||||
assert(path);
|
assert(path);
|
||||||
|
|
||||||
this.pending.balance.unconfirmed += coin.value;
|
this.pending.unconfirmed += coin.value;
|
||||||
|
|
||||||
this.del(layout.s(prevout.hash, prevout.index));
|
this.del(layout.s(prevout.hash, prevout.index));
|
||||||
|
|
||||||
if (tx.height !== -1) {
|
if (tx.height !== -1) {
|
||||||
raw = coin.toRaw();
|
raw = coin.toRaw();
|
||||||
this.pending.balance.confirmed += coin.value;
|
this.pending.confirmed += coin.value;
|
||||||
|
this.pending.coin++;
|
||||||
this.put(layout.c(prevout.hash, prevout.index), raw);
|
this.put(layout.c(prevout.hash, prevout.index), raw);
|
||||||
this.put(layout.C(path.account, prevout.hash, prevout.index), DUMMY);
|
this.put(layout.C(path.account, prevout.hash, prevout.index), DUMMY);
|
||||||
this.coinCache.set(key, raw);
|
this.coinCache.set(key, raw);
|
||||||
@ -1221,10 +1218,11 @@ TXDB.prototype.__remove = co(function* remove(tx, info) {
|
|||||||
|
|
||||||
coin = Coin.fromTX(tx, i);
|
coin = Coin.fromTX(tx, i);
|
||||||
|
|
||||||
this.pending.balance.unconfirmed -= coin.value;
|
this.pending.coin--;
|
||||||
|
this.pending.unconfirmed -= coin.value;
|
||||||
|
|
||||||
if (tx.height !== -1)
|
if (tx.height !== -1)
|
||||||
this.pending.balance.confirmed -= coin.value;
|
this.pending.confirmed -= coin.value;
|
||||||
|
|
||||||
this.del(layout.c(hash, i));
|
this.del(layout.c(hash, i));
|
||||||
this.del(layout.C(path.account, hash, i));
|
this.del(layout.C(path.account, hash, i));
|
||||||
@ -1236,7 +1234,7 @@ TXDB.prototype.__remove = co(function* remove(tx, info) {
|
|||||||
this.put(layout.R, this.pending.commit());
|
this.put(layout.R, this.pending.commit());
|
||||||
|
|
||||||
this.emit('remove tx', tx, info);
|
this.emit('remove tx', tx, info);
|
||||||
this.emit('balance', this.pending.balance, info);
|
this.emit('balance', this.pending.toBalance(), info);
|
||||||
|
|
||||||
return info;
|
return info;
|
||||||
});
|
});
|
||||||
@ -1345,7 +1343,8 @@ TXDB.prototype.__unconfirm = co(function* unconfirm(tx, info) {
|
|||||||
this.put(layout.c(prevout.hash, prevout.index), raw);
|
this.put(layout.c(prevout.hash, prevout.index), raw);
|
||||||
this.put(layout.C(path.account, prevout.hash, prevout.index), DUMMY);
|
this.put(layout.C(path.account, prevout.hash, prevout.index), DUMMY);
|
||||||
|
|
||||||
this.pending.balance.confirmed += coin.value;
|
this.pending.coin++;
|
||||||
|
this.pending.confirmed += coin.value;
|
||||||
|
|
||||||
this.spentCache.set(key, spender);
|
this.spentCache.set(key, spender);
|
||||||
this.coinCache.set(key, raw);
|
this.coinCache.set(key, raw);
|
||||||
@ -1365,18 +1364,20 @@ TXDB.prototype.__unconfirm = co(function* unconfirm(tx, info) {
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
coin.height = -1;
|
coin.height = -1;
|
||||||
|
raw = coin.toRaw();
|
||||||
|
|
||||||
this.pending.balance.confirmed -= coin.value;
|
this.pending.confirmed -= coin.value;
|
||||||
|
this.pending.coin++;
|
||||||
|
|
||||||
this.put(layout.c(hash, i), coin.toRaw());
|
this.put(layout.c(hash, i), raw);
|
||||||
|
|
||||||
this.coinCache.remove(key);
|
this.coinCache.set(key, raw);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.put(layout.R, this.pending.commit());
|
this.put(layout.R, this.pending.commit());
|
||||||
|
|
||||||
this.emit('unconfirmed', tx, info);
|
this.emit('unconfirmed', tx, info);
|
||||||
this.emit('balance', this.pending.balance, info);
|
this.emit('balance', this.pending.toBalance(), info);
|
||||||
|
|
||||||
return info;
|
return info;
|
||||||
});
|
});
|
||||||
@ -2185,7 +2186,7 @@ TXDB.prototype.getBalance = co(function* getBalance(account) {
|
|||||||
return yield this.getAccountBalance(account);
|
return yield this.getAccountBalance(account);
|
||||||
|
|
||||||
// Fast case
|
// Fast case
|
||||||
return this.balance;
|
return this.state.toBalance();
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -2248,8 +2249,7 @@ TXDB.prototype.zap = co(function* zap(account, age) {
|
|||||||
var now = utils.now();
|
var now = utils.now();
|
||||||
var i, txs, tx, hash;
|
var i, txs, tx, hash;
|
||||||
|
|
||||||
if (!utils.isUInt32(age))
|
assert(utils.isUInt32(age));
|
||||||
throw new Error('Age must be a number.');
|
|
||||||
|
|
||||||
txs = yield this.getRange(account, {
|
txs = yield this.getRange(account, {
|
||||||
start: 0,
|
start: 0,
|
||||||
@ -2304,66 +2304,12 @@ function Balance(wid, id, account) {
|
|||||||
this.confirmed = 0;
|
this.confirmed = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Balance.prototype.clone = function clone() {
|
|
||||||
var balance = new Balance(this.wid, this.id, this.account);
|
|
||||||
balance.unconfirmed = this.unconfirmed;
|
|
||||||
balance.confirmed = this.confirmed;
|
|
||||||
return balance;
|
|
||||||
};
|
|
||||||
|
|
||||||
Balance.prototype.equal = function equal(balance) {
|
Balance.prototype.equal = function equal(balance) {
|
||||||
return this.wid === balance.wid
|
return this.wid === balance.wid
|
||||||
&& this.confirmed === balance.confirmed
|
&& this.confirmed === balance.confirmed
|
||||||
&& this.unconfirmed === balance.unconfirmed;
|
&& this.unconfirmed === balance.unconfirmed;
|
||||||
};
|
};
|
||||||
|
|
||||||
Balance.prototype.add = function add(coin) {
|
|
||||||
if (coin.height === -1)
|
|
||||||
this.unconfirmed += coin.value;
|
|
||||||
else
|
|
||||||
this.confirmed += coin.value;
|
|
||||||
};
|
|
||||||
|
|
||||||
Balance.prototype.sub = function sub(coin) {
|
|
||||||
if (coin.height === -1)
|
|
||||||
this.unconfirmed -= coin.value;
|
|
||||||
else
|
|
||||||
this.confirmed -= coin.value;
|
|
||||||
};
|
|
||||||
|
|
||||||
Balance.prototype.confirm = function confirm(value) {
|
|
||||||
this.unconfirmed -= value;
|
|
||||||
this.confirmed += value;
|
|
||||||
};
|
|
||||||
|
|
||||||
Balance.prototype.unconfirm = function unconfirm(value) {
|
|
||||||
this.unconfirmed += value;
|
|
||||||
this.confirmed -= value;
|
|
||||||
};
|
|
||||||
|
|
||||||
Balance.prototype.toRaw = function toRaw(writer) {
|
|
||||||
var p = new BufferWriter(writer);
|
|
||||||
|
|
||||||
p.writeU64(this.unconfirmed);
|
|
||||||
p.writeU64(this.confirmed);
|
|
||||||
|
|
||||||
if (!writer)
|
|
||||||
p = p.render();
|
|
||||||
|
|
||||||
return p;
|
|
||||||
};
|
|
||||||
|
|
||||||
Balance.prototype.fromRaw = function fromRaw(data) {
|
|
||||||
var p = new BufferReader(data);
|
|
||||||
this.unconfirmed = p.readU53();
|
|
||||||
this.confirmed = p.readU53();
|
|
||||||
return this;
|
|
||||||
};
|
|
||||||
|
|
||||||
Balance.fromRaw = function fromRaw(wid, id, data) {
|
|
||||||
return new Balance(wid, id, -1).fromRaw(data);
|
|
||||||
};
|
|
||||||
|
|
||||||
Balance.prototype.toJSON = function toJSON(minimal) {
|
Balance.prototype.toJSON = function toJSON(minimal) {
|
||||||
return {
|
return {
|
||||||
wid: !minimal ? this.wid : undefined,
|
wid: !minimal ? this.wid : undefined,
|
||||||
@ -2395,7 +2341,8 @@ function TXDBState(wid, id) {
|
|||||||
this.id = id;
|
this.id = id;
|
||||||
this.tx = 0;
|
this.tx = 0;
|
||||||
this.coin = 0;
|
this.coin = 0;
|
||||||
this.balance = new Balance(wid, id, -1);
|
this.unconfirmed = 0;
|
||||||
|
this.confirmed = 0;
|
||||||
this.committed = false;
|
this.committed = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2403,7 +2350,8 @@ TXDBState.prototype.clone = function clone() {
|
|||||||
var state = new TXDBState(this.wid, this.id);
|
var state = new TXDBState(this.wid, this.id);
|
||||||
state.tx = this.tx;
|
state.tx = this.tx;
|
||||||
state.coin = this.coin;
|
state.coin = this.coin;
|
||||||
state.balance = this.balance.clone();
|
state.unconfirmed = this.unconfirmed;
|
||||||
|
state.confirmed = this.confirmed;
|
||||||
return state;
|
return state;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -2412,12 +2360,20 @@ TXDBState.prototype.commit = function commit() {
|
|||||||
return this.toRaw();
|
return this.toRaw();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
TXDBState.prototype.toBalance = function toBalance() {
|
||||||
|
var balance = new Balance(this.wid, this.id, -1);
|
||||||
|
balance.unconfirmed = this.unconfirmed;
|
||||||
|
balance.confirmed = this.confirmed;
|
||||||
|
return balance;
|
||||||
|
};
|
||||||
|
|
||||||
TXDBState.prototype.toRaw = function toRaw(writer) {
|
TXDBState.prototype.toRaw = function toRaw(writer) {
|
||||||
var p = new BufferWriter(writer);
|
var p = new BufferWriter(writer);
|
||||||
|
|
||||||
p.writeU64(this.tx);
|
p.writeU64(this.tx);
|
||||||
p.writeU64(this.coin);
|
p.writeU64(this.coin);
|
||||||
this.balance.toRaw(p);
|
p.writeU64(this.unconfirmed);
|
||||||
|
p.writeU64(this.confirmed);
|
||||||
|
|
||||||
if (!writer)
|
if (!writer)
|
||||||
p = p.render();
|
p = p.render();
|
||||||
@ -2429,7 +2385,8 @@ TXDBState.prototype.fromRaw = function fromRaw(data) {
|
|||||||
var p = new BufferReader(data);
|
var p = new BufferReader(data);
|
||||||
this.tx = p.readU53();
|
this.tx = p.readU53();
|
||||||
this.coin = p.readU53();
|
this.coin = p.readU53();
|
||||||
this.balance.fromRaw(p);
|
this.unconfirmed = p.readU53();
|
||||||
|
this.confirmed = p.readU53();
|
||||||
return this;
|
return this;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -2437,32 +2394,14 @@ TXDBState.fromRaw = function fromRaw(wid, id, data) {
|
|||||||
return new TXDBState(wid, id).fromRaw(data);
|
return new TXDBState(wid, id).fromRaw(data);
|
||||||
};
|
};
|
||||||
|
|
||||||
TXDBState.prototype.add = function add(coin) {
|
|
||||||
this.coin++;
|
|
||||||
return this.balance.add(coin);
|
|
||||||
};
|
|
||||||
|
|
||||||
TXDBState.prototype.sub = function sub(coin) {
|
|
||||||
this.coin--;
|
|
||||||
return this.balance.sub(coin);
|
|
||||||
};
|
|
||||||
|
|
||||||
TXDBState.prototype.confirm = function confirm(value) {
|
|
||||||
return this.balance.confirm(value);
|
|
||||||
};
|
|
||||||
|
|
||||||
TXDBState.prototype.unconfirm = function unconfirm(value) {
|
|
||||||
return this.balance.unconfirm(value);
|
|
||||||
};
|
|
||||||
|
|
||||||
TXDBState.prototype.toJSON = function toJSON(minimal) {
|
TXDBState.prototype.toJSON = function toJSON(minimal) {
|
||||||
return {
|
return {
|
||||||
wid: !minimal ? this.wid : undefined,
|
wid: !minimal ? this.wid : undefined,
|
||||||
id: !minimal ? this.id : undefined,
|
id: !minimal ? this.id : undefined,
|
||||||
tx: this.tx,
|
tx: this.tx,
|
||||||
coin: this.coin,
|
coin: this.coin,
|
||||||
unconfirmed: utils.btc(this.balance.unconfirmed),
|
unconfirmed: utils.btc(this.unconfirmed),
|
||||||
confirmed: utils.btc(this.balance.confirmed)
|
confirmed: utils.btc(this.confirmed)
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user