Compare commits

..

30 Commits

Author SHA1 Message Date
Richard Holland
e5b5efcc87 Merge branch 'dev' into coverage 2026-04-28 11:34:19 +10:00
tequ
a77e6ee7fd use clang-format-18 on check-genesis-hooks workflow 2026-04-28 11:30:54 +10:00
tequ
67034cda77 Update build_xahau.h.sh 2026-04-28 11:30:54 +10:00
tequ
aa1e4d38d3 update workflow 2026-04-28 11:30:54 +10:00
tequ
d4417d3461 remove workflow cache 2026-04-28 11:30:54 +10:00
tequ
6f6e56952e Remove path filters for Genesis Hooks in GitHub Actions workflow 2026-04-28 11:30:54 +10:00
tequ
e673cb5b80 Update GitHub Actions workflow to install binaryen version 100 directly from GitHub Releases 2026-04-28 11:30:54 +10:00
tequ
cfb1b36bae Add wasm-opt to required tools and enforce version check 2026-04-28 11:30:54 +10:00
tequ
628c942a98 update xahau.h using binaryen version=100 2026-04-28 11:30:54 +10:00
tequ
4cb64497e9 revert xahau.h 2026-04-28 11:30:54 +10:00
tequ
96065296ab revert arm 2026-04-28 11:30:54 +10:00
tequ
6ab87ed696 wasmcc version 2026-04-28 11:30:54 +10:00
tequ
1b7c70d3ba try arm 2026-04-28 11:30:54 +10:00
tequ
ba2b188aaf fix 2026-04-28 11:30:54 +10:00
tequ
7a78672983 fix 2026-04-28 11:30:54 +10:00
tequ
14de6cc76d fix wasienv script 2026-04-28 11:30:54 +10:00
tequ
13f4313f64 restore headers for xahau.h and build, check in github actions 2026-04-28 11:30:54 +10:00
tequ
2244fae464 Merge branch 'dev' into coverage 2026-04-24 14:12:11 +09:00
tequ
8d0e6eedea Merge branch 'dev' into coverage 2026-03-06 16:29:37 +09:00
tequ
59580e2b28 Merge branch 'dev' into coverage 2026-02-24 17:09:52 +09:00
RichardAH
866119cf80 Merge branch 'dev' into coverage 2026-02-18 09:34:45 +10:00
Niq Dudfield
498f63651d Merge branch 'dev' into coverage 2026-02-17 11:14:33 +07:00
Niq Dudfield
4c5c9b14b7 fix: ci build action and coverage workflow fixes (#682)
- move --target before ${VERBOSE_FLAG} so [ci-ga-cmake-verbose] doesn't
  swallow the target argument
- add stdlib: default option for GCC entries (GCC doesn't support -stdlib flag)
- pass stdlib explicitly to coverage build step
- remove dead CMAKE_BUILD_PARALLEL_LEVEL export (doesn't persist across steps,
  and build step already uses --parallel)
- remove duplicate ccache config block
2026-02-17 10:22:59 +09:00
tequ
689f3c07c9 Merge branch 'dev' into coverage 2026-02-16 13:36:42 +09:00
tequ
407cc83241 Merge branch 'dev' into coverage 2026-01-28 14:12:07 +09:00
tequ
97deee10ca Merge branch 'dev' into coverage 2026-01-27 21:30:10 +09:00
tequ
0c8de81657 Merge branch 'dev' into coverage 2026-01-05 19:49:26 +09:00
tequ
cb40a9d726 fix cmake-target 2025-12-24 22:03:45 +09:00
Bronek Kozicki
3d9f8aa7a9 test: improve code coverage reporting (#4849)
* Speed up the generation of coverage reports by using multiple cores.

* Add codecov step to coverage workflow.
2025-12-24 22:03:23 +09:00
tequ
d7fd2adb34 Add coverage workflow 2025-12-24 17:10:46 +09:00
20 changed files with 108 additions and 1804 deletions

View File

@@ -230,9 +230,6 @@ jobs:
build: build:
needs: matrix-setup needs: matrix-setup
runs-on: ${{ fromJSON(matrix.runs_on) }} runs-on: ${{ fromJSON(matrix.runs_on) }}
permissions:
id-token: write
contents: read
container: container:
image: ubuntu:24.04 image: ubuntu:24.04
volumes: volumes:
@@ -335,7 +332,7 @@ jobs:
# Install gcovr for coverage jobs # Install gcovr for coverage jobs
if [ "${{ matrix.job_type }}" = "coverage" ]; then if [ "${{ matrix.job_type }}" = "coverage" ]; then
pipx install "gcovr>=7,<9" pipx install "gcovr>=7,<9"
apt-get install -y curl lcov apt-get install -y lcov
fi fi
- name: Check environment - name: Check environment
@@ -410,8 +407,7 @@ jobs:
cache_version: ${{ env.CACHE_VERSION }} cache_version: ${{ env.CACHE_VERSION }}
main_branch: ${{ env.MAIN_BRANCH_NAME }} main_branch: ${{ env.MAIN_BRANCH_NAME }}
stdlib: ${{ matrix.stdlib }} stdlib: ${{ matrix.stdlib }}
# Coverage builds are slower due to instrumentation; use fewer parallel jobs to avoid flakiness cmake-args: '-Dcoverage=ON -Dcoverage_format=xml -DCODE_COVERAGE_VERBOSE=ON -DCMAKE_CXX_FLAGS="-O0" -DCMAKE_C_FLAGS="-O0"'
cmake-args: '-Dcoverage=ON -Dcoverage_format=xml -Dcoverage_test_parallelism=$(($(nproc)/2)) -DCODE_COVERAGE_VERBOSE=ON -DCMAKE_CXX_FLAGS="-O0" -DCMAKE_C_FLAGS="-O0"'
cmake-target: 'coverage' cmake-target: 'coverage'
ccache_max_size: '100G' ccache_max_size: '100G'
@@ -456,11 +452,15 @@ jobs:
- name: Upload coverage report - name: Upload coverage report
if: matrix.job_type == 'coverage' if: matrix.job_type == 'coverage'
uses: codecov/codecov-action@v5 uses: wandalen/wretry.action/main@v3
with: with:
files: coverage.xml action: codecov/codecov-action@v4.3.0
fail_ci_if_error: true with: |
disable_search: true files: coverage.xml
verbose: true fail_ci_if_error: true
plugins: noop disable_search: true
use_oidc: true verbose: true
plugin: noop
token: ${{ secrets.CODECOV_TOKEN }}
attempt_limit: 5
attempt_delay: 210000 # in milliseconds

View File

@@ -80,7 +80,7 @@ namespace detail {
// Feature.cpp. Because it's only used to reserve storage, and determine how // Feature.cpp. Because it's only used to reserve storage, and determine how
// large to make the FeatureBitset, it MAY be larger. It MUST NOT be less than // large to make the FeatureBitset, it MAY be larger. It MUST NOT be less than
// the actual number of amendments. A LogicError on startup will verify this. // the actual number of amendments. A LogicError on startup will verify this.
static constexpr std::size_t numFeatures = 114; static constexpr std::size_t numFeatures = 113;
/** Amendments that this server supports and the default voting behavior. /** Amendments that this server supports and the default voting behavior.
Whether they are enabled depends on the Rules defined in the validated Whether they are enabled depends on the Rules defined in the validated

View File

@@ -31,7 +31,6 @@
// If you add an amendment here, then do not forget to increment `numFeatures` // If you add an amendment here, then do not forget to increment `numFeatures`
// in include/xrpl/protocol/Feature.h. // in include/xrpl/protocol/Feature.h.
XRPL_FIX (ImportIssuer, Supported::yes, VoteBehavior::DefaultYes)
XRPL_FEATURE(HookAPISerializedType240, Supported::yes, VoteBehavior::DefaultNo) XRPL_FEATURE(HookAPISerializedType240, Supported::yes, VoteBehavior::DefaultNo)
XRPL_FEATURE(PermissionedDomains, Supported::no, VoteBehavior::DefaultNo) XRPL_FEATURE(PermissionedDomains, Supported::no, VoteBehavior::DefaultNo)
XRPL_FEATURE(DynamicNFT, Supported::no, VoteBehavior::DefaultNo) XRPL_FEATURE(DynamicNFT, Supported::no, VoteBehavior::DefaultNo)

View File

@@ -18,7 +18,6 @@
//============================================================================== //==============================================================================
#include <test/jtx.h> #include <test/jtx.h>
#include <test/jtx/AMM.h>
#include <xrpld/app/ledger/LedgerMaster.h> #include <xrpld/app/ledger/LedgerMaster.h>
#include <xrpl/protocol/Feature.h> #include <xrpl/protocol/Feature.h>
#include <xrpl/protocol/jss.h> #include <xrpl/protocol/jss.h>
@@ -301,28 +300,6 @@ struct ClaimReward_test : public beast::unit_test::suite
env(tx, reward::issuer(issuer), ter(tecNO_ISSUER)); env(tx, reward::issuer(issuer), ter(tecNO_ISSUER));
env.close(); env.close();
} }
// tecNO_PERMISSION
// issuer is an AMM account
{
test::jtx::Env env{*this, network::makeNetworkConfig(21337)};
auto const alice = Account("alice");
auto const issuer = Account("issuer");
auto const USD = issuer["USD"];
env.fund(XRP(1000), alice, issuer);
env.close();
AMM amm(env, issuer, XRP(100), USD(100));
BEAST_EXPECT(amm.ammExists());
env(reward::claim(alice),
reward::issuer(amm.ammAccount()),
ter(tecNO_PERMISSION));
env.close();
}
} }
void void

View File

@@ -19,7 +19,6 @@
#include <test/app/Import_json.h> #include <test/app/Import_json.h>
#include <test/jtx.h> #include <test/jtx.h>
#include <test/jtx/AMM.h>
#include <xrpld/app/ledger/LedgerMaster.h> #include <xrpld/app/ledger/LedgerMaster.h>
#include <xrpld/app/misc/AmendmentTable.h> #include <xrpld/app/misc/AmendmentTable.h>
#include <xrpld/app/misc/HashRouter.h> #include <xrpld/app/misc/HashRouter.h>
@@ -2636,77 +2635,6 @@ class Import_test : public beast::unit_test::suite
ter(temDISABLED)); ter(temDISABLED));
} }
// tecNO_ISSUER, tecNO_PERMISSION
// issuer not found, issuer is an AMM account
{
auto const alice = Account("alice");
auto const bob = Account("bob");
auto const issuer = Account("issuer");
auto const USD = issuer["USD"];
for (bool const withFixImportIssuer : {true, false})
{
auto const amend =
withFixImportIssuer ? features : features - fixImportIssuer;
test::jtx::Env env{
*this, network::makeNetworkVLConfig(21337, keys), amend};
env.fund(XRP(1000), alice, issuer);
env.close();
// burn 10'000 xrp
auto const master = Account("masterpassphrase");
env(noop(master), fee(10'000'000'000), ter(tesSUCCESS));
env.close();
env(import::import(
alice, import::loadXpop(ImportTCAccountSet::w_seed)),
import::issuer(bob),
fee(100'000'000),
withFixImportIssuer ? ter(tecNO_ISSUER) : ter(tesSUCCESS));
env.close();
}
for (bool const withFixImportIssuer : {true, false})
{
auto const amend =
withFixImportIssuer ? features : features - fixImportIssuer;
test::jtx::Env env{
*this, network::makeNetworkVLConfig(21337, keys), amend};
env.fund(XRP(1000), alice, issuer);
env.close();
// burn 10'000 xrp
auto const master = Account("masterpassphrase");
env(noop(master), fee(10'000'000'000), ter(tesSUCCESS));
env.close();
AMM amm(env, issuer, XRP(100), USD(100));
BEAST_EXPECT(amm.ammExists());
env(import::import(
alice, import::loadXpop(ImportTCAccountSet::w_seed)),
import::issuer(amm.ammAccount()),
fee(100'000'000),
withFixImportIssuer ? ter(tecNO_PERMISSION)
: ter(tesSUCCESS));
env.close();
}
// env.enableFeature(fixImportIssuer);
// env.close();
// env(import::import(
// carol, import::loadXpop(ImportTCAccountSet::w_seed)),
// import::issuer(bob),
// ter(tecNO_ISSUER));
// env.close();
// env(import::import(
// dave, import::loadXpop(ImportTCAccountSet::w_seed)),
// import::issuer(amm.ammAccount()),
// // fee(100'000'000),
// ter(tecNO_PERMISSION));
// env.close();
}
// tefINTERNAL // tefINTERNAL
// during preclaim could not parse xpop, bailing. // during preclaim could not parse xpop, bailing.
{ {

View File

@@ -18,7 +18,6 @@
//============================================================================== //==============================================================================
#include <test/jtx.h> #include <test/jtx.h>
#include <test/jtx/AMM.h>
#include <xrpl/protocol/jss.h> #include <xrpl/protocol/jss.h>
namespace ripple { namespace ripple {
@@ -169,27 +168,6 @@ class Invoke_test : public beast::unit_test::suite
fee(feeDrops), fee(feeDrops),
ter(tecNO_TARGET)); ter(tecNO_TARGET));
} }
// tecNO_PERMISSION
// issuer is an AMM account
{
test::jtx::Env env{*this, network::makeNetworkConfig(21337)};
auto const alice = Account("alice");
auto const issuer = Account("issuer");
auto const USD = issuer["USD"];
env.fund(XRP(1000), alice, issuer);
env.close();
AMM amm(env, issuer, XRP(100), USD(100));
BEAST_EXPECT(amm.ammExists());
env(invoke::invoke(alice),
invoke::dest(amm.ammAccount()),
ter(tecNO_PERMISSION));
env.close();
}
} }
void void

View File

@@ -18,7 +18,6 @@
//============================================================================== //==============================================================================
#include <test/jtx.h> #include <test/jtx.h>
#include <test/jtx/AMM.h>
#include <xrpld/core/ConfigSections.h> #include <xrpld/core/ConfigSections.h>
#include <xrpld/ledger/Dir.h> #include <xrpld/ledger/Dir.h>
#include <xrpl/basics/chrono.h> #include <xrpl/basics/chrono.h>
@@ -411,21 +410,6 @@ struct Remit_test : public beast::unit_test::suite
env.close(); env.close();
} }
// tecNO_PERMISSION - inform account is an AMM
{
Env env{*this, features};
env.fund(XRP(1000), gw, alice, bob);
env.close();
AMM amm(env, gw, XRP(100), USD(100));
BEAST_EXPECT(amm.ammExists());
auto tx = remit::remit(alice, bob);
tx[sfInform.jsonName] = to_string(amm.ammAccount());
env(tx, alice, ter(tecNO_PERMISSION));
env.close();
}
// tecNO_PERMISSION - lsfDisallowIncomingRemit // tecNO_PERMISSION - lsfDisallowIncomingRemit
// DA: see testAllowIncoming // DA: see testAllowIncoming

File diff suppressed because it is too large Load Diff

View File

@@ -140,7 +140,8 @@ struct XahauGenesis_test : public beast::unit_test::suite
bool skipTests = false, bool skipTests = false,
bool const testFlag = false, bool const testFlag = false,
bool const badNetID = false, bool const badNetID = false,
uint32_t const expectedOwnerCount = 14 /** case for testFlag=false */) uint32_t const expectedOwnerCount =
10 /** testFlag ? 10 : 14 (default) */)
{ {
using namespace jtx; using namespace jtx;
@@ -249,7 +250,9 @@ struct XahauGenesis_test : public beast::unit_test::suite
genesisAccRoot->getFieldAmount(sfBalance) == genesisAccRoot->getFieldAmount(sfBalance) ==
XahauGenesis::GenesisAmount); XahauGenesis::GenesisAmount);
BEAST_EXPECT( BEAST_EXPECT(
genesisAccRoot->getFieldU32(sfOwnerCount) == expectedOwnerCount); genesisAccRoot->getFieldU32(sfOwnerCount) == !testFlag
? expectedOwnerCount
: 14);
// ensure the definitions are correctly set // ensure the definitions are correctly set
{ {
@@ -592,8 +595,7 @@ struct XahauGenesis_test : public beast::unit_test::suite
false, false,
true, true,
{}, {},
2 /*Hook objects *2 */ + 3 /* IRR,IRD,IMC HookStates */ + 3 /* IRR,IRD,IMC */ + members.size() + tables.size());
members.size());
env.close(); env.close();
env.close(); env.close();
@@ -2325,7 +2327,7 @@ struct XahauGenesis_test : public beast::unit_test::suite
{ {
BEAST_EXPECT( BEAST_EXPECT(
root->getFieldU32(sfOwnerCount) == root->getFieldU32(sfOwnerCount) ==
(mc * 2 + 2 + paramsCount)); mc * 2 + 2 + paramsCount);
BEAST_EXPECT(root->getFieldU32(sfFlags) & lsfDisableMaster); BEAST_EXPECT(root->getFieldU32(sfFlags) & lsfDisableMaster);
BEAST_EXPECT(root->getAccountID(sfRegularKey) == noAccount()); BEAST_EXPECT(root->getAccountID(sfRegularKey) == noAccount());
} }

View File

@@ -44,7 +44,7 @@ import(jtx::Account const& account, Json::Value const& xpop)
void void
issuer::operator()(Env& env, JTx& jt) const issuer::operator()(Env& env, JTx& jt) const
{ {
jt.jv[sfIssuer.jsonName] = to_string(issuer_); jt.jv[sfIssuer.jsonName] = issuer_.human();
} }
Json::Value Json::Value

View File

@@ -66,7 +66,7 @@ blob::operator()(Env& env, JTx& jt) const
void void
dest::operator()(Env& env, JTx& jt) const dest::operator()(Env& env, JTx& jt) const
{ {
jt.jv[sfDestination.jsonName] = to_string(dest_); jt.jv[sfDestination.jsonName] = dest_.human();
} }
} // namespace invoke } // namespace invoke

View File

@@ -29,24 +29,18 @@ namespace reward {
// Claim a reward. // Claim a reward.
Json::Value Json::Value
claim(jtx::Account const& account) claim(jtx::Account const& account)
{
return claim(account.id());
}
Json::Value
claim(AccountID const& account)
{ {
using namespace jtx; using namespace jtx;
Json::Value jv; Json::Value jv;
jv[jss::TransactionType] = jss::ClaimReward; jv[jss::TransactionType] = jss::ClaimReward;
jv[jss::Account] = to_string(account); jv[jss::Account] = account.human();
return jv; return jv;
} }
void void
issuer::operator()(Env& env, JTx& jt) const issuer::operator()(Env& env, JTx& jt) const
{ {
jt.jv[sfIssuer.jsonName] = to_string(issuer_); jt.jv[sfIssuer.jsonName] = issuer_.human();
} }
} // namespace reward } // namespace reward

View File

@@ -37,10 +37,10 @@ import(jtx::Account const& account, Json::Value const& xpop);
class issuer class issuer
{ {
private: private:
AccountID issuer_; jtx::Account issuer_;
public: public:
explicit issuer(AccountID const& issuer) : issuer_(issuer) explicit issuer(jtx::Account const& issuer) : issuer_(issuer)
{ {
} }

View File

@@ -58,10 +58,10 @@ public:
class dest class dest
{ {
private: private:
AccountID dest_; jtx::Account dest_;
public: public:
explicit dest(AccountID const& dest) : dest_(dest) explicit dest(jtx::Account const& dest) : dest_(dest)
{ {
} }

View File

@@ -34,24 +34,17 @@ namespace reward {
Json::Value Json::Value
claim(jtx::Account const& account); claim(jtx::Account const& account);
Json::Value
claim(AccountID const& account);
/** Sets the optional Issuer on a JTx. */ /** Sets the optional Issuer on a JTx. */
class issuer class issuer
{ {
private: private:
AccountID issuer_; jtx::Account issuer_;
public: public:
explicit issuer(jtx::Account const& issuer) : issuer_(issuer) explicit issuer(jtx::Account const& issuer) : issuer_(issuer)
{ {
} }
explicit issuer(AccountID const& issuer) : issuer_(issuer)
{
}
void void
operator()(Env&, JTx& jtx) const; operator()(Env&, JTx& jtx) const;
}; };

View File

@@ -301,14 +301,18 @@ getTransactionalStakeHolders(STTx const& tx, ReadView const& rv)
bool issuerCanRollback = nft::getFlags(nid) & tfStrongTSH; bool issuerCanRollback = nft::getFlags(nid) & tfStrongTSH;
ADD_TSH(issuer, issuerCanRollback); ADD_TSH(issuer, issuerCanRollback);
for (auto const& offer : {bo, so}) if (bo)
{ {
if (offer) ADD_TSH(bo->getAccountID(sfOwner), tshSTRONG);
{ if (bo->isFieldPresent(sfDestination))
ADD_TSH(offer->getAccountID(sfOwner), tshSTRONG); ADD_TSH(bo->getAccountID(sfDestination), tshSTRONG);
if (offer->isFieldPresent(sfDestination)) }
ADD_TSH(offer->getAccountID(sfDestination), tshSTRONG);
} if (so)
{
ADD_TSH(so->getAccountID(sfOwner), tshSTRONG);
if (so->isFieldPresent(sfDestination))
ADD_TSH(so->getAccountID(sfDestination), tshSTRONG);
} }
break; break;
@@ -547,8 +551,7 @@ getTransactionalStakeHolders(STTx const& tx, ReadView const& rv)
break; break;
} }
case ttLEDGER_STATE_FIX: { case ttLEDGER_STATE_FIX: {
if (tx.isFieldPresent(sfOwner)) // TODO: Implement if needed
ADD_TSH(tx.getAccountID(sfOwner), tshWEAK);
break; break;
} }
case ttMPTOKEN_ISSUANCE_CREATE: case ttMPTOKEN_ISSUANCE_CREATE:
@@ -2727,23 +2730,26 @@ DEFINE_HOOK_FUNCTION(
return serialize_keylet(kl, memory, write_ptr, write_len); return serialize_keylet(kl, memory, write_ptr, write_len);
} }
// These keylet types are not yet implemented. Their
// corresponding amendments are not yet supported on the
// network. Each case needs a full implementation (see
// above cases for reference) before its amendment can be
// enabled.
// featureXChainBridge
case keylet_code::BRIDGE: case keylet_code::BRIDGE:
case keylet_code::XCHAIN_OWNED_CLAIM_ID: case keylet_code::XCHAIN_OWNED_CLAIM_ID:
case keylet_code::XCHAIN_OWNED_CREATE_ACCOUNT_CLAIM_ID: case keylet_code::XCHAIN_OWNED_CREATE_ACCOUNT_CLAIM_ID: {
// featureMPTokensV1 if (!applyCtx.view().rules().enabled(featureXChainBridge))
return INVALID_ARGUMENT;
}
case keylet_code::MPTOKEN_ISSUANCE: case keylet_code::MPTOKEN_ISSUANCE:
case keylet_code::MPTOKEN: case keylet_code::MPTOKEN: {
// featureCredentials if (!applyCtx.view().rules().enabled(featureMPTokensV1))
case keylet_code::CREDENTIAL: return INVALID_ARGUMENT;
// featurePermissionedDomains }
case keylet_code::PERMISSIONED_DOMAIN: case keylet_code::CREDENTIAL: {
return INVALID_ARGUMENT; if (!applyCtx.view().rules().enabled(featureCredentials))
return INVALID_ARGUMENT;
}
case keylet_code::PERMISSIONED_DOMAIN: {
if (!applyCtx.view().rules().enabled(
featurePermissionedDomains))
return INVALID_ARGUMENT;
}
} }
} }
catch (std::exception& e) catch (std::exception& e)

