mirror of
https://github.com/Xahau/xahau.js.git
synced 2025-11-18 19:25:48 +00:00
Fixes for per-transaction defined secret and offline errors
This commit is contained in:
@@ -281,8 +281,25 @@ Transaction.prototype._getServer = function() {
|
||||
|
||||
Transaction.prototype.complete = function() {
|
||||
// Try to auto-fill the secret
|
||||
if (!this._secret && !(this._secret = this._account_secret(this.tx_json.Account))) {
|
||||
return this.emit('error', new RippleError('tejSecretUnknown', 'Missing secret'));
|
||||
if (!this._secret && !(this._secret = this._accountSecret(this.tx_json.Account))) {
|
||||
this.emit('error', new RippleError('tejSecretUnknown', 'Missing secret'));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (typeof this.tx_json.SigningPubKey === 'undefined') {
|
||||
try {
|
||||
var seed = Seed.from_json(this._secret);
|
||||
var key = seed.get_key(this.tx_json.Account);
|
||||
this.tx_json.SigningPubKey = key.to_hex_pub();
|
||||
} catch(e) {
|
||||
this.emit('error', new RippleError('tejSecretInvalid', 'Invalid secret'));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!this.remote.trusted && !this.remote.local_signing) {
|
||||
this.emit('error', new RippleError('tejServerUntrusted', 'Attempt to give secret to untrusted server'));
|
||||
return false;
|
||||
}
|
||||
|
||||
// If the Fee hasn't been set, one needs to be computed by
|
||||
@@ -294,14 +311,9 @@ Transaction.prototype.complete = function() {
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof this.tx_json.SigningPubKey === 'undefined') {
|
||||
try {
|
||||
var seed = Seed.from_json(this._secret);
|
||||
var key = seed.get_key(this.tx_json.Account);
|
||||
this.tx_json.SigningPubKey = key.to_hex_pub();
|
||||
} catch(e) {
|
||||
return this.emit('error', new RippleError('tejSecretInvalid', 'Invalid secret'));
|
||||
}
|
||||
if (Number(this.tx_json.Fee) > this._maxFee) {
|
||||
tx.emit('error', new RippleError('tejMaxFeeExceeded', 'Max fee exceeded'));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Set canonical flag - this enables canonicalized signature checking
|
||||
|
||||
@@ -184,24 +184,20 @@ TransactionManager.prototype._fillSequence = function(tx, callback) {
|
||||
fill.account_set(self._accountID);
|
||||
fill.tx_json.Sequence = sequence;
|
||||
fill.once('submitted', callback);
|
||||
|
||||
// Secrets may be set on a per-transaction basis
|
||||
if (tx._secret) {
|
||||
fill.secret(tx._secret);
|
||||
}
|
||||
|
||||
fill.submit();
|
||||
};
|
||||
|
||||
function sequenceLoaded(err, sequence) {
|
||||
if (typeof sequence !== 'number') {
|
||||
callback(new Error('Failed to fetch account transaction sequence'));
|
||||
return;
|
||||
}
|
||||
|
||||
var sequenceDif = tx.tx_json.Sequence - sequence;
|
||||
var submitted = 0;
|
||||
|
||||
for (var i=sequence; i<tx.tx_json.Sequence; i++) {
|
||||
submitFill(i, function() {
|
||||
if (++submitted === sequenceDif) {
|
||||
callback();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
submitFill(sequence, callback);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -378,7 +374,11 @@ TransactionManager.prototype._request = function(tx) {
|
||||
|
||||
function transactionRetry(message) {
|
||||
if (tx.finalized) return;
|
||||
|
||||
console.log('TER, submitting fill');
|
||||
|
||||
self._fillSequence(tx, function() {
|
||||
console.log('FILL COMPLETE, resubmitting');
|
||||
self._resubmit(1, tx);
|
||||
});
|
||||
};
|
||||
@@ -580,27 +580,21 @@ TransactionManager.prototype.submit = function(tx) {
|
||||
tx.tx_json.Sequence = this._nextSequence++;
|
||||
}
|
||||
|
||||
// Attach secret, associate transaction with a server, attach fee.
|
||||
// If the transaction can't complete, decrement sequence so that
|
||||
// subsequent transactions
|
||||
if (!tx.complete()) {
|
||||
return;
|
||||
}
|
||||
|
||||
tx.attempts = 0;
|
||||
|
||||
// Attach secret, associate transaction with a server, attach fee
|
||||
tx.complete();
|
||||
|
||||
var fee = Number(tx.tx_json.Fee);
|
||||
|
||||
if (!tx._secret && !tx.tx_json.TxnSignature) {
|
||||
tx.emit('error', new RippleError('tejSecretUnknown', 'Missing secret'));
|
||||
} else if (!remote.trusted && !remote.local_signing) {
|
||||
tx.emit('error', new RippleError('tejServerUntrusted', 'Attempt to give secret to untrusted server'));
|
||||
} else if (fee && fee > this._maxFee) {
|
||||
tx.emit('error', new RippleError('tejMaxFeeExceeded', 'Max fee exceeded'));
|
||||
} else {
|
||||
// ND: this is the ONLY place we put the tx into the queue. The
|
||||
// TransactionQueue queue is merely a list, so any mutations to tx._hash
|
||||
// will cause subsequent look ups (eg. inside 'transaction-outbound'
|
||||
// validated transaction clearing) to fail.
|
||||
this._pending.push(tx);
|
||||
this._request(tx);
|
||||
}
|
||||
// ND: this is the ONLY place we put the tx into the queue. The
|
||||
// TransactionQueue queue is merely a list, so any mutations to tx._hash
|
||||
// will cause subsequent look ups (eg. inside 'transaction-outbound'
|
||||
// validated transaction clearing) to fail.
|
||||
this._pending.push(tx);
|
||||
this._request(tx);
|
||||
};
|
||||
|
||||
exports.TransactionManager = TransactionManager;
|
||||
|
||||
@@ -4,46 +4,17 @@
|
||||
*/
|
||||
|
||||
var Transaction = require('./transaction').Transaction;
|
||||
var LRU = require('lru-cache');
|
||||
|
||||
function TransactionQueue() {
|
||||
var self = this;
|
||||
|
||||
this._queue = [ ];
|
||||
this._idCache = { };
|
||||
this._sequenceCache = { };
|
||||
this._idCache = LRU({ max: 100 });
|
||||
this._sequenceCache = LRU({ max: 100 });
|
||||
this._save = void(0);
|
||||
};
|
||||
|
||||
TransactionQueue.prototype.clearCache = function() {
|
||||
this._idCache = { };
|
||||
this._sequenceCache = { };
|
||||
};
|
||||
|
||||
TransactionQueue.prototype.getMinLedger = function() {
|
||||
var minLedger = Infinity;
|
||||
|
||||
for (var i=0; i<this._queue.length; i++) {
|
||||
var submitIndex = this._queue[i].submitIndex;
|
||||
|
||||
if (typeof submitIndex !== 'number') {
|
||||
// If any pending transactions don't have a submit index,
|
||||
// return -1 for scanning all previous transactions
|
||||
minLedger = -1;
|
||||
break;
|
||||
}
|
||||
|
||||
if (submitIndex < minLedger) {
|
||||
minLedger = submitIndex;
|
||||
}
|
||||
};
|
||||
|
||||
if (!isFinite(minLedger)) minLedger = -1;
|
||||
|
||||
if (minLedger !== -1) minLedger -= 1;
|
||||
|
||||
return minLedger;
|
||||
};
|
||||
|
||||
TransactionQueue.prototype.save = function() {
|
||||
if (typeof this._save !== 'function') return;
|
||||
|
||||
@@ -60,7 +31,7 @@ TransactionQueue.prototype.save = function() {
|
||||
*/
|
||||
|
||||
TransactionQueue.prototype.addReceivedSequence = function(sequence) {
|
||||
this._sequenceCache[sequence] = true;
|
||||
this._sequenceCache.set(String(sequence), true);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -68,7 +39,7 @@ TransactionQueue.prototype.addReceivedSequence = function(sequence) {
|
||||
*/
|
||||
|
||||
TransactionQueue.prototype.addReceivedId = function(id, transaction) {
|
||||
this._idCache[id] = transaction;
|
||||
this._idCache.set(id, transaction);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -76,7 +47,7 @@ TransactionQueue.prototype.addReceivedId = function(id, transaction) {
|
||||
*/
|
||||
|
||||
TransactionQueue.prototype.getReceived = function(id) {
|
||||
return this._idCache[id];
|
||||
return this._idCache.get(id);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -85,7 +56,7 @@ TransactionQueue.prototype.getReceived = function(id) {
|
||||
*/
|
||||
|
||||
TransactionQueue.prototype.hasSequence = function(sequence) {
|
||||
return this._sequenceCache[sequence] || false;
|
||||
return this._sequenceCache.has(String(sequence));
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -121,10 +92,6 @@ TransactionQueue.prototype.remove = function(tx) {
|
||||
}
|
||||
}
|
||||
|
||||
if (!this._queue.length) {
|
||||
this.clearCache();
|
||||
}
|
||||
|
||||
this.save();
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user