Submit Env transactions through RPC interface

This commit is contained in:
Vinnie Falco
2015-12-21 13:57:23 -05:00
committed by Edward Hennis
parent 8f74ee1d96
commit d5363d1a85
6 changed files with 84 additions and 35 deletions

View File

@@ -146,7 +146,7 @@ struct Regression_test : public beast::unit_test::suite
(sfSigningPubKey, std::move(pubKeyBlob.first));
jt.stx.reset (secp256r1Sig.release());
env (jt, ter (temBAD_SIGNATURE));
env (jt, ter (temINVALID));
};
Account const alice {"alice", KeyType::secp256k1};

View File

@@ -25,6 +25,7 @@
#include <boost/asio/io_service.hpp>
#include <functional>
#include <string>
#include <utility>
#include <vector>
namespace ripple {
@@ -53,6 +54,12 @@ void fromNetwork (
std::function<void (Json::Value const& jvInput)> callbackFuncP = std::function<void (Json::Value const& jvInput)> ());
}
/** Internal invocation of RPC client.
*/
std::pair<int, Json::Value>
rpcClient(std::vector<std::string> const& args,
Config const& config, Logs& logs);
} // ripple
#endif

View File

@@ -1079,18 +1079,18 @@ struct RPCCallImp
};
//------------------------------------------------------------------------------
namespace RPCCall {
int fromCommandLine (
Config const& config,
const std::vector<std::string>& vCmd,
Logs& logs)
std::pair<int, Json::Value>
rpcClient(std::vector<std::string> const& args,
Config const& config, Logs& logs)
{
if (vCmd.empty ())
return 1; // 1 = print usage.
static_assert(rpcBAD_SYNTAX == 1 && rpcSUCCESS == 0,
"Expect specific rpc enum values.");
if (args.empty ())
return { rpcBAD_SYNTAX, {} }; // rpcBAD_SYNTAX = print usage
int nRet = rpcSUCCESS;
Json::Value jvOutput;
int nRet = 0;
Json::Value jvRequest (Json::objectValue);
auto rpcJ = logs.journal ("RPCParser");
@@ -1099,15 +1099,15 @@ int fromCommandLine (
RPCParser rpParser (rpcJ);
Json::Value jvRpcParams (Json::arrayValue);
for (int i = 1; i != vCmd.size (); i++)
jvRpcParams.append (vCmd[i]);
for (int i = 1; i != args.size (); i++)
jvRpcParams.append (args[i]);
Json::Value jvRpc = Json::Value (Json::objectValue);
jvRpc["method"] = vCmd[0];
jvRpc["method"] = args[0];
jvRpc[jss::params] = jvRpcParams;
jvRequest = rpParser.parseCommand (vCmd[0], jvRpcParams, true);
jvRequest = rpParser.parseCommand (args[0], jvRpcParams, true);
JLOG (rpcJ.trace) << "RPC Request: " << jvRequest << std::endl;
@@ -1147,7 +1147,7 @@ int fromCommandLine (
{
boost::asio::io_service isService;
fromNetwork (
RPCCall::fromNetwork (
isService,
setup.client.ip,
setup.client.port,
@@ -1155,7 +1155,7 @@ int fromCommandLine (
setup.client.password,
"",
jvRequest.isMember ("method") // Allow parser to rewrite method.
? jvRequest["method"].asString () : vCmd[0],
? jvRequest["method"].asString () : args[0],
jvParams, // Parsed, execute.
setup.client.secure != 0, // Use SSL
config.QUIET,
@@ -1196,7 +1196,7 @@ int fromCommandLine (
nRet = jvOutput.isMember (jss::error_code)
? beast::lexicalCast <int> (jvOutput[jss::error_code].asString ())
: 1;
: rpcBAD_SYNTAX;
}
// YYY We could have a command line flag for single line output for scripts.
@@ -1209,9 +1209,24 @@ int fromCommandLine (
nRet = rpcINTERNAL;
}
std::cout << jvOutput.toStyledString ();
return { nRet, std::move(jvOutput) };
}
return nRet;
//------------------------------------------------------------------------------
namespace RPCCall {
int fromCommandLine (
Config const& config,
const std::vector<std::string>& vCmd,
Logs& logs)
{
auto const result = rpcClient(vCmd, config, logs);
if (result.first != rpcBAD_SYNTAX)
std::cout << result.second.toStyledString ();
return result.first;
}
//------------------------------------------------------------------------------

View File

@@ -36,6 +36,7 @@
#include <ripple/json/json_value.h>
#include <ripple/json/to_string.h>
#include <ripple/ledger/CachedSLEs.h>
#include <ripple/net/RPCCall.h>
#include <ripple/protocol/Indexes.h>
#include <ripple/protocol/Issue.h>
#include <ripple/protocol/STAmount.h>
@@ -44,10 +45,12 @@
#include <beast/is_call_possible.h>
#include <beast/unit_test/suite.h>
#include <functional>
#include <string>
#include <tuple>
#include <type_traits>
#include <utility>
#include <unordered_map>
#include <vector>
namespace ripple {
namespace test {
@@ -420,6 +423,11 @@ public:
std::shared_ptr<STObject const>
meta();
/** Execute a client command */
template <class Arg, class... Args>
std::pair<int, Json::Value>
rpc (Arg&& arg0, Args&&... args);
private:
void
fund (bool setDefaultRipple,
@@ -620,6 +628,18 @@ protected:
AccountID, Account> map_;
};
//------------------------------------------------------------------------------
template <class Arg, class... Args>
std::pair<int, Json::Value>
Env::rpc (Arg&& arg0, Args&&... args)
{
std::vector<std::string> v({ std::forward<Arg>(arg0),
std::forward<Args>(args)... });
return rpcClient(v,
app().config(), app().logs());
}
} // jtx
} // test
} // ripple

View File

@@ -36,6 +36,7 @@
#include <ripple/basics/Slice.h>
#include <ripple/core/ConfigSections.h>
#include <ripple/json/to_string.h>
#include <ripple/net/HTTPClient.h>
#include <ripple/protocol/ErrorCodes.h>
#include <ripple/protocol/HashPrefix.h>
#include <ripple/protocol/Indexes.h>
@@ -62,6 +63,8 @@ setupConfigForUnitTests (Config& config)
config.legacy("database_path", "");
config.RUN_STANDALONE = true;
config.QUIET = true;
config.SILENT = true;
config["server"].append("port_peer");
config["port_peer"].set("ip", "127.0.0.1");
config["port_peer"].set("port", "8080");
@@ -88,6 +91,8 @@ Env::AppBundle::AppBundle(std::unique_ptr<Config> config)
auto timeKeeper_ =
std::make_unique<ManualTimeKeeper>();
timeKeeper = timeKeeper_.get();
// Hack so we dont have to call Config::setup
HTTPClient::initializeSSLContext(*config);
owned = make_Application(std::move(config),
std::move(logs), std::move(timeKeeper_));
app = owned.get();
@@ -258,14 +263,16 @@ Env::submit (JTx const& jt)
if (jt.stx)
{
txid_ = jt.stx->getTransactionID();
app().openLedger().modify(
[&](OpenView& view, beast::Journal j)
{
std::tie(ter_, didApply) = app().getTxQ().apply(
app(), view, jt.stx, applyFlags(),
beast::Journal{});
return didApply;
});
Serializer s;
jt.stx->add(s);
auto const result = rpc("submit", strHex(s.slice()));
if (result.first == rpcSUCCESS &&
result.second["result"].isMember("engine_result_code"))
ter_ = static_cast<TER>(
result.second["result"]["engine_result_code"].asInt());
else
ter_ = temINVALID;
didApply = isTesSuccess(ter_) || isTecClaim(ter_);
}
else
{

View File

@@ -290,21 +290,21 @@ public:
auto const gw = Account("gateway");
auto const USD = gw["USD"];
env(pay(env.master, "alice", XRP(1000)), fee(none), ter(temMALFORMED));
env(pay(env.master, "alice", XRP(1000)), fee(1), ter(telINSUF_FEE_P));
env(pay(env.master, "alice", XRP(1000)), seq(none), ter(temMALFORMED));
env(pay(env.master, "alice", XRP(1000)), seq(2), ter(terPRE_SEQ));
env(pay(env.master, "alice", XRP(1000)), sig(none), ter(temMALFORMED));
env(pay(env.master, "alice", XRP(1000)), sig("bob"), ter(tefBAD_AUTH_MASTER));
env(pay(env.master, "dilbert", XRP(1000)), sig(env.master));
env.fund(XRP(10000), "alice", "bob", "carol", gw);
env.require(balance("alice", XRP(10000)));
env.require(balance("bob", XRP(10000)));
env.require(balance("carol", XRP(10000)));
env.require(balance(gw, XRP(10000)));
env(pay(env.master, "alice", XRP(1000)), fee(none), ter(temMALFORMED));
env(pay(env.master, "alice", XRP(1000)), fee(1), ter(telINSUF_FEE_P));
env(pay(env.master, "alice", XRP(1000)), seq(none), ter(temMALFORMED));
env(pay(env.master, "alice", XRP(1000)), seq(20), ter(terPRE_SEQ));
env(pay(env.master, "alice", XRP(1000)), sig(none), ter(temMALFORMED));
env(pay(env.master, "alice", XRP(1000)), sig("bob"), ter(tefBAD_AUTH_MASTER));
env(pay(env.master, "dilbert", XRP(1000)), sig(env.master));
env.trust(USD(100), "alice", "bob", "carol");
env.require(owners("alice", 1), lines("alice", 1));
env(rate(gw, 1.05));