View File

@@ -82,15 +82,8 @@ ClaimReward::preclaim(PreclaimContext const& ctx)
if ((issuer && isOptOut) || (!issuer && !isOptOut)) if ((issuer && isOptOut) || (!issuer && !isOptOut))
return temMALFORMED; return temMALFORMED;
if (issuer) if (issuer && !ctx.view.exists(keylet::account(*issuer)))
{ return tecNO_ISSUER;
auto const sleIssuer = ctx.view.read(keylet::account(*issuer));
if (!sleIssuer)
return tecNO_ISSUER;
if (sleIssuer->isFieldPresent(sfAMMID))
return tecNO_PERMISSION;
}
return tesSUCCESS; return tesSUCCESS;
} }

View File

@@ -870,17 +870,6 @@ Import::preclaim(PreclaimContext const& ctx)
if (!ctx.tx.isFieldPresent(sfBlob)) if (!ctx.tx.isFieldPresent(sfBlob))
return tefINTERNAL; return tefINTERNAL;
if (ctx.tx.isFieldPresent(sfIssuer) &&
ctx.view.rules().enabled(fixImportIssuer))
{
auto const sleIssuer = ctx.view.read(keylet::account(ctx.tx[sfIssuer]));
if (!sleIssuer)
return tecNO_ISSUER;
if (sleIssuer->isFieldPresent(sfAMMID))
return tecNO_PERMISSION;
}
// parse blob as json // parse blob as json
auto const xpop = syntaxCheckXPOP(ctx.tx.getFieldVL(sfBlob), ctx.j); auto const xpop = syntaxCheckXPOP(ctx.tx.getFieldVL(sfBlob), ctx.j);

