mirror of
https://github.com/XRPLF/rippled.git
synced 2025-11-20 11:05:54 +00:00
WIP support adding domainID in VaultSet
This commit is contained in:
@@ -347,6 +347,7 @@ enum TECcodes : TERUnderlyingType {
|
|||||||
tecBAD_CREDENTIALS = 193,
|
tecBAD_CREDENTIALS = 193,
|
||||||
tecWRONG_ASSET = 194,
|
tecWRONG_ASSET = 194,
|
||||||
tecLIMIT_EXCEEDED = 195,
|
tecLIMIT_EXCEEDED = 195,
|
||||||
|
tecREMOVING_PERMISSIONS = 196,
|
||||||
};
|
};
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -479,6 +479,7 @@ TRANSACTION(ttVAULT_CREATE, 64, VaultCreate, ({
|
|||||||
TRANSACTION(ttVAULT_SET, 65, VaultSet, ({
|
TRANSACTION(ttVAULT_SET, 65, VaultSet, ({
|
||||||
{sfVaultID, soeREQUIRED},
|
{sfVaultID, soeREQUIRED},
|
||||||
{sfAssetMaximum, soeOPTIONAL},
|
{sfAssetMaximum, soeOPTIONAL},
|
||||||
|
{sfDomainID, soeOPTIONAL}, // PermissionedDomainID
|
||||||
// no WithdrawalPolicy yet
|
// no WithdrawalPolicy yet
|
||||||
{sfData, soeOPTIONAL},
|
{sfData, soeOPTIONAL},
|
||||||
}))
|
}))
|
||||||
|
|||||||
@@ -119,6 +119,7 @@ transResults()
|
|||||||
MAKE_ERROR(tecBAD_CREDENTIALS, "Bad credentials."),
|
MAKE_ERROR(tecBAD_CREDENTIALS, "Bad credentials."),
|
||||||
MAKE_ERROR(tecWRONG_ASSET, "Wrong asset given."),
|
MAKE_ERROR(tecWRONG_ASSET, "Wrong asset given."),
|
||||||
MAKE_ERROR(tecLIMIT_EXCEEDED, "Limit exceeded."),
|
MAKE_ERROR(tecLIMIT_EXCEEDED, "Limit exceeded."),
|
||||||
|
MAKE_ERROR(tecREMOVING_PERMISSIONS, "Would remove permissions previously granted."),
|
||||||
|
|
||||||
MAKE_ERROR(tefALREADY, "The exact transaction was already in this ledger."),
|
MAKE_ERROR(tefALREADY, "The exact transaction was already in this ledger."),
|
||||||
MAKE_ERROR(tefBAD_ADD_AUTH, "Not authorized to add account."),
|
MAKE_ERROR(tefBAD_ADD_AUTH, "Not authorized to add account."),
|
||||||
|
|||||||
@@ -23,6 +23,7 @@
|
|||||||
#include <xrpl/protocol/Feature.h>
|
#include <xrpl/protocol/Feature.h>
|
||||||
#include <xrpl/protocol/Indexes.h>
|
#include <xrpl/protocol/Indexes.h>
|
||||||
#include <xrpl/protocol/STNumber.h>
|
#include <xrpl/protocol/STNumber.h>
|
||||||
|
#include <xrpl/protocol/TER.h>
|
||||||
#include <xrpl/protocol/TxFlags.h>
|
#include <xrpl/protocol/TxFlags.h>
|
||||||
|
|
||||||
namespace ripple {
|
namespace ripple {
|
||||||
@@ -45,16 +46,19 @@ VaultCreate::preflight(PreflightContext const& ctx)
|
|||||||
return temSTRING_TOO_LARGE;
|
return temSTRING_TOO_LARGE;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto const domain = ctx.tx[~sfDomainID];
|
if (auto const domain = ctx.tx[~sfDomainID])
|
||||||
if (domain && *domain == beast::zero)
|
{
|
||||||
return temMALFORMED;
|
if (*domain == beast::zero)
|
||||||
|
return temMALFORMED;
|
||||||
|
else if ((ctx.tx.getFlags() & tfVaultPrivate) == 0)
|
||||||
|
return temMALFORMED; // DomainID only allowed on private vaults
|
||||||
|
}
|
||||||
|
|
||||||
// This block is copied from `MPTokenIssuanceCreate::preflight`.
|
|
||||||
if (auto const metadata = ctx.tx[~sfMPTokenMetadata])
|
if (auto const metadata = ctx.tx[~sfMPTokenMetadata])
|
||||||
{
|
{
|
||||||
if (metadata->length() == 0 ||
|
if (metadata->length() == 0 ||
|
||||||
metadata->length() > maxMPTokenMetadataLength)
|
metadata->length() > maxMPTokenMetadataLength)
|
||||||
return temSTRING_TOO_LARGE;
|
return temMALFORMED;
|
||||||
}
|
}
|
||||||
|
|
||||||
return preflight2(ctx);
|
return preflight2(ctx);
|
||||||
@@ -83,8 +87,7 @@ VaultCreate::preclaim(PreclaimContext const& ctx)
|
|||||||
return tecLOCKED;
|
return tecLOCKED;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto const domain = ctx.tx[~sfDomainID];
|
if (auto const domain = ctx.tx[~sfDomainID])
|
||||||
if (domain)
|
|
||||||
{
|
{
|
||||||
auto const sleDomain =
|
auto const sleDomain =
|
||||||
ctx.view.read(keylet::permissionedDomain(*domain));
|
ctx.view.read(keylet::permissionedDomain(*domain));
|
||||||
@@ -129,7 +132,7 @@ VaultCreate::doApply()
|
|||||||
|
|
||||||
auto txFlags = tx.getFlags();
|
auto txFlags = tx.getFlags();
|
||||||
std::uint32_t mptFlags = 0;
|
std::uint32_t mptFlags = 0;
|
||||||
if (!(txFlags & tfVaultShareNonTransferable))
|
if ((txFlags & tfVaultShareNonTransferable) == 0)
|
||||||
mptFlags |= (lsfMPTCanEscrow | lsfMPTCanTrade | lsfMPTCanTransfer);
|
mptFlags |= (lsfMPTCanEscrow | lsfMPTCanTrade | lsfMPTCanTransfer);
|
||||||
if (txFlags & tfVaultPrivate)
|
if (txFlags & tfVaultPrivate)
|
||||||
mptFlags |= lsfMPTRequireAuth;
|
mptFlags |= lsfMPTRequireAuth;
|
||||||
|
|||||||
@@ -19,6 +19,7 @@
|
|||||||
|
|
||||||
#include <xrpld/app/tx/detail/VaultDeposit.h>
|
#include <xrpld/app/tx/detail/VaultDeposit.h>
|
||||||
|
|
||||||
|
#include <xrpld/app/misc/CredentialHelpers.h>
|
||||||
#include <xrpld/app/tx/detail/MPTokenAuthorize.h>
|
#include <xrpld/app/tx/detail/MPTokenAuthorize.h>
|
||||||
#include <xrpld/ledger/View.h>
|
#include <xrpld/ledger/View.h>
|
||||||
#include <xrpl/protocol/Feature.h>
|
#include <xrpl/protocol/Feature.h>
|
||||||
@@ -49,6 +50,19 @@ VaultDeposit::preclaim(PreclaimContext const& ctx)
|
|||||||
auto const vault = ctx.view.read(keylet::vault(ctx.tx[sfVaultID]));
|
auto const vault = ctx.view.read(keylet::vault(ctx.tx[sfVaultID]));
|
||||||
if (!vault)
|
if (!vault)
|
||||||
return tecOBJECT_NOT_FOUND;
|
return tecOBJECT_NOT_FOUND;
|
||||||
|
|
||||||
|
// Only the VaultDeposit transaction is subject to this permission check.
|
||||||
|
if (vault->getFlags() == tfVaultPrivate &&
|
||||||
|
ctx.tx[sfAccount] != vault->at(sfOwner))
|
||||||
|
{
|
||||||
|
if (auto const domain = vault->at(~sfVaultID))
|
||||||
|
{
|
||||||
|
if (!credentials::authorizedDomain(
|
||||||
|
ctx.view, *domain, ctx.tx[sfAccount]))
|
||||||
|
return tecNO_PERMISSION;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return tesSUCCESS;
|
return tesSUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,7 +20,9 @@
|
|||||||
#include <xrpld/app/tx/detail/VaultSet.h>
|
#include <xrpld/app/tx/detail/VaultSet.h>
|
||||||
#include <xrpld/ledger/View.h>
|
#include <xrpld/ledger/View.h>
|
||||||
#include <xrpl/protocol/Feature.h>
|
#include <xrpl/protocol/Feature.h>
|
||||||
|
#include <xrpl/protocol/Indexes.h>
|
||||||
#include <xrpl/protocol/STNumber.h>
|
#include <xrpl/protocol/STNumber.h>
|
||||||
|
#include <xrpl/protocol/TER.h>
|
||||||
#include <xrpl/protocol/TxFlags.h>
|
#include <xrpl/protocol/TxFlags.h>
|
||||||
|
|
||||||
namespace ripple {
|
namespace ripple {
|
||||||
@@ -41,12 +43,40 @@ VaultSet::preflight(PreflightContext const& ctx)
|
|||||||
return temSTRING_TOO_LARGE;
|
return temSTRING_TOO_LARGE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto const domain = ctx.tx[~sfDomainID];
|
||||||
|
if (domain && *domain == beast::zero)
|
||||||
|
return temMALFORMED;
|
||||||
|
|
||||||
return preflight2(ctx);
|
return preflight2(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
TER
|
TER
|
||||||
VaultSet::preclaim(PreclaimContext const& ctx)
|
VaultSet::preclaim(PreclaimContext const& ctx)
|
||||||
{
|
{
|
||||||
|
auto const id = ctx.tx[sfVaultID];
|
||||||
|
auto const sle = ctx.view.read(keylet::vault(id));
|
||||||
|
if (!sle)
|
||||||
|
return tecOBJECT_NOT_FOUND;
|
||||||
|
|
||||||
|
// Assert that submitter is the Owner.
|
||||||
|
if (ctx.tx[sfAccount] != sle->at(sfOwner))
|
||||||
|
return tecNO_PERMISSION;
|
||||||
|
|
||||||
|
// We can only set domain if private flag was originally set and
|
||||||
|
// domain was not set
|
||||||
|
if (auto const domain = ctx.tx[~sfDomainID])
|
||||||
|
{
|
||||||
|
if ((sle->getFlags() & tfVaultPrivate) == 0)
|
||||||
|
return tecREMOVING_PERMISSIONS;
|
||||||
|
if (auto const oldDomain = sle->at(~sfDomainID))
|
||||||
|
{
|
||||||
|
if (*oldDomain != *domain)
|
||||||
|
return tecREMOVING_PERMISSIONS;
|
||||||
|
// else no change
|
||||||
|
}
|
||||||
|
// else domain wasn't set previously, we allow setting it now
|
||||||
|
}
|
||||||
|
|
||||||
return tesSUCCESS;
|
return tesSUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -58,17 +88,12 @@ VaultSet::doApply()
|
|||||||
// we can consider downgrading them to `tef` or `tem`.
|
// we can consider downgrading them to `tef` or `tem`.
|
||||||
|
|
||||||
auto const& tx = ctx_.tx;
|
auto const& tx = ctx_.tx;
|
||||||
auto const& owner = account_;
|
|
||||||
|
|
||||||
// Update existing object.
|
// Update existing object.
|
||||||
auto vault = view().peek({ltVAULT, tx[sfVaultID]});
|
auto vault = view().peek({ltVAULT, tx[sfVaultID]});
|
||||||
if (!vault)
|
if (!vault)
|
||||||
return tecOBJECT_NOT_FOUND;
|
return tecOBJECT_NOT_FOUND;
|
||||||
|
|
||||||
// Assert that submitter is the Owner.
|
|
||||||
if (owner != vault->at(sfOwner))
|
|
||||||
return tecNO_PERMISSION;
|
|
||||||
|
|
||||||
// Update mutable flags and fields if given.
|
// Update mutable flags and fields if given.
|
||||||
if (tx.isFieldPresent(sfData))
|
if (tx.isFieldPresent(sfData))
|
||||||
vault->at(sfData) = tx[sfData];
|
vault->at(sfData) = tx[sfData];
|
||||||
@@ -78,6 +103,17 @@ VaultSet::doApply()
|
|||||||
return tecLIMIT_EXCEEDED;
|
return tecLIMIT_EXCEEDED;
|
||||||
vault->at(sfAssetMaximum) = tx[sfAssetMaximum];
|
vault->at(sfAssetMaximum) = tx[sfAssetMaximum];
|
||||||
}
|
}
|
||||||
|
if (tx.isFieldPresent(sfDomainID))
|
||||||
|
{
|
||||||
|
// In VaultSet::preclaim we enforce that either DomainID wasn't present
|
||||||
|
// in the vault, or was the same value as the one supplied. We also
|
||||||
|
// enforce that tfVaultPrivate must have been set in the vault. By
|
||||||
|
// adding DomainID to an existing private vault, we are allowing
|
||||||
|
// permissioned users to interract with a vault which was previously
|
||||||
|
// accessible to its owner only. We currently do not support making
|
||||||
|
// such a vault public (i.e. removal of tfVaultPrivate flag)
|
||||||
|
vault->setFieldH256(sfDomainID, tx.getFieldH256(sfDomainID));
|
||||||
|
}
|
||||||
|
|
||||||
view().update(vault);
|
view().update(vault);
|
||||||
|
|
||||||
|
|||||||
@@ -19,9 +19,12 @@
|
|||||||
|
|
||||||
#include <xrpld/app/tx/detail/VaultWithdraw.h>
|
#include <xrpld/app/tx/detail/VaultWithdraw.h>
|
||||||
|
|
||||||
|
#include <xrpld/app/misc/CredentialHelpers.h>
|
||||||
#include <xrpld/ledger/View.h>
|
#include <xrpld/ledger/View.h>
|
||||||
#include <xrpl/protocol/Feature.h>
|
#include <xrpl/protocol/Feature.h>
|
||||||
|
#include <xrpl/protocol/SField.h>
|
||||||
#include <xrpl/protocol/STNumber.h>
|
#include <xrpl/protocol/STNumber.h>
|
||||||
|
#include <xrpl/protocol/TER.h>
|
||||||
#include <xrpl/protocol/TxFlags.h>
|
#include <xrpl/protocol/TxFlags.h>
|
||||||
|
|
||||||
namespace ripple {
|
namespace ripple {
|
||||||
@@ -47,6 +50,7 @@ VaultWithdraw::preclaim(PreclaimContext const& ctx)
|
|||||||
auto const vault = ctx.view.read(keylet::vault(ctx.tx[sfVaultID]));
|
auto const vault = ctx.view.read(keylet::vault(ctx.tx[sfVaultID]));
|
||||||
if (!vault)
|
if (!vault)
|
||||||
return tecOBJECT_NOT_FOUND;
|
return tecOBJECT_NOT_FOUND;
|
||||||
|
|
||||||
return tesSUCCESS;
|
return tesSUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user