From f9bb7094e95a0c9da0270e8ae506599939ff4660 Mon Sep 17 00:00:00 2001 From: Nicholas Dudfield Date: Thu, 9 Jan 2014 13:48:03 +0700 Subject: [PATCH] Disable transaction resubmission when remote signing. Throw error when attempt to build_path when using local_signing --- src/js/ripple/request.js | 12 +++++++++++ src/js/ripple/transactionmanager.js | 31 +++++++++++++++++++++++------ 2 files changed, 37 insertions(+), 6 deletions(-) diff --git a/src/js/ripple/request.js b/src/js/ripple/request.js index b618b2fe..6aacb966 100644 --- a/src/js/ripple/request.js +++ b/src/js/ripple/request.js @@ -129,8 +129,20 @@ Request.prototype.setServer = function(server) { }; Request.prototype.buildPath = function(build) { + + if (this.remote.local_signing) { + throw new Error( + '`build_path` is completely ignored when doing local signing as ' + + '`Paths` is a component of the signed blob. The `tx_blob` is signed,' + + 'sealed and delivered, and the txn unmodified after' ); + } + if (build) { this.message.build_path = true; + } else { + // ND: rippled currently intreprets the mere presence of `build_path` as the + // value being `truthy` + delete this.message.build_path } return this; }; diff --git a/src/js/ripple/transactionmanager.js b/src/js/ripple/transactionmanager.js index f2301c67..5cc25216 100644 --- a/src/js/ripple/transactionmanager.js +++ b/src/js/ripple/transactionmanager.js @@ -285,24 +285,43 @@ TransactionManager.prototype._request = function(tx) { if (tx.attempts > 10) { tx.emit('error', new RippleError('tejAttemptsExceeded')); return; + } else if (tx.attempts > 0 && !remote.local_signing + // && tx.submittedTxnIDs.length != tx.attempts + + // ^^^ Above commented out intentionally + + // ^^^^ We might be a bit cleverer about allowing this in SOME cases, but + // it's not really worth it, and would be prone to error. Use + // `local_signing` + + ) { + tx.emit('error', new RippleError('tejTxnResubmitWithoutLocalSigning', + 'It\s not possible to resubmit transactions automatically safely without ' + + 'synthesizing the transactionID locally. See `local_signing` config option')); } var submitRequest = remote.requestSubmit(); - submitRequest.build_path(tx._build_path); - if (remote.local_signing) { tx.sign(); + // TODO: We are serializing twice, when we could/should be feeding the + // tx_blob to `tx.hash()` which rebuilds it to sign it. submitRequest.tx_blob(tx.serialize().to_hex()); + // ND: ecdsa produces a random `TxnSignature` field value, a component of + // the hash. Attempting to identify a transaction via a hash synthesized + // locally while using remote signing is inherently flawed. + tx.addSubmittedTxnID(tx.hash()); } else { + // ND: `build_path` is completely ignored when doing local signing as + // `Paths` is a component of the signed blob, the `tx_blob` is signed, + // sealed and delivered, and the txn unmodified. + // TODO: perhaps an exception should be raised if build_path is attempted + // while local signing + submitRequest.build_path(tx._build_path); submitRequest.secret(tx._secret); submitRequest.tx_json(tx.tx_json); } - // ND: We could consider sharing the work with tx_blob when doing - // local_signing - tx.addSubmittedTxnID(tx.hash()); - remote._trace('transactionmanager: submit:', tx.tx_json); function transactionProposed(message) {