From 8538e03c23100d30d61c39fe66f546e76f82e6a5 Mon Sep 17 00:00:00 2001 From: Arthur Britto Date: Mon, 5 Nov 2012 12:25:19 -0800 Subject: [PATCH] Fixes and clean up for API change. --- js/remote.js | 173 ++++++++++++++++++++++++------------------- src/Application.cpp | 6 +- src/NetworkOPs.cpp | 2 +- src/RPCHandler.cpp | 59 +++++++++------ src/RPCHandler.h | 2 +- src/WSConnection.cpp | 16 ++-- 6 files changed, 144 insertions(+), 114 deletions(-) diff --git a/js/remote.js b/js/remote.js index 89a2cdb9d..77978585d 100644 --- a/js/remote.js +++ b/js/remote.js @@ -110,8 +110,14 @@ Request.prototype.secret = function (s) { return this; }; -Request.prototype.transaction = function (t) { - this.message.transaction = t; +Request.prototype.tx_hash = function (h) { + this.message.tx_hash = h; + + return this; +}; + +Request.prototype.tx_json = function (j) { + this.message.tx_json = j; return this; }; @@ -544,14 +550,14 @@ Remote.prototype.request_transaction_entry = function (hash) { assert(this.trusted); // If not trusted, need to check proof, maybe talk packet protocol. return (new Request(this, 'transaction_entry')) - .transaction(hash); + .tx_hash(hash); }; // Submit a transaction. Remote.prototype.submit = function (transaction) { var self = this; - if (this.trace) console.log("remote: submit: %s", JSON.stringify(transaction.transaction)); + if (this.trace) console.log("remote: submit: %s", JSON.stringify(transaction.tx_json)); if (transaction.secret && !this.trusted) { @@ -561,14 +567,14 @@ Remote.prototype.submit = function (transaction) { }); } else { - if (!transaction.transaction.Sequence) { - transaction.transaction.Sequence = this.account_seq(transaction.transaction.Account, 'ADVANCE'); - // console.log("Sequence: %s", transaction.transaction.Sequence); + if (!transaction.tx_json.Sequence) { + transaction.tx_json.Sequence = this.account_seq(transaction.tx_json.Account, 'ADVANCE'); + // console.log("Sequence: %s", transaction.tx_json.Sequence); } - if (!transaction.transaction.Sequence) { + if (!transaction.tx_json.Sequence) { // Look in the last closed ledger. - this.account_seq_cache(transaction.transaction.Account, false) + this.account_seq_cache(transaction.tx_json.Account, false) .on('success_account_seq_cache', function () { // Try again. self.submit(transaction); @@ -577,7 +583,7 @@ Remote.prototype.submit = function (transaction) { // XXX Maybe be smarter about this. Don't want to trust an untrusted server for this seq number. // Look in the current ledger. - self.account_seq_cache(transaction.transaction.Account, 'CURRENT') + self.account_seq_cache(transaction.tx_json.Account, 'CURRENT') .on('success_account_seq_cache', function () { // Try again. self.submit(transaction); @@ -593,9 +599,12 @@ Remote.prototype.submit = function (transaction) { else { var submit_request = new Request(this, 'submit'); - submit_request.transaction(transaction.transaction); + submit_request.tx_json(transaction.tx_json); submit_request.secret(transaction.secret); + if (transaction.build_path) + submit_request.build_path = true; + // Forward successes and errors. submit_request.on('success', function (message) { transaction.emit('success', message); }); submit_request.on('error', function (message) { transaction.emit('error', message); }); @@ -840,7 +849,8 @@ var Transaction = function (remote) { this.remote = remote; this.secret = undefined; - this.transaction = { // Transaction data. + this.build_path = true; + this.tx_json = { // Transaction data. 'Flags' : 0, // XXX Would be nice if server did not require this. }; this.hash = undefined; @@ -849,12 +859,12 @@ var Transaction = function (remote) { this.on('success', function (message) { if (message.engine_result) { - self.hash = message.transaction.hash; + self.hash = message.tx_json.hash; self.set_state('client_proposed'); self.emit('proposed', { - 'transaction' : message.transaction, + 'tx_json' : message.tx_json, 'result' : message.engine_result, 'result_code' : message.engine_result_code, 'result_message' : message.engine_result_message, @@ -920,10 +930,10 @@ Transaction.prototype.set_state = function (state) { // XXX Have a network canSubmit(), post events for following. // XXX Also give broader status for tracking through network disconnects. Transaction.prototype.submit = function () { - var self = this; - var transaction = this.transaction; + var self = this; + var tx_json = this.tx_json; - if ('string' !== typeof transaction.Account) + if ('string' !== typeof tx_json.Account) { this.emit('error', { 'error' : 'invalidAccount', @@ -934,14 +944,14 @@ Transaction.prototype.submit = function () { // YYY Might check paths for invalid accounts. - if (undefined === transaction.Fee) { - if ('Payment' === transaction.TransactionType - && transaction.Flags & Remote.flags.Payment.CreateAccount) { + if (undefined === tx_json.Fee) { + if ('Payment' === tx_json.TransactionType + && tx_json.Flags & Remote.flags.Payment.CreateAccount) { - transaction.Fee = Remote.fees.account_create.to_json(); + tx_json.Fee = Remote.fees.account_create.to_json(); } else { - transaction.Fee = Remote.fees['default'].to_json(); + tx_json.Fee = Remote.fees['default'].to_json(); } } @@ -1000,6 +1010,12 @@ Transaction.prototype.submit = function () { // Set options for Transactions // +Transaction.prototype.build_path = function (build) { + this.build_path = build; + + return this; +} + Transaction._path_rewrite = function (path) { var path_new = []; @@ -1023,8 +1039,8 @@ Transaction._path_rewrite = function (path) { } Transaction.prototype.path_add = function (path) { - this.transaction.Paths = this.transaction.Paths || [] - this.transaction.Paths.push(Transaction._path_rewrite(path)); + this.tx_json.Paths = this.tx_json.Paths || [] + this.tx_json.Paths.push(Transaction._path_rewrite(path)); return this; } @@ -1046,16 +1062,16 @@ Transaction.prototype.secret = function (secret) { Transaction.prototype.send_max = function (send_max) { if (send_max) - this.transaction.SendMax = Amount.json_rewrite(send_max); + this.tx_json.SendMax = Amount.json_rewrite(send_max); return this; } // --> rate: In billionths. Transaction.prototype.transfer_rate = function (rate) { - this.transaction.TransferRate = Number(rate); + this.tx_json.TransferRate = Number(rate); - if (this.transaction.TransferRate < 1e9) + if (this.tx_json.TransferRate < 1e9) throw 'invalidTransferRate'; return this; @@ -1065,10 +1081,10 @@ Transaction.prototype.transfer_rate = function (rate) { // --> flags: undefined, _flag_, or [ _flags_ ] Transaction.prototype.set_flags = function (flags) { if (flags) { - var transaction_flags = Remote.flags[this.transaction.TransactionType]; + var transaction_flags = Remote.flags[this.tx_json.TransactionType]; - if (undefined == this.transaction.Flags) // We plan to not define this field on new Transaction. - this.transaction.Flags = 0; + if (undefined == this.tx_json.Flags) // We plan to not define this field on new Transaction. + this.tx_json.Flags = 0; var flag_set = 'object' === typeof flags ? flags : [ flags ]; @@ -1077,15 +1093,15 @@ Transaction.prototype.set_flags = function (flags) { if (flag in transaction_flags) { - this.transaction.Flags += transaction_flags[flag]; + this.tx_json.Flags += transaction_flags[flag]; } else { // XXX Immediately report an error or mark it. } } - if (this.transaction.Flags & Remote.flags.Payment.CreateAccount) - this.transaction.Fee = Remote.fees.account_create.to_json(); + if (this.tx_json.Flags & Remote.flags.Payment.CreateAccount) + this.tx_json.Fee = Remote.fees.account_create.to_json(); } return this; @@ -1106,43 +1122,43 @@ Transaction.prototype._account_secret = function (account) { // .transfer_rate() // .wallet_locator() NYI Transaction.prototype.account_set = function (src) { - this.secret = this._account_secret(src); - this.transaction.TransactionType = 'AccountSet'; - this.transaction.Account = UInt160.json_rewrite(src); + this.secret = this._account_secret(src); + this.tx_json.TransactionType = 'AccountSet'; + this.tx_json.Account = UInt160.json_rewrite(src); return this; }; Transaction.prototype.claim = function (src, generator, public_key, signature) { - this.secret = this._account_secret(src); - this.transaction.TransactionType = 'Claim'; - this.transaction.Generator = generator; - this.transaction.PublicKey = public_key; - this.transaction.Signature = signature; + this.secret = this._account_secret(src); + this.tx_json.TransactionType = 'Claim'; + this.tx_json.Generator = generator; + this.tx_json.PublicKey = public_key; + this.tx_json.Signature = signature; return this; }; Transaction.prototype.offer_cancel = function (src, sequence) { - this.secret = this._account_secret(src); - this.transaction.TransactionType = 'OfferCancel'; - this.transaction.Account = UInt160.json_rewrite(src); - this.transaction.OfferSequence = Number(sequence); + this.secret = this._account_secret(src); + this.tx_json.TransactionType = 'OfferCancel'; + this.tx_json.Account = UInt160.json_rewrite(src); + this.tx_json.OfferSequence = Number(sequence); return this; }; // --> expiration : Date or Number Transaction.prototype.offer_create = function (src, taker_pays, taker_gets, expiration) { - this.secret = this._account_secret(src); - this.transaction.TransactionType = 'OfferCreate'; - this.transaction.Account = UInt160.json_rewrite(src); - this.transaction.Fee = Remote.fees.offer.to_json(); - this.transaction.TakerPays = Amount.json_rewrite(taker_pays); - this.transaction.TakerGets = Amount.json_rewrite(taker_gets); + this.secret = this._account_secret(src); + this.tx_json.TransactionType = 'OfferCreate'; + this.tx_json.Account = UInt160.json_rewrite(src); + this.tx_json.Fee = Remote.fees.offer.to_json(); + this.tx_json.TakerPays = Amount.json_rewrite(taker_pays); + this.tx_json.TakerGets = Amount.json_rewrite(taker_gets); if (expiration) - this.transaction.Expiration = Date === expiration.constructor + this.tx_json.Expiration = Date === expiration.constructor ? expiration.getTime() : Number(expiration); @@ -1150,20 +1166,20 @@ Transaction.prototype.offer_create = function (src, taker_pays, taker_gets, expi }; Transaction.prototype.password_fund = function (src, dst) { - this.secret = this._account_secret(src); - this.transaction.TransactionType = 'PasswordFund'; - this.transaction.Destination = UInt160.json_rewrite(dst); + this.secret = this._account_secret(src); + this.tx_json.TransactionType = 'PasswordFund'; + this.tx_json.Destination = UInt160.json_rewrite(dst); return this; } Transaction.prototype.password_set = function (src, authorized_key, generator, public_key, signature) { - this.secret = this._account_secret(src); - this.transaction.TransactionType = 'PasswordSet'; - this.transaction.AuthorizedKey = authorized_key; - this.transaction.Generator = generator; - this.transaction.PublicKey = public_key; - this.transaction.Signature = signature; + this.secret = this._account_secret(src); + this.tx_json.TransactionType = 'PasswordSet'; + this.tx_json.AuthorizedKey = authorized_key; + this.tx_json.Generator = generator; + this.tx_json.PublicKey = public_key; + this.tx_json.Signature = signature; return this; } @@ -1178,34 +1194,35 @@ Transaction.prototype.password_set = function (src, authorized_key, generator, p // // Options: // .paths() +// .build_path() // .path_add() // .secret() // .send_max() // .set_flags() Transaction.prototype.payment = function (src, dst, deliver_amount) { - this.secret = this._account_secret(src); - this.transaction.TransactionType = 'Payment'; - this.transaction.Account = UInt160.json_rewrite(src); - this.transaction.Amount = Amount.json_rewrite(deliver_amount); - this.transaction.Destination = UInt160.json_rewrite(dst); + this.secret = this._account_secret(src); + this.tx_json.TransactionType = 'Payment'; + this.tx_json.Account = UInt160.json_rewrite(src); + this.tx_json.Amount = Amount.json_rewrite(deliver_amount); + this.tx_json.Destination = UInt160.json_rewrite(dst); return this; } Transaction.prototype.ripple_line_set = function (src, limit, quality_in, quality_out) { - this.secret = this._account_secret(src); - this.transaction.TransactionType = 'CreditSet'; - this.transaction.Account = UInt160.json_rewrite(src); + this.secret = this._account_secret(src); + this.tx_json.TransactionType = 'CreditSet'; + this.tx_json.Account = UInt160.json_rewrite(src); // Allow limit of 0 through. if (undefined !== limit) - this.transaction.LimitAmount = Amount.json_rewrite(limit); + this.tx_json.LimitAmount = Amount.json_rewrite(limit); if (quality_in) - this.transaction.QualityIn = quality_in; + this.tx_json.QualityIn = quality_in; if (quality_out) - this.transaction.QualityOut = quality_out; + this.tx_json.QualityOut = quality_out; // XXX Throw an error if nothing is set. @@ -1213,12 +1230,12 @@ Transaction.prototype.ripple_line_set = function (src, limit, quality_in, qualit }; Transaction.prototype.wallet_add = function (src, amount, authorized_key, public_key, signature) { - this.secret = this._account_secret(src); - this.transaction.TransactionType = 'WalletAdd'; - this.transaction.Amount = Amount.json_rewrite(amount); - this.transaction.AuthorizedKey = authorized_key; - this.transaction.PublicKey = public_key; - this.transaction.Signature = signature; + this.secret = this._account_secret(src); + this.tx_json.TransactionType = 'WalletAdd'; + this.tx_json.Amount = Amount.json_rewrite(amount); + this.tx_json.AuthorizedKey = authorized_key; + this.tx_json.PublicKey = public_key; + this.tx_json.Signature = signature; return this; }; diff --git a/src/Application.cpp b/src/Application.cpp index aa15bc653..8133fa271 100644 --- a/src/Application.cpp +++ b/src/Application.cpp @@ -40,9 +40,11 @@ DatabaseCon::~DatabaseCon() Application::Application() : mIOWork(mIOService), mAuxWork(mAuxService), mUNL(mIOService), mNetOps(mIOService, &mMasterLedger), mTempNodeCache("NodeCache", 16384, 90), mHashedObjectStore(16384, 300), - mSNTPClient(mAuxService), mRpcDB(NULL), mTxnDB(NULL), mLedgerDB(NULL), mWalletDB(NULL), + mSNTPClient(mAuxService), + mRPCHandler(&mNetOps), + mRpcDB(NULL), mTxnDB(NULL), mLedgerDB(NULL), mWalletDB(NULL), mHashNodeDB(NULL), mNetNodeDB(NULL), - mConnectionPool(mIOService), mPeerDoor(NULL), mRPCDoor(NULL), mSweepTimer(mAuxService), mRPCHandler(&mNetOps) + mConnectionPool(mIOService), mPeerDoor(NULL), mRPCDoor(NULL), mSweepTimer(mAuxService) { RAND_bytes(mNonce256.begin(), mNonce256.size()); RAND_bytes(reinterpret_cast(&mNonceST), sizeof(mNonceST)); diff --git a/src/NetworkOPs.cpp b/src/NetworkOPs.cpp index 21ce90666..3b2493cf6 100644 --- a/src/NetworkOPs.cpp +++ b/src/NetworkOPs.cpp @@ -967,7 +967,7 @@ void NetworkOPs::pubLedger(Ledger::ref lpAccepted) } } } - + { // we don't lock since pubAcceptedTransaction is locking if (!mSubTransactions.empty() || !mSubRTTransactions.empty() || !mSubAccount.empty() || !mSubRTAccount.empty() || !mSubmitMap.empty() ) diff --git a/src/RPCHandler.cpp b/src/RPCHandler.cpp index 3aafeb7e8..f48d71ac3 100644 --- a/src/RPCHandler.cpp +++ b/src/RPCHandler.cpp @@ -694,20 +694,26 @@ Json::Value RPCHandler::doSubmit(const Json::Value& params) Json::Reader reader; if(reader.parse(params[1u].asString(),txJSON)) { - return handleJSONSubmit(params[0u].asString(), txJSON); + Json::Value jvRequest; + + jvRequest["secret"] = params[0u].asString(); + jvRequest["tx_json"] = txJSON; + + return handleJSONSubmit(jvRequest); } return rpcError(rpcSRC_ACT_MALFORMED); } -Json::Value RPCHandler::handleJSONSubmit(const std::string& key, Json::Value& txJSON) +Json::Value RPCHandler::handleJSONSubmit(const Json::Value& jvRequest) { - Json::Value jvResult; + Json::Value jvResult; RippleAddress naSeed; RippleAddress srcAddress; + Json::Value txJSON = jvResult["tx_json"]; - if (!naSeed.setSeedGeneric(key)) + if (!naSeed.setSeedGeneric(jvResult["secret"].asString())) { return rpcError(rpcBAD_SEED); } @@ -727,6 +733,11 @@ Json::Value RPCHandler::handleJSONSubmit(const std::string& key, Json::Value& tx txJSON["TransactionType"]=0; RippleAddress dstAccountID; + + if (!txJSON.isMember("Destination")) + { + return rpcError(rpcDST_ACT_MISSING); + } if (!dstAccountID.setAccountID(txJSON["Destination"].asString())) { return rpcError(rpcDST_ACT_MALFORMED); @@ -738,7 +749,8 @@ Json::Value RPCHandler::handleJSONSubmit(const std::string& key, Json::Value& tx txJSON["Fee"]=(int)theConfig.FEE_DEFAULT; else txJSON["Fee"]=(int)theConfig.FEE_ACCOUNT_CREATE; } - if(!txJSON.isMember("Paths")) + + if(!txJSON.isMember("Paths") && (!jvRequest.isMember("build_path") || jvRequest["build_path"].asBool())) { if(txJSON["Amount"].isObject() || txJSON.isMember("SendMax") ) { // we need a ripple path @@ -746,8 +758,12 @@ Json::Value RPCHandler::handleJSONSubmit(const std::string& key, Json::Value& tx uint160 srcCurrencyID; if(txJSON.isMember("SendMax") && txJSON["SendMax"].isMember("currency")) { - STAmount::currencyFromString(srcCurrencyID, "XRP"); - }else STAmount::currencyFromString(srcCurrencyID, txJSON["SendMax"]["currency"].asString()); + STAmount::currencyFromString(srcCurrencyID, txJSON["SendMax"]["currency"].asString()); + } + else + { + srcCurrencyID = CURRENCY_XRP; + } STAmount dstAmount; if(txJSON["Amount"].isObject()) @@ -804,7 +820,7 @@ Json::Value RPCHandler::handleJSONSubmit(const std::string& key, Json::Value& tx RippleAddress naAuthorizedPublic; - RippleAddress naSecret = RippleAddress::createSeedGeneric(key); + RippleAddress naSecret = RippleAddress::createSeedGeneric(jvResult["secret"].asString()); RippleAddress naMasterGenerator = RippleAddress::createGeneratorPublic(naSecret); // Find the index of Account from the master generator, so we can generate the public and private keys. @@ -858,7 +874,7 @@ Json::Value RPCHandler::handleJSONSubmit(const std::string& key, Json::Value& tx { jvResult["error"] = "malformedTransaction"; jvResult["error_exception"] = e.what(); - return(jvResult); + return jvResult; } sopTrans->setFieldVL(sfSigningPubKey, naAccountPublic.getAccountPublic()); @@ -888,7 +904,7 @@ Json::Value RPCHandler::handleJSONSubmit(const std::string& key, Json::Value& tx { jvResult["error"] = "internalTransaction"; jvResult["error_exception"] = e.what(); - return(jvResult); + return jvResult; } try @@ -898,19 +914,19 @@ Json::Value RPCHandler::handleJSONSubmit(const std::string& key, Json::Value& tx if (!tpTrans) { jvResult["error"] = "invalidTransaction"; jvResult["error_exception"] = "Unable to sterilize transaction."; - return(jvResult); + return jvResult; } } catch (std::exception& e) { jvResult["error"] = "internalSubmit"; jvResult["error_exception"] = e.what(); - return(jvResult); + return jvResult; } try { - jvResult["transaction"] = tpTrans->getJson(0); + jvResult["tx_json"] = tpTrans->getJson(0); if (temUNCERTAIN != tpTrans->getResult()) { @@ -923,15 +939,14 @@ Json::Value RPCHandler::handleJSONSubmit(const std::string& key, Json::Value& tx jvResult["engine_result_code"] = tpTrans->getResult(); jvResult["engine_result_message"] = sHuman; } - return(jvResult); + return jvResult; } catch (std::exception& e) { jvResult["error"] = "internalJson"; jvResult["error_exception"] = e.what(); - return(jvResult); + return jvResult; } - } Json::Value RPCHandler::doServerInfo(const Json::Value& params) @@ -1603,7 +1618,6 @@ Json::Value RPCHandler::doLedgerAccept(const Json::Value& ) return(jvResult); } - Json::Value RPCHandler::doTransactionEntry(const Json::Value& params) { Json::Value jvResult; @@ -1640,26 +1654,24 @@ Json::Value RPCHandler::doTransactionEntry(const Json::Value& params) Transaction::pointer tpTrans; TransactionMetaSet::pointer tmTrans; - if (!lpLedger-> getTransaction(uTransID, tpTrans, tmTrans)) + if (!lpLedger->getTransaction(uTransID, tpTrans, tmTrans)) { jvResult["error"] = "transactionNotFound"; } else { - jvResult["transaction"] = tpTrans->getJson(0); - jvResult["metadata"] = tmTrans->getJson(0); + jvResult["tx_json"] = tpTrans->getJson(0); + jvResult["metadata"] = tmTrans->getJson(0); // 'accounts' // 'engine_...' // 'ledger_...' } } } - + return jvResult; } - - Json::Value RPCHandler::doLedgerEntry(const Json::Value& params) { Json::Value jvResult; @@ -1667,7 +1679,6 @@ Json::Value RPCHandler::doLedgerEntry(const Json::Value& params) Json::Reader reader; if(!reader.parse(params[0u].asString(),jvRequest)) return rpcError(rpcINVALID_PARAMS); - uint256 uLedger = jvRequest.isMember("ledger_closed") ? uint256(jvRequest["ledger_closed"].asString()) : 0; uint32 uLedgerIndex = jvRequest.isMember("ledger_index") && jvRequest["ledger_index"].isNumeric() ? jvRequest["ledger_index"].asUInt() : 0; diff --git a/src/RPCHandler.h b/src/RPCHandler.h index e23eb103f..344bdc262 100644 --- a/src/RPCHandler.h +++ b/src/RPCHandler.h @@ -154,7 +154,7 @@ public: Json::Value doCommand(const std::string& command, Json::Value& params,int role); Json::Value rpcError(int iError); - Json::Value handleJSONSubmit(const std::string& key, Json::Value& txJSON); + Json::Value handleJSONSubmit(const Json::Value& jvRequest); }; diff --git a/src/WSConnection.cpp b/src/WSConnection.cpp index 1a03819ad..121bdead1 100644 --- a/src/WSConnection.cpp +++ b/src/WSConnection.cpp @@ -149,7 +149,7 @@ void WSConnection::doSubscribe(Json::Value& jvResult, Json::Value& jvRequest) mNetwork.subTransactions(this); }else if(streamName=="rt_transactions") { - mNetwork.subRTTransactions(this); + mNetwork.subRTTransactions(this); }else { jvResult["error"] = str(boost::format("Unknown stream: %s") % streamName); @@ -223,7 +223,7 @@ void WSConnection::doUnsubscribe(Json::Value& jvResult, Json::Value& jvRequest) mNetwork.unsubTransactions(this); }else if(streamName=="rt_transactions") { - mNetwork.unsubRTTransactions(this); + mNetwork.unsubRTTransactions(this); }else { jvResult["error"] = str(boost::format("Unknown stream: %s") % streamName); @@ -293,15 +293,15 @@ void WSConnection::doSubmit(Json::Value& jvResult, Json::Value& jvRequest) { if (!jvRequest.isMember("tx_json")) { - jvResult["error"] = "fieldNotFoundTransaction"; - }else if (!jvRequest.isMember("key")) + jvResult["error"] = "fieldNotFoundTxJson"; + }else if (!jvRequest.isMember("secret")) { - jvResult["error"] = "fieldNotFoundKey"; - }else + jvResult["error"] = "fieldNotFoundSecret"; + }else { - jvResult=theApp->getRPCHandler().handleJSONSubmit(jvRequest["key"].asString(),jvRequest["tx_json"]); + jvResult=theApp->getRPCHandler().handleJSONSubmit(jvRequest); // TODO: track the transaction mNetwork.subSubmit(this, jvResult["tx hash"] ); } } - +// vim:ts=4