View File

@@ -64,13 +64,8 @@ Invoke::preclaim(PreclaimContext const& ctx)
if (ctx.tx.isFieldPresent(sfDestination)) if (ctx.tx.isFieldPresent(sfDestination))
{ {
auto const sleDest = if (!ctx.view.exists(keylet::account(ctx.tx[sfDestination])))
ctx.view.read(keylet::account(ctx.tx[sfDestination]));
if (!sleDest)
return tecNO_TARGET; return tecNO_TARGET;
if (sleDest->isFieldPresent(sfAMMID))
return tecNO_PERMISSION;
} }
return tesSUCCESS; return tesSUCCESS;

View File

@@ -256,18 +256,11 @@ Remit::doApply()
if (ctx_.tx.isFieldPresent(sfInform)) if (ctx_.tx.isFieldPresent(sfInform))
{ {
auto const informAcc = ctx_.tx.getAccountID(sfInform); auto const informAcc = ctx_.tx.getAccountID(sfInform);
auto const sleInformAcc = sb.read(keylet::account(informAcc)); if (!sb.exists(keylet::account(informAcc)))
if (!sleInformAcc)
{ {
JLOG(j.warn()) << "Remit: sfInform account does not exist."; JLOG(j.warn()) << "Remit: sfInform account does not exist.";
return tecNO_TARGET; return tecNO_TARGET;
} }
if (sleInformAcc->isFieldPresent(sfAMMID))
{
JLOG(j.warn()) << "Remit: sfInform account is an AMM.";
return tecNO_PERMISSION;
}
} }
XRPAmount const accountReserve{sb.fees().accountReserve(0)}; XRPAmount const accountReserve{sb.fees().accountReserve(0)};