mirror of
https://github.com/Xahau/xahaud.git
synced 2025-11-20 18:45:55 +00:00
refactor
This commit is contained in:
@@ -1,9 +1,4 @@
|
||||
// A decoupled Hook host API helper for programmatic use and testing.
|
||||
// Provides selected Hook APIs (emit-related and dependencies) without any
|
||||
// dependency on WASM memory. It operates directly on ripple types.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <ripple/app/hook/Enum.h>
|
||||
#include <ripple/app/tx/impl/ApplyContext.h>
|
||||
#include <ripple/basics/Blob.h>
|
||||
#include <ripple/basics/Expected.h>
|
||||
@@ -14,6 +9,8 @@
|
||||
#include <cstdint>
|
||||
|
||||
namespace hook {
|
||||
using namespace ripple;
|
||||
using HookReturnCode = hook_api::hook_return_code;
|
||||
|
||||
struct HookContext; // defined in applyHook.h
|
||||
|
||||
@@ -26,21 +23,21 @@ public:
|
||||
|
||||
// Emit a transaction from the running hook. On success, returns 32-byte
|
||||
// transaction ID bytes (same content written by the wasm host function).
|
||||
ripple::Expected<std::shared_ptr<ripple::Transaction>, std::int64_t>
|
||||
emit(ripple::Slice txBlob);
|
||||
Expected<std::shared_ptr<Transaction>, HookReturnCode>
|
||||
emit(Slice txBlob);
|
||||
|
||||
// Dependencies (public so callers can compose):
|
||||
// etxn_generation == otxn_generation() + 1
|
||||
std::int64_t
|
||||
uint32_t
|
||||
etxn_generation() const;
|
||||
std::int64_t
|
||||
Expected<uint64_t, HookReturnCode>
|
||||
etxn_burden() const;
|
||||
std::int64_t
|
||||
etxn_fee_base(ripple::Slice txBlob) const;
|
||||
Expected<uint64_t, HookReturnCode>
|
||||
etxn_fee_base(Slice txBlob) const;
|
||||
|
||||
std::int64_t
|
||||
uint32_t
|
||||
otxn_generation() const;
|
||||
std::int64_t
|
||||
uint64_t
|
||||
otxn_burden() const;
|
||||
|
||||
private:
|
||||
|
||||
@@ -16,7 +16,7 @@ namespace hook {
|
||||
|
||||
using namespace ripple;
|
||||
|
||||
std::int64_t
|
||||
uint64_t
|
||||
HookAPI::otxn_burden() const
|
||||
{
|
||||
auto& applyCtx = hookCtx.applyCtx;
|
||||
@@ -41,13 +41,13 @@ HookAPI::otxn_burden() const
|
||||
return 1;
|
||||
}
|
||||
|
||||
std::uint64_t burden = pd.getFieldU64(sfEmitBurden);
|
||||
uint64_t burden = pd.getFieldU64(sfEmitBurden);
|
||||
burden &= ((1ULL << 63) - 1);
|
||||
hookCtx.burden = burden;
|
||||
return static_cast<std::int64_t>(burden);
|
||||
return static_cast<int64_t>(burden);
|
||||
}
|
||||
|
||||
std::int64_t
|
||||
uint32_t
|
||||
HookAPI::otxn_generation() const
|
||||
{
|
||||
auto& applyCtx = hookCtx.applyCtx;
|
||||
@@ -76,34 +76,34 @@ HookAPI::otxn_generation() const
|
||||
return hookCtx.generation;
|
||||
}
|
||||
|
||||
std::int64_t
|
||||
uint32_t
|
||||
HookAPI::etxn_generation() const
|
||||
{
|
||||
return otxn_generation() + 1;
|
||||
}
|
||||
|
||||
std::int64_t
|
||||
Expected<uint64_t, HookReturnCode>
|
||||
HookAPI::etxn_burden() const
|
||||
{
|
||||
if (hookCtx.expected_etxn_count <= -1)
|
||||
return hook_api::PREREQUISITE_NOT_MET;
|
||||
return Unexpected(hook_api::PREREQUISITE_NOT_MET);
|
||||
|
||||
std::uint64_t last_burden = static_cast<std::uint64_t>(otxn_burden());
|
||||
std::uint64_t burden =
|
||||
last_burden * static_cast<std::uint64_t>(hookCtx.expected_etxn_count);
|
||||
uint64_t last_burden = static_cast<uint64_t>(otxn_burden());
|
||||
uint64_t burden =
|
||||
last_burden * static_cast<uint64_t>(hookCtx.expected_etxn_count);
|
||||
if (burden < last_burden)
|
||||
return hook_api::FEE_TOO_LARGE;
|
||||
return static_cast<std::int64_t>(burden);
|
||||
return Unexpected(hook_api::FEE_TOO_LARGE);
|
||||
return burden;
|
||||
}
|
||||
|
||||
std::int64_t
|
||||
Expected<uint64_t, HookReturnCode>
|
||||
HookAPI::etxn_fee_base(ripple::Slice txBlob) const
|
||||
{
|
||||
auto& applyCtx = hookCtx.applyCtx;
|
||||
auto j = applyCtx.app.journal("View");
|
||||
|
||||
if (hookCtx.expected_etxn_count <= -1)
|
||||
return hook_api::PREREQUISITE_NOT_MET;
|
||||
return Unexpected(hook_api::PREREQUISITE_NOT_MET);
|
||||
|
||||
try
|
||||
{
|
||||
@@ -118,11 +118,11 @@ HookAPI::etxn_fee_base(ripple::Slice txBlob) const
|
||||
{
|
||||
JLOG(j.trace()) << "HookInfo[" << HC_ACC()
|
||||
<< "]: etxn_fee_base exception: " << e.what();
|
||||
return hook_api::INVALID_TXN;
|
||||
return Unexpected(hook_api::INVALID_TXN);
|
||||
}
|
||||
}
|
||||
|
||||
ripple::Expected<std::shared_ptr<Transaction>, std::int64_t>
|
||||
Expected<std::shared_ptr<Transaction>, HookReturnCode>
|
||||
HookAPI::emit(ripple::Slice txBlob)
|
||||
{
|
||||
auto& applyCtx = hookCtx.applyCtx;
|
||||
@@ -130,10 +130,10 @@ HookAPI::emit(ripple::Slice txBlob)
|
||||
auto& view = applyCtx.view();
|
||||
|
||||
if (hookCtx.expected_etxn_count < 0)
|
||||
return ripple::Unexpected<std::int64_t>(hook_api::PREREQUISITE_NOT_MET);
|
||||
return Unexpected(hook_api::PREREQUISITE_NOT_MET);
|
||||
|
||||
if (hookCtx.result.emittedTxn.size() >= hookCtx.expected_etxn_count)
|
||||
return ripple::Unexpected<std::int64_t>(hook_api::TOO_MANY_EMITTED_TXN);
|
||||
return Unexpected(hook_api::TOO_MANY_EMITTED_TXN);
|
||||
|
||||
std::shared_ptr<STTx const> stpTrans;
|
||||
try
|
||||
@@ -144,14 +144,14 @@ HookAPI::emit(ripple::Slice txBlob)
|
||||
catch (std::exception const& e)
|
||||
{
|
||||
JLOG(j.trace()) << "HookEmit[" << HC_ACC() << "]: Failed " << e.what();
|
||||
return ripple::Unexpected<std::int64_t>(hook_api::EMISSION_FAILURE);
|
||||
return Unexpected(hook_api::EMISSION_FAILURE);
|
||||
}
|
||||
|
||||
if (isPseudoTx(*stpTrans))
|
||||
{
|
||||
JLOG(j.trace()) << "HookEmit[" << HC_ACC()
|
||||
<< "]: Attempted to emit pseudo txn.";
|
||||
return ripple::Unexpected<std::int64_t>(hook_api::EMISSION_FAILURE);
|
||||
return Unexpected(hook_api::EMISSION_FAILURE);
|
||||
}
|
||||
|
||||
ripple::TxType txType = stpTrans->getTxnType();
|
||||
@@ -161,7 +161,7 @@ HookAPI::emit(ripple::Slice txBlob)
|
||||
{
|
||||
JLOG(j.trace()) << "HookEmit[" << HC_ACC()
|
||||
<< "]: Hook cannot emit this txn.";
|
||||
return ripple::Unexpected<std::uint64_t>(hook_api::EMISSION_FAILURE);
|
||||
return Unexpected(hook_api::EMISSION_FAILURE);
|
||||
}
|
||||
|
||||
// check the emitted txn is valid
|
||||
@@ -184,7 +184,7 @@ HookAPI::emit(ripple::Slice txBlob)
|
||||
{
|
||||
JLOG(j.trace()) << "HookEmit[" << HC_ACC()
|
||||
<< "]: sfAccount does not match hook account";
|
||||
return ripple::Unexpected<std::int64_t>(hook_api::EMISSION_FAILURE);
|
||||
return Unexpected(hook_api::EMISSION_FAILURE);
|
||||
}
|
||||
|
||||
// rule 1: sfSequence must be present and 0
|
||||
@@ -193,7 +193,7 @@ HookAPI::emit(ripple::Slice txBlob)
|
||||
{
|
||||
JLOG(j.trace()) << "HookEmit[" << HC_ACC()
|
||||
<< "]: sfSequence missing or non-zero";
|
||||
return ripple::Unexpected<std::int64_t>(hook_api::EMISSION_FAILURE);
|
||||
return Unexpected(hook_api::EMISSION_FAILURE);
|
||||
}
|
||||
|
||||
// rule 2: sfSigningPubKey must be present and 00...00
|
||||
@@ -201,7 +201,7 @@ HookAPI::emit(ripple::Slice txBlob)
|
||||
{
|
||||
JLOG(j.trace()) << "HookEmit[" << HC_ACC()
|
||||
<< "]: sfSigningPubKey missing";
|
||||
return ripple::Unexpected<std::int64_t>(hook_api::EMISSION_FAILURE);
|
||||
return Unexpected(hook_api::EMISSION_FAILURE);
|
||||
}
|
||||
|
||||
auto const pk = stpTrans->getSigningPubKey();
|
||||
@@ -209,7 +209,7 @@ HookAPI::emit(ripple::Slice txBlob)
|
||||
{
|
||||
JLOG(j.trace()) << "HookEmit[" << HC_ACC()
|
||||
<< "]: sfSigningPubKey present but wrong size";
|
||||
return ripple::Unexpected<std::int64_t>(hook_api::EMISSION_FAILURE);
|
||||
return Unexpected(hook_api::EMISSION_FAILURE);
|
||||
}
|
||||
|
||||
for (int i = 0; i < pk.size(); ++i)
|
||||
@@ -217,7 +217,7 @@ HookAPI::emit(ripple::Slice txBlob)
|
||||
{
|
||||
JLOG(j.trace()) << "HookEmit[" << HC_ACC()
|
||||
<< "]: sfSigningPubKey present but non-zero.";
|
||||
return ripple::Unexpected<std::int64_t>(hook_api::EMISSION_FAILURE);
|
||||
return Unexpected(hook_api::EMISSION_FAILURE);
|
||||
}
|
||||
|
||||
// rule 2.a: no signers
|
||||
@@ -225,7 +225,7 @@ HookAPI::emit(ripple::Slice txBlob)
|
||||
{
|
||||
JLOG(j.trace()) << "HookEmit[" << HC_ACC()
|
||||
<< "]: sfSigners not allowed in emitted txns.";
|
||||
return ripple::Unexpected<std::int64_t>(hook_api::EMISSION_FAILURE);
|
||||
return Unexpected(hook_api::EMISSION_FAILURE);
|
||||
}
|
||||
|
||||
// rule 2.b: ticketseq cannot be used
|
||||
@@ -233,7 +233,7 @@ HookAPI::emit(ripple::Slice txBlob)
|
||||
{
|
||||
JLOG(j.trace()) << "HookEmit[" << HC_ACC()
|
||||
<< "]: sfTicketSequence not allowed in emitted txns.";
|
||||
return ripple::Unexpected<std::int64_t>(hook_api::EMISSION_FAILURE);
|
||||
return Unexpected(hook_api::EMISSION_FAILURE);
|
||||
}
|
||||
|
||||
// rule 2.c sfAccountTxnID not allowed
|
||||
@@ -241,7 +241,7 @@ HookAPI::emit(ripple::Slice txBlob)
|
||||
{
|
||||
JLOG(j.trace()) << "HookEmit[" << HC_ACC()
|
||||
<< "]: sfAccountTxnID not allowed in emitted txns.";
|
||||
return ripple::Unexpected<std::int64_t>(hook_api::EMISSION_FAILURE);
|
||||
return Unexpected(hook_api::EMISSION_FAILURE);
|
||||
}
|
||||
|
||||
// rule 3: sfEmitDetails must be present and valid
|
||||
@@ -249,7 +249,7 @@ HookAPI::emit(ripple::Slice txBlob)
|
||||
{
|
||||
JLOG(j.trace()) << "HookEmit[" << HC_ACC()
|
||||
<< "]: sfEmitDetails missing.";
|
||||
return ripple::Unexpected<std::int64_t>(hook_api::EMISSION_FAILURE);
|
||||
return Unexpected(hook_api::EMISSION_FAILURE);
|
||||
}
|
||||
|
||||
auto const& emitDetails = const_cast<ripple::STTx&>(*stpTrans)
|
||||
@@ -264,7 +264,7 @@ HookAPI::emit(ripple::Slice txBlob)
|
||||
{
|
||||
JLOG(j.trace()) << "HookEmit[" << HC_ACC()
|
||||
<< "]: sfEmitDetails malformed.";
|
||||
return ripple::Unexpected<std::int64_t>(hook_api::EMISSION_FAILURE);
|
||||
return Unexpected(hook_api::EMISSION_FAILURE);
|
||||
}
|
||||
|
||||
// rule 8: emit generation cannot exceed 10
|
||||
@@ -272,7 +272,7 @@ HookAPI::emit(ripple::Slice txBlob)
|
||||
{
|
||||
JLOG(j.trace()) << "HookEmit[" << HC_ACC()
|
||||
<< "]: sfEmitGeneration was 10 or more.";
|
||||
return ripple::Unexpected<std::int64_t>(hook_api::EMISSION_FAILURE);
|
||||
return Unexpected(hook_api::EMISSION_FAILURE);
|
||||
}
|
||||
|
||||
auto const gen = emitDetails.getFieldU32(sfEmitGeneration);
|
||||
@@ -286,7 +286,7 @@ HookAPI::emit(ripple::Slice txBlob)
|
||||
|
||||
auto const& hash = emitDetails.getFieldH256(sfEmitHookHash);
|
||||
|
||||
std::uint32_t gen_proper = static_cast<std::uint32_t>(etxn_generation());
|
||||
uint32_t gen_proper = static_cast<uint32_t>(etxn_generation());
|
||||
|
||||
if (gen != gen_proper)
|
||||
{
|
||||
@@ -294,17 +294,17 @@ HookAPI::emit(ripple::Slice txBlob)
|
||||
<< "]: sfEmitGeneration provided in EmitDetails "
|
||||
<< "not correct (" << gen << ") "
|
||||
<< "should be " << gen_proper;
|
||||
return ripple::Unexpected<std::int64_t>(hook_api::EMISSION_FAILURE);
|
||||
return Unexpected(hook_api::EMISSION_FAILURE);
|
||||
}
|
||||
|
||||
std::uint64_t bur_proper = static_cast<std::uint64_t>(etxn_burden());
|
||||
uint64_t bur_proper = static_cast<uint64_t>(etxn_burden().value());
|
||||
if (bur != bur_proper)
|
||||
{
|
||||
JLOG(j.trace()) << "HookEmit[" << HC_ACC()
|
||||
<< "]: sfEmitBurden provided in EmitDetails "
|
||||
<< "was not correct (" << bur << ") "
|
||||
<< "should be " << bur_proper;
|
||||
return ripple::Unexpected<std::int64_t>(hook_api::EMISSION_FAILURE);
|
||||
return Unexpected(hook_api::EMISSION_FAILURE);
|
||||
}
|
||||
|
||||
if (pTxnID != applyCtx.tx.getTransactionID())
|
||||
@@ -312,7 +312,7 @@ HookAPI::emit(ripple::Slice txBlob)
|
||||
JLOG(j.trace()) << "HookEmit[" << HC_ACC()
|
||||
<< "]: sfEmitParentTxnID provided in EmitDetails"
|
||||
<< "was not correct";
|
||||
return ripple::Unexpected<std::int64_t>(hook_api::EMISSION_FAILURE);
|
||||
return Unexpected(hook_api::EMISSION_FAILURE);
|
||||
}
|
||||
|
||||
if (hookCtx.nonce_used.find(nonce) == hookCtx.nonce_used.end())
|
||||
@@ -320,7 +320,7 @@ HookAPI::emit(ripple::Slice txBlob)
|
||||
JLOG(j.trace()) << "HookEmit[" << HC_ACC()
|
||||
<< "]: sfEmitNonce provided in EmitDetails was not "
|
||||
"generated by nonce api";
|
||||
return ripple::Unexpected<std::int64_t>(hook_api::EMISSION_FAILURE);
|
||||
return Unexpected(hook_api::EMISSION_FAILURE);
|
||||
}
|
||||
|
||||
if (callback && *callback != hookCtx.result.account)
|
||||
@@ -328,7 +328,7 @@ HookAPI::emit(ripple::Slice txBlob)
|
||||
JLOG(j.trace()) << "HookEmit[" << HC_ACC()
|
||||
<< "]: sfEmitCallback account must be the account of "
|
||||
"the emitting hook";
|
||||
return ripple::Unexpected<std::int64_t>(hook_api::EMISSION_FAILURE);
|
||||
return Unexpected(hook_api::EMISSION_FAILURE);
|
||||
}
|
||||
|
||||
if (hash != hookCtx.result.hookHash)
|
||||
@@ -336,7 +336,7 @@ HookAPI::emit(ripple::Slice txBlob)
|
||||
JLOG(j.trace())
|
||||
<< "HookEmit[" << HC_ACC()
|
||||
<< "]: sfEmitHookHash must be the hash of the emitting hook";
|
||||
return ripple::Unexpected<std::int64_t>(hook_api::EMISSION_FAILURE);
|
||||
return Unexpected(hook_api::EMISSION_FAILURE);
|
||||
}
|
||||
|
||||
// rule 4: sfTxnSignature must be absent
|
||||
@@ -344,7 +344,7 @@ HookAPI::emit(ripple::Slice txBlob)
|
||||
{
|
||||
JLOG(j.trace()) << "HookEmit[" << HC_ACC()
|
||||
<< "]: sfTxnSignature is present but should not be";
|
||||
return ripple::Unexpected<std::int64_t>(hook_api::EMISSION_FAILURE);
|
||||
return Unexpected(hook_api::EMISSION_FAILURE);
|
||||
}
|
||||
|
||||
// rule 5: LastLedgerSeq must be present and after current ledger
|
||||
@@ -352,17 +352,17 @@ HookAPI::emit(ripple::Slice txBlob)
|
||||
{
|
||||
JLOG(j.trace()) << "HookEmit[" << HC_ACC()
|
||||
<< "]: sfLastLedgerSequence missing";
|
||||
return ripple::Unexpected<std::int64_t>(hook_api::EMISSION_FAILURE);
|
||||
return Unexpected(hook_api::EMISSION_FAILURE);
|
||||
}
|
||||
|
||||
std::uint32_t tx_lls = stpTrans->getFieldU32(sfLastLedgerSequence);
|
||||
std::uint32_t ledgerSeq = view.info().seq;
|
||||
uint32_t tx_lls = stpTrans->getFieldU32(sfLastLedgerSequence);
|
||||
uint32_t ledgerSeq = view.info().seq;
|
||||
if (tx_lls < ledgerSeq + 1)
|
||||
{
|
||||
JLOG(j.trace())
|
||||
<< "HookEmit[" << HC_ACC()
|
||||
<< "]: sfLastLedgerSequence invalid (less than next ledger)";
|
||||
return ripple::Unexpected<std::int64_t>(hook_api::EMISSION_FAILURE);
|
||||
return Unexpected(hook_api::EMISSION_FAILURE);
|
||||
}
|
||||
|
||||
if (tx_lls > ledgerSeq + 5)
|
||||
@@ -370,7 +370,7 @@ HookAPI::emit(ripple::Slice txBlob)
|
||||
JLOG(j.trace())
|
||||
<< "HookEmit[" << HC_ACC()
|
||||
<< "]: sfLastLedgerSequence cannot be greater than current seq + 5";
|
||||
return ripple::Unexpected<std::int64_t>(hook_api::EMISSION_FAILURE);
|
||||
return Unexpected(hook_api::EMISSION_FAILURE);
|
||||
}
|
||||
|
||||
// rule 6
|
||||
@@ -380,32 +380,32 @@ HookAPI::emit(ripple::Slice txBlob)
|
||||
JLOG(j.trace()) << "HookEmit[" << HC_ACC()
|
||||
<< "]: sfFirstLedgerSequence must be present and <= "
|
||||
"LastLedgerSequence";
|
||||
return ripple::Unexpected<std::int64_t>(hook_api::EMISSION_FAILURE);
|
||||
return Unexpected(hook_api::EMISSION_FAILURE);
|
||||
}
|
||||
|
||||
// rule 7 check the emitted txn pays the appropriate fee
|
||||
std::int64_t minfee = etxn_fee_base(txBlob);
|
||||
int64_t minfee = etxn_fee_base(txBlob).value();
|
||||
|
||||
if (minfee < 0)
|
||||
{
|
||||
JLOG(j.trace()) << "HookEmit[" << HC_ACC()
|
||||
<< "]: Fee could not be calculated";
|
||||
return ripple::Unexpected<std::int64_t>(hook_api::EMISSION_FAILURE);
|
||||
return Unexpected(hook_api::EMISSION_FAILURE);
|
||||
}
|
||||
|
||||
if (!stpTrans->isFieldPresent(sfFee))
|
||||
{
|
||||
JLOG(j.trace()) << "HookEmit[" << HC_ACC()
|
||||
<< "]: Fee missing from emitted tx";
|
||||
return ripple::Unexpected<std::int64_t>(hook_api::EMISSION_FAILURE);
|
||||
return Unexpected(hook_api::EMISSION_FAILURE);
|
||||
}
|
||||
|
||||
std::int64_t fee = stpTrans->getFieldAmount(sfFee).xrp().drops();
|
||||
int64_t fee = stpTrans->getFieldAmount(sfFee).xrp().drops();
|
||||
if (fee < minfee)
|
||||
{
|
||||
JLOG(j.trace()) << "HookEmit[" << HC_ACC()
|
||||
<< "]: Fee less than minimum required";
|
||||
return ripple::Unexpected<std::int64_t>(hook_api::EMISSION_FAILURE);
|
||||
return Unexpected(hook_api::EMISSION_FAILURE);
|
||||
}
|
||||
|
||||
std::string reason;
|
||||
@@ -415,7 +415,7 @@ HookAPI::emit(ripple::Slice txBlob)
|
||||
{
|
||||
JLOG(j.trace()) << "HookEmit[" << HC_ACC()
|
||||
<< "]: tpTrans->getStatus() != NEW";
|
||||
return ripple::Unexpected<std::int64_t>(hook_api::EMISSION_FAILURE);
|
||||
return Unexpected(hook_api::EMISSION_FAILURE);
|
||||
}
|
||||
|
||||
// preflight the transaction
|
||||
@@ -431,7 +431,7 @@ HookAPI::emit(ripple::Slice txBlob)
|
||||
JLOG(j.trace()) << "HookEmit[" << HC_ACC()
|
||||
<< "]: Transaction preflight failure: "
|
||||
<< preflightResult.ter;
|
||||
return ripple::Unexpected<std::int64_t>(hook_api::EMISSION_FAILURE);
|
||||
return Unexpected(hook_api::EMISSION_FAILURE);
|
||||
}
|
||||
|
||||
return tpTrans;
|
||||
|
||||
@@ -3490,7 +3490,10 @@ DEFINE_HOOK_FUNCNARG(int64_t, etxn_burden)
|
||||
{
|
||||
HOOK_SETUP();
|
||||
hook::HookAPI api(hookCtx);
|
||||
return api.etxn_burden();
|
||||
auto const burden = api.etxn_burden();
|
||||
if (!burden)
|
||||
return burden.error();
|
||||
return burden.value();
|
||||
HOOK_TEARDOWN();
|
||||
}
|
||||
|
||||
@@ -4280,7 +4283,10 @@ DEFINE_HOOK_FUNCTION(
|
||||
hook::HookAPI api(hookCtx);
|
||||
ripple::Slice tx{
|
||||
reinterpret_cast<const void*>(read_ptr + memory), read_len};
|
||||
return api.etxn_fee_base(tx);
|
||||
auto const fee_base = api.etxn_fee_base(tx);
|
||||
if (!fee_base)
|
||||
return fee_base.error();
|
||||
return fee_base.value();
|
||||
HOOK_TEARDOWN();
|
||||
}
|
||||
|
||||
|
||||
@@ -137,14 +137,14 @@ class [[nodiscard]] Expected
|
||||
public:
|
||||
template <typename U>
|
||||
requires std::convertible_to<U, T> constexpr Expected(U && r)
|
||||
: Base(T(std::forward<U>(r)))
|
||||
: Base(boost::outcome_v2::success(T(std::forward<U>(r))))
|
||||
{
|
||||
}
|
||||
|
||||
template <typename U>
|
||||
requires std::convertible_to<U, E> &&
|
||||
(!std::is_reference_v<U>)constexpr Expected(Unexpected<U> e)
|
||||
: Base(E(std::move(e.value())))
|
||||
: Base(boost::outcome_v2::failure(E(std::move(e.value()))))
|
||||
{
|
||||
}
|
||||
|
||||
@@ -220,7 +220,7 @@ public:
|
||||
template <typename U>
|
||||
requires std::convertible_to<U, E> &&
|
||||
(!std::is_reference_v<U>)constexpr Expected(Unexpected<U> e)
|
||||
: Base(E(std::move(e.value())))
|
||||
: Base(boost::outcome_v2::failure(E(std::move(e.value()))))
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user