mirror of
https://github.com/Xahau/xahaud.git
synced 2025-12-06 17:27:52 +00:00
JTx sign-and-submit mode support
This commit is contained in:
committed by
Miguel Portilla
parent
2d53ee4051
commit
119d5c1e47
@@ -3531,6 +3531,8 @@
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\test\jtx\Env.h">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\test\jtx\Env_ss.h">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\test\jtx\fee.h">
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\test\jtx\flags.h">
|
||||
|
||||
@@ -4005,6 +4005,9 @@
|
||||
<ClInclude Include="..\..\src\ripple\test\jtx\Env.h">
|
||||
<Filter>ripple\test\jtx</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\test\jtx\Env_ss.h">
|
||||
<Filter>ripple\test\jtx</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\ripple\test\jtx\fee.h">
|
||||
<Filter>ripple\test\jtx</Filter>
|
||||
</ClInclude>
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
#include <ripple/test/jtx/balance.h>
|
||||
#include <ripple/test/jtx/delivermin.h>
|
||||
#include <ripple/test/jtx/Env.h>
|
||||
#include <ripple/test/jtx/Env_ss.h>
|
||||
#include <ripple/test/jtx/fee.h>
|
||||
#include <ripple/test/jtx/flags.h>
|
||||
#include <ripple/test/jtx/jtx_json.h>
|
||||
|
||||
@@ -381,6 +381,12 @@ public:
|
||||
jtx::required(args...)(*this);
|
||||
}
|
||||
|
||||
/** Gets the TER result and `didApply` flag from a RPC Json result object.
|
||||
*/
|
||||
static
|
||||
std::pair<TER, bool>
|
||||
parseResult(Json::Value const& jr);
|
||||
|
||||
/** Submit an existing JTx.
|
||||
This calls postconditions.
|
||||
*/
|
||||
@@ -388,6 +394,12 @@ public:
|
||||
void
|
||||
submit (JTx const& jt);
|
||||
|
||||
/** Use the submit RPC command with a provided JTx object.
|
||||
This calls postconditions.
|
||||
*/
|
||||
void
|
||||
sign_and_submit(JTx const& jt, Json::Value params = Json::nullValue);
|
||||
|
||||
/** Check expected postconditions
|
||||
of JTx submission.
|
||||
*/
|
||||
@@ -407,8 +419,7 @@ public:
|
||||
template <class JsonValue,
|
||||
class... FN>
|
||||
void
|
||||
operator()(JsonValue&& jv,
|
||||
FN const&... fN)
|
||||
operator()(JsonValue&& jv, FN const&... fN)
|
||||
{
|
||||
apply(std::forward<
|
||||
JsonValue>(jv), fN...);
|
||||
@@ -433,6 +444,20 @@ public:
|
||||
std::shared_ptr<STObject const>
|
||||
meta();
|
||||
|
||||
/** Return the tx data for the last JTx.
|
||||
|
||||
Effects:
|
||||
|
||||
The tx data for the last transaction
|
||||
ID, if any, is returned. No side
|
||||
effects.
|
||||
|
||||
@note Only necessary for JTx submitted
|
||||
with via sign-and-submit method.
|
||||
*/
|
||||
std::shared_ptr<STTx const>
|
||||
tx() const;
|
||||
|
||||
private:
|
||||
void
|
||||
fund (bool setDefaultRipple,
|
||||
|
||||
86
src/ripple/test/jtx/Env_ss.h
Normal file
86
src/ripple/test/jtx/Env_ss.h
Normal file
@@ -0,0 +1,86 @@
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
This file is part of rippled: https://github.com/ripple/rippled
|
||||
Copyright (c) 2012, 2013 Ripple Labs Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any
|
||||
purpose with or without fee is hereby granted, provided that the above
|
||||
copyright notice and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
//==============================================================================
|
||||
|
||||
#ifndef RIPPLE_TEST_JTX_ENV_SS_H_INCLUDED
|
||||
#define RIPPLE_TEST_JTX_ENV_SS_H_INCLUDED
|
||||
|
||||
#include <ripple/test/jtx/Env.h>
|
||||
|
||||
namespace ripple {
|
||||
namespace test {
|
||||
namespace jtx {
|
||||
|
||||
/** A transaction testing environment wrapper.
|
||||
Transactions submitted in sign-and-submit mode
|
||||
by default.
|
||||
*/
|
||||
class Env_ss
|
||||
{
|
||||
private:
|
||||
Env& env_;
|
||||
|
||||
private:
|
||||
|
||||
class SignSubmitRunner
|
||||
{
|
||||
public:
|
||||
SignSubmitRunner(SignSubmitRunner&&) = default;
|
||||
SignSubmitRunner& operator= (SignSubmitRunner&&) = delete;
|
||||
|
||||
SignSubmitRunner(Env& env, JTx&& jt)
|
||||
: env_(env)
|
||||
, jt_(jt)
|
||||
{
|
||||
}
|
||||
|
||||
void operator()(Json::Value const& params = Json::nullValue)
|
||||
{
|
||||
env_.sign_and_submit(jt_, params);
|
||||
}
|
||||
|
||||
private:
|
||||
Env& env_;
|
||||
JTx const jt_;
|
||||
};
|
||||
|
||||
public:
|
||||
Env_ss (Env_ss const&) = delete;
|
||||
Env_ss& operator= (Env_ss const&) = delete;
|
||||
|
||||
Env_ss (Env& env)
|
||||
: env_(env)
|
||||
{
|
||||
}
|
||||
|
||||
template <class JsonValue,
|
||||
class... FN>
|
||||
SignSubmitRunner
|
||||
operator()(JsonValue&& jv, FN const&... fN)
|
||||
{
|
||||
auto jtx = env_.jt(std::forward<
|
||||
JsonValue>(jv), fN...);
|
||||
return SignSubmitRunner(env_, std::move(jtx));
|
||||
}
|
||||
};
|
||||
|
||||
} // jtx
|
||||
} // test
|
||||
} // ripple
|
||||
|
||||
#endif
|
||||
@@ -345,6 +345,20 @@ Env::trust (STAmount const& amount,
|
||||
test.expect(balance(account) == start);
|
||||
}
|
||||
|
||||
std::pair<TER, bool>
|
||||
Env::parseResult(Json::Value const& jr)
|
||||
{
|
||||
TER ter;
|
||||
if (jr.isObject() && jr.isMember(jss::result) &&
|
||||
jr[jss::result].isMember(jss::engine_result_code))
|
||||
ter = static_cast<TER>(
|
||||
jr[jss::result][jss::engine_result_code].asInt());
|
||||
else
|
||||
ter = temINVALID;
|
||||
return std::make_pair(ter,
|
||||
isTesSuccess(ter) || isTecClaim(ter));
|
||||
}
|
||||
|
||||
void
|
||||
Env::submit (JTx const& jt)
|
||||
{
|
||||
@@ -355,12 +369,8 @@ Env::submit (JTx const& jt)
|
||||
Serializer s;
|
||||
jt.stx->add(s);
|
||||
auto const jr = rpc("submit", strHex(s.slice()));
|
||||
if (jr["result"].isMember("engine_result_code"))
|
||||
ter_ = static_cast<TER>(
|
||||
jr["result"]["engine_result_code"].asInt());
|
||||
else
|
||||
ter_ = temINVALID;
|
||||
didApply = isTesSuccess(ter_) || isTecClaim(ter_);
|
||||
|
||||
std::tie(ter_, didApply) = parseResult(jr);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -372,6 +382,46 @@ Env::submit (JTx const& jt)
|
||||
return postconditions(jt, ter_, didApply);
|
||||
}
|
||||
|
||||
void
|
||||
Env::sign_and_submit(JTx const& jt, Json::Value params)
|
||||
{
|
||||
bool didApply;
|
||||
|
||||
auto const account =
|
||||
lookup(jt.jv[jss::Account].asString());
|
||||
auto const& passphrase = account.name();
|
||||
|
||||
Json::Value jr;
|
||||
if (params.isNull())
|
||||
{
|
||||
// Use the command line interface
|
||||
auto const jv = boost::lexical_cast<std::string>(jt.jv);
|
||||
jr = rpc("submit", passphrase, jv);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Use the provided parameters, and go straight
|
||||
// to the (RPC) client.
|
||||
assert(params.isObject());
|
||||
if (!params.isMember(jss::secret) &&
|
||||
!params.isMember(jss::key_type) &&
|
||||
!params.isMember(jss::seed) &&
|
||||
!params.isMember(jss::seed_hex) &&
|
||||
!params.isMember(jss::passphrase))
|
||||
{
|
||||
params[jss::secret] = passphrase;
|
||||
}
|
||||
params[jss::tx_json] = jt.jv;
|
||||
jr = client().invoke("submit", params);
|
||||
}
|
||||
txid_.SetHex(
|
||||
jr[jss::result][jss::tx_json][jss::hash].asString());
|
||||
|
||||
std::tie(ter_, didApply) = parseResult(jr);
|
||||
|
||||
return postconditions(jt, ter_, didApply);
|
||||
}
|
||||
|
||||
void
|
||||
Env::postconditions(JTx const& jt, TER ter, bool didApply)
|
||||
{
|
||||
@@ -404,6 +454,12 @@ Env::meta()
|
||||
return item.second;
|
||||
}
|
||||
|
||||
std::shared_ptr<STTx const>
|
||||
Env::tx() const
|
||||
{
|
||||
return current()->txRead(txid_).first;
|
||||
}
|
||||
|
||||
void
|
||||
Env::autofill_sig (JTx& jt)
|
||||
{
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include <ripple/test/jtx.h>
|
||||
#include <ripple/json/to_string.h>
|
||||
#include <ripple/protocol/Feature.h>
|
||||
#include <ripple/protocol/JsonFields.h>
|
||||
#include <ripple/protocol/TxFlags.h>
|
||||
#include <ripple/beast/hash/uhash.h>
|
||||
#include <ripple/beast/unit_test.h>
|
||||
@@ -578,6 +579,54 @@ public:
|
||||
env (jt);
|
||||
}
|
||||
|
||||
void testSignAndSubmit()
|
||||
{
|
||||
using namespace jtx;
|
||||
Env env(*this);
|
||||
Env_ss envs(env);
|
||||
|
||||
auto const alice = Account("alice");
|
||||
env.fund(XRP(10000), alice);
|
||||
|
||||
{
|
||||
envs(noop(alice), fee(none), seq(none))();
|
||||
|
||||
// Make sure we get the right account back.
|
||||
auto tx = env.tx();
|
||||
if (expect(tx))
|
||||
{
|
||||
expect(tx->getAccountID(sfAccount) == alice.id());
|
||||
expect(tx->getTxnType() == ttACCOUNT_SET);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
auto params = Json::Value(Json::nullValue);
|
||||
envs(noop(alice), fee(none), seq(none))(params);
|
||||
|
||||
// Make sure we get the right account back.
|
||||
auto tx = env.tx();
|
||||
if (expect(tx))
|
||||
{
|
||||
expect(tx->getAccountID(sfAccount) == alice.id());
|
||||
expect(tx->getTxnType() == ttACCOUNT_SET);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
auto params = Json::Value(Json::objectValue);
|
||||
// Force the factor low enough to fail
|
||||
params[jss::fee_mult_max] = 1;
|
||||
params[jss::fee_div_max] = 2;
|
||||
// RPC errors result in temINVALID
|
||||
envs(noop(alice), fee(none),
|
||||
seq(none), ter(temINVALID))(params);
|
||||
|
||||
auto tx = env.tx();
|
||||
expect(!tx);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
run()
|
||||
{
|
||||
@@ -598,6 +647,7 @@ public:
|
||||
testClose();
|
||||
testPath();
|
||||
testResignSigned();
|
||||
testSignAndSubmit();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user