mirror of
https://github.com/Xahau/xahaud.git
synced 2025-11-27 22:15:49 +00:00
js prepare otxn_json, compiling not tested
This commit is contained in:
committed by
RichardAH
parent
1f7355719d
commit
46308e33b0
@@ -275,6 +275,15 @@ DECLARE_JS_FUNCTION(
|
||||
emit,
|
||||
JSValue txn);
|
||||
|
||||
DECLARE_JS_FUNCTION(
|
||||
JSValue,
|
||||
prepare,
|
||||
JSValue tmpl);
|
||||
|
||||
DECLARE_JS_FUNCNARG(
|
||||
JSValue,
|
||||
otxn_json);
|
||||
|
||||
DECLARE_WASM_FUNCTION(int64_t, float_set, int32_t exponent, int64_t mantissa);
|
||||
DECLARE_JS_FUNCTION(
|
||||
JSValue,
|
||||
@@ -1301,6 +1310,8 @@ public:
|
||||
ADD_JS_FUNCTION(sto_erase, ctx);
|
||||
|
||||
ADD_JS_FUNCTION(emit, ctx);
|
||||
ADD_JS_FUNCTION(prepare, ctx);
|
||||
ADD_JS_FUNCTION(otxn_json, ctx);
|
||||
|
||||
ADD_JS_FUNCTION(etxn_burden, ctx);
|
||||
ADD_JS_FUNCTION(etxn_fee_base, ctx);
|
||||
|
||||
@@ -22,6 +22,8 @@
|
||||
#include <cstdint>
|
||||
#include <limits>
|
||||
#include <tuple>
|
||||
#include <ripple/json/json_value.h>
|
||||
#include <ripple/json/json_writer.h>
|
||||
|
||||
using namespace ripple;
|
||||
// check if any std::optionals are missing (any !has_value())
|
||||
@@ -2973,7 +2975,7 @@ int64_t __etxn_burden(
|
||||
return PREREQUISITE_NOT_MET;
|
||||
|
||||
// always non-negative so cast is safe
|
||||
uint64_t last_burden = (uint64_t)__etxn_burden(hookCtx, applyCtx, j);
|
||||
uint64_t last_burden = (uint64_t)__otxn_burden(hookCtx, applyCtx, j);
|
||||
|
||||
uint64_t burden = last_burden * hookCtx.expected_etxn_count;
|
||||
if (burden <
|
||||
@@ -5060,9 +5062,44 @@ DEFINE_JS_FUNCTION(
|
||||
{
|
||||
JS_HOOK_SETUP();
|
||||
|
||||
auto tx = FromJSIntArrayOrHexString(ctx, raw_tx, 0x10000);
|
||||
std::optional<std::vector<uint8_t>> tx = FromJSIntArrayOrHexString(ctx, raw_tx, 0x10000);
|
||||
|
||||
if (!tx.has_value() || tx->empty())
|
||||
returnJS(INVALID_ARGUMENT);
|
||||
{
|
||||
|
||||
// the user may specify the tx as a js object
|
||||
if (!JS_IsObject(raw_tx))
|
||||
returnJS(INVALID_ARGUMENT);
|
||||
|
||||
// stringify it
|
||||
JSValue sdata = JS_JSONStringify(ctx, raw_tx, JS_UNDEFINED, JS_UNDEFINED);
|
||||
if (JS_IsException(sdata))
|
||||
returnJS(INVALID_ARGUMENT);
|
||||
|
||||
size_t len;
|
||||
const char* cstr = JS_ToCStringLen(ctx, &len, sdata);
|
||||
if (len > 1024*1024)
|
||||
returnJS(TOO_BIG);
|
||||
std::string const tmpl(cstr, len);
|
||||
JS_FreeCString(ctx, cstr);
|
||||
|
||||
// parse it on rippled side
|
||||
Json::Value json;
|
||||
Json::Reader reader;
|
||||
if (!reader.parse(tmpl, json) || !json || !json.isObject())
|
||||
returnJS(INVALID_ARGUMENT);
|
||||
|
||||
// turn the json into a stobject
|
||||
STParsedJSONObject parsed(std::string(jss::tx_json), json);
|
||||
if (!parsed.object.has_value())
|
||||
returnJS(INVALID_ARGUMENT);
|
||||
|
||||
// turn the stobject into a tx_blob
|
||||
STObject& obj = *(parsed.object);
|
||||
Serializer s;
|
||||
obj.add(s);
|
||||
tx = s.getData();
|
||||
}
|
||||
|
||||
auto ret = __emit(hookCtx, applyCtx, j, tx->data(), tx->size());
|
||||
|
||||
@@ -5083,6 +5120,141 @@ DEFINE_JS_FUNCTION(
|
||||
JS_HOOK_TEARDOWN();
|
||||
}
|
||||
|
||||
inline
|
||||
int64_t __etxn_details(
|
||||
hook::HookContext& hookCtx, ApplyContext& applyCtx, beast::Journal& j,
|
||||
uint8_t* out_ptr, size_t max_len);
|
||||
|
||||
DEFINE_JS_FUNCTION(
|
||||
JSValue,
|
||||
prepare,
|
||||
JSValue raw_tmpl)
|
||||
{
|
||||
JS_HOOK_SETUP();
|
||||
|
||||
if (!JS_IsObject(raw_tmpl))
|
||||
returnJS(INVALID_ARGUMENT);
|
||||
|
||||
auto& view = applyCtx.view();
|
||||
|
||||
// stringify it
|
||||
JSValue sdata = JS_JSONStringify(ctx, raw_tmpl, JS_UNDEFINED, JS_UNDEFINED);
|
||||
if (JS_IsException(sdata))
|
||||
returnJS(INVALID_ARGUMENT);
|
||||
size_t len;
|
||||
const char* cstr = JS_ToCStringLen(ctx, &len, sdata);
|
||||
if (len > 1024*1024)
|
||||
returnJS(TOO_BIG);
|
||||
std::string tmpl(cstr, len);
|
||||
JS_FreeCString(ctx, cstr);
|
||||
|
||||
// parse it on rippled side
|
||||
Json::Value json;
|
||||
Json::Reader reader;
|
||||
if (!reader.parse(tmpl, json) || !json || !json.isObject())
|
||||
returnJS(INVALID_ARGUMENT);
|
||||
|
||||
// add a dummy fee
|
||||
json[jss::fee] = "0";
|
||||
|
||||
// force key to empty
|
||||
json[jss::SigningPubKey] = "";
|
||||
|
||||
// force sequence to 0
|
||||
json[jss::Sequence] = Json::Value(0u);
|
||||
|
||||
std::string raddr =
|
||||
encodeBase58Token(TokenType::AccountID, hookCtx.result.account.data(), 20);
|
||||
|
||||
json[jss::Account] = raddr;
|
||||
|
||||
int64_t seq = view.info().seq;
|
||||
if (!json.isMember(jss::FirstLedgerSequence))
|
||||
json[jss::FirstLedgerSequence] = Json::Value((uint32_t)(seq + 1));
|
||||
|
||||
if (!json.isMember(jss::LastLedgerSequence))
|
||||
json[jss::LastLedgerSequence] = Json::Value((uint32_t)(seq + 5));
|
||||
|
||||
uint8_t details[512];
|
||||
if (!json.isMember(jss::EmitDetails))
|
||||
{
|
||||
int64_t ret = __etxn_details(hookCtx, applyCtx, j, details, 512);
|
||||
if (ret <= 0)
|
||||
returnJS(INTERNAL_ERROR);
|
||||
Slice s(reinterpret_cast<void const*>(details), (size_t)ret);
|
||||
|
||||
try
|
||||
{
|
||||
SerialIter sit{s};
|
||||
STObject st{sit, sfGeneric};
|
||||
json[jss::EmitDetails] = st.getJson(JsonOptions::none);
|
||||
}
|
||||
catch (std::exception const& ex)
|
||||
{
|
||||
JLOG(j.warn())
|
||||
<< "Exception in " << __func__ << ": " << ex.what();
|
||||
returnJS(INTERNAL_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
STParsedJSONObject parsed(std::string(jss::tx_json), json);
|
||||
if (!parsed.object.has_value())
|
||||
returnJS(INVALID_ARGUMENT);
|
||||
|
||||
STObject& obj = *(parsed.object);
|
||||
|
||||
// serialize it
|
||||
Serializer s;
|
||||
obj.add(s);
|
||||
Blob tx_blob = s.getData();
|
||||
|
||||
// run it through the fee estimate, this doubles as a txn sanity check
|
||||
int64_t fee = __etxn_fee_base(hookCtx, applyCtx, j, tx_blob.data(), tx_blob.size());
|
||||
if (fee < 0)
|
||||
returnJS(INVALID_ARGUMENT);
|
||||
|
||||
json[jss::fee] = to_string(fee);
|
||||
|
||||
// send it back to the user
|
||||
|
||||
const std::string flat = Json::FastWriter().write(json);
|
||||
|
||||
JSValue out;
|
||||
out = JS_ParseJSON(ctx, flat.data(), flat.size(), "<json>");
|
||||
|
||||
if (JS_IsException(out))
|
||||
returnJS(INTERNAL_ERROR);
|
||||
|
||||
return out;
|
||||
|
||||
JS_HOOK_TEARDOWN();
|
||||
}
|
||||
|
||||
DEFINE_JS_FUNCNARG(
|
||||
JSValue,
|
||||
otxn_json)
|
||||
{
|
||||
JS_HOOK_SETUP();
|
||||
|
||||
auto const& st = std::make_unique<ripple::STObject>(
|
||||
hookCtx.emitFailure ? *(hookCtx.emitFailure)
|
||||
: const_cast<ripple::STTx&>(applyCtx.tx)
|
||||
.downcast<ripple::STObject>());
|
||||
|
||||
const std::string flat = Json::FastWriter().write(st->getJson(JsonOptions::none));
|
||||
|
||||
JSValue out;
|
||||
out = JS_ParseJSON(ctx, flat.data(), flat.size(), "<json>");
|
||||
|
||||
if (JS_IsException(out))
|
||||
returnJS(INTERNAL_ERROR);
|
||||
|
||||
return out;
|
||||
|
||||
JS_HOOK_TEARDOWN();
|
||||
}
|
||||
|
||||
// When implemented will return the hash of the current hook
|
||||
DEFINE_WASM_FUNCTION(
|
||||
int64_t,
|
||||
|
||||
@@ -96,6 +96,7 @@ JSS(ImportVLSequence);
|
||||
JSS(Invalid); //
|
||||
JSS(Invoke); // transaction type
|
||||
JSS(InvoiceID); // field
|
||||
JSS(FirstLedgerSequence);
|
||||
JSS(LastLedgerSequence); // in: TransactionSign; field
|
||||
JSS(LedgerHashes); // ledger type.
|
||||
JSS(LimitAmount); // field.
|
||||
@@ -134,6 +135,7 @@ JSS(HookDefinition); // ledger type.
|
||||
JSS(HookState); // ledger type.
|
||||
JSS(HookStateData); // field.
|
||||
JSS(HookStateKey); // field.
|
||||
JSS(EmitDetails);
|
||||
JSS(EmittedTxn); // ledger type.
|
||||
JSS(SignerList); // ledger type.
|
||||
JSS(SignerListSet); // transaction type.
|
||||
|
||||
Reference in New Issue
Block a user