mirror of
https://github.com/Xahau/xahaud.git
synced 2025-11-29 06:55:49 +00:00
attestation consensus stuff. compiling not tested
This commit is contained in:
@@ -71,6 +71,7 @@ Attest::preclaim(PreclaimContext const& ctx)
|
||||
else if (!exists && isDelete)
|
||||
return tecNO_ENTRY;
|
||||
|
||||
|
||||
return tesSUCCESS;
|
||||
}
|
||||
|
||||
@@ -83,6 +84,19 @@ Attest::doApply()
|
||||
if (!sle)
|
||||
return tefINTERNAL;
|
||||
|
||||
// check for sufficient reserves
|
||||
{
|
||||
STAmount const reserve{
|
||||
view().fees().accountReserve(sle->getFieldU32(sfOwnerCount) + 1)};
|
||||
|
||||
STAmount const afterFee =
|
||||
mPriorBalance - ctx_.tx.getFieldAmount(sfFee).xrp();
|
||||
|
||||
if (afterFee > mPriorBalance || afterFee < reserve)
|
||||
return tecINSUFFICIENT_RESERVE;
|
||||
}
|
||||
|
||||
|
||||
Keylet kl =
|
||||
keylet::attestation(account_, ctx_.tx.getFieldH256(sfAttestedTxnID));
|
||||
|
||||
|
||||
@@ -85,6 +85,41 @@ preflight0(PreflightContext const& ctx)
|
||||
return temINVALID;
|
||||
}
|
||||
|
||||
// don't allow attestations unless enabled
|
||||
if (ctx.tx.isFieldPresent(sfAttesters))
|
||||
{
|
||||
if (!ctx.rules.enabled(featureAttestations))
|
||||
return temDISABLED;
|
||||
|
||||
// make sure they can't spam millions of attesters
|
||||
auto const& attesters = ctx.tx.getFieldArray(sfAttesters);
|
||||
if (attesters.empty() || attesters.size() > 32)
|
||||
{
|
||||
JLOG(ctx.j.warn())
|
||||
<< "applyTransaction: attesters array too big (max 32) or empty.";
|
||||
return temMALFORMED;
|
||||
}
|
||||
|
||||
// sanity check entries
|
||||
std::set<AccountID> used;
|
||||
for (auto const& attester: attesters)
|
||||
{
|
||||
if (attester.getFName() != sfAttesterEntry)
|
||||
{
|
||||
JLOG(ctx.j.warn())
|
||||
<< "applyTransaction: attesters array contained non AttesterEntry object.";
|
||||
return temMALFORMED;
|
||||
}
|
||||
|
||||
if (used.find(attester.getAccountID(sfAccount)) != used.end())
|
||||
{
|
||||
JLOG(ctx.j.warn())
|
||||
<< "applyTransaction: attesters array contained duplicate attester ID.";
|
||||
return temMALFORMED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return tesSUCCESS;
|
||||
}
|
||||
|
||||
@@ -1928,6 +1963,54 @@ Transactor::operator()()
|
||||
}
|
||||
}
|
||||
|
||||
if (applied && ctx_.tx.isFieldPresent(sfAttesters) && view().rules().enabled(featureAttestations))
|
||||
{
|
||||
// delete used attestation objects
|
||||
|
||||
auto const& attesters = ctx_.tx.getFieldArray(sfAttesters);
|
||||
auto const txid = ctx_.tx.getTransactionID();
|
||||
|
||||
auto const& j = ctx_.app.journal("View");
|
||||
|
||||
for (auto const& attester : attesters)
|
||||
{
|
||||
Keylet kl = keylet::attestation(attester.getAccountID(sfAccount), txid);
|
||||
if (!view().exists(kl))
|
||||
{
|
||||
JLOG(j.warn())
|
||||
<< "Transactor: Warning!!! Attestation does not exist at end of attested txn "
|
||||
<< txid;
|
||||
continue;
|
||||
}
|
||||
|
||||
// remove from dir
|
||||
auto sleA = view().peek(kl);
|
||||
|
||||
AccountID owner = sleA->getAccountID(sfOwner);
|
||||
auto sle = view().peek(keylet::account(owner));
|
||||
|
||||
if (!sle)
|
||||
{
|
||||
JLOG(j.warn())
|
||||
<< "Transactor: Warning!!! Attester account does not exist at the end of attested txn "
|
||||
<< txid;
|
||||
continue;
|
||||
}
|
||||
|
||||
auto const page = (*sleA)[sfOwnerNode];
|
||||
if (!view().dirRemove(
|
||||
keylet::ownerDir(owner), page, kl.key, true))
|
||||
{
|
||||
JLOG(j.warn())
|
||||
<< "Could not remove Attestation from owner directory";
|
||||
continue;
|
||||
}
|
||||
|
||||
view().erase(sleA);
|
||||
adjustOwnerCount(view(), sle, -1, j);
|
||||
}
|
||||
}
|
||||
|
||||
// Post-application (Weak TSH/AAW) Hooks are executed here.
|
||||
// These TSH do not have the ability to rollback.
|
||||
// The callback, if any, is also executed here.
|
||||
|
||||
@@ -160,6 +160,20 @@ public:
|
||||
{
|
||||
// Most transactors do nothing
|
||||
// after checkSeq/Fee/Sign.
|
||||
|
||||
if (ctx.tx.isFieldPresent(sfAttesters) && ctx.view.rules().enabled(featureAttestations))
|
||||
{
|
||||
// check if the required attestations are present on ledger
|
||||
auto const& attesters = ctx.tx.getFieldArray(sfAttesters);
|
||||
|
||||
auto const txid = ctx.tx.getTransactionID();
|
||||
|
||||
// each required attestation must exist on the ledger to allow the txn through
|
||||
// otherwise it gets marked retry
|
||||
for (auto const& attester : attesters)
|
||||
if (!ctx.view.exists(keylet::attestation(attester.getAccountID(sfAccount), txid)))
|
||||
return terRETRY;
|
||||
}
|
||||
return tesSUCCESS;
|
||||
}
|
||||
/////////////////////////////////////////////////////
|
||||
|
||||
@@ -591,6 +591,7 @@ extern SField const sfHookGrant;
|
||||
extern SField const sfActiveValidator;
|
||||
extern SField const sfImportVLKey;
|
||||
extern SField const sfHookEmission;
|
||||
extern SField const sfAttesterEntry;
|
||||
|
||||
// array of objects (common)
|
||||
// ARRAY/1 is reserved for end of array
|
||||
@@ -618,6 +619,7 @@ extern SField const sfGenesisMints;
|
||||
extern SField const sfActiveValidators;
|
||||
extern SField const sfImportVLKeys;
|
||||
extern SField const sfHookEmissions;
|
||||
extern SField const sfAttesters;
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
|
||||
@@ -141,6 +141,13 @@ InnerObjectFormats::InnerObjectFormats()
|
||||
{sfPublicKey, soeREQUIRED},
|
||||
{sfAccount, soeOPTIONAL},
|
||||
});
|
||||
|
||||
add(sfAttesterEntry.jsonName.c_str(),
|
||||
sfAttesterEntry.getCode(),
|
||||
{
|
||||
{sfAccount, soeREQUIRED},
|
||||
{sfFlags, soeREQUIRED},
|
||||
});
|
||||
}
|
||||
|
||||
InnerObjectFormats const&
|
||||
|
||||
@@ -347,6 +347,7 @@ CONSTRUCT_UNTYPED_SFIELD(sfGenesisMint, "GenesisMint", OBJECT,
|
||||
CONSTRUCT_UNTYPED_SFIELD(sfActiveValidator, "ActiveValidator", OBJECT, 95);
|
||||
CONSTRUCT_UNTYPED_SFIELD(sfImportVLKey, "ImportVLKey", OBJECT, 94);
|
||||
CONSTRUCT_UNTYPED_SFIELD(sfHookEmission, "HookEmission", OBJECT, 93);
|
||||
CONSTRUCT_UNTYPED_SFIELD(sfAttesterEntry, "AttesterEntry", OBJECT, 90);
|
||||
|
||||
// array of objects
|
||||
// ARRAY/1 is reserved for end of array
|
||||
@@ -371,6 +372,7 @@ CONSTRUCT_UNTYPED_SFIELD(sfGenesisMints, "GenesisMints", ARRAY,
|
||||
CONSTRUCT_UNTYPED_SFIELD(sfActiveValidators, "ActiveValidators", ARRAY, 95);
|
||||
CONSTRUCT_UNTYPED_SFIELD(sfImportVLKeys, "ImportVLKeys", ARRAY, 94);
|
||||
CONSTRUCT_UNTYPED_SFIELD(sfHookEmissions, "HookEmissions", ARRAY, 93);
|
||||
CONSTRUCT_UNTYPED_SFIELD(sfAttesters, "Attesters", ARRAY, 91);
|
||||
|
||||
// clang-format on
|
||||
|
||||
|
||||
@@ -44,6 +44,7 @@ TxFormats::TxFormats()
|
||||
{sfNetworkID, soeOPTIONAL},
|
||||
{sfHookParameters, soeOPTIONAL},
|
||||
{sfOperationLimit, soeOPTIONAL},
|
||||
{sfAttesters, soeOPTIONAL},
|
||||
};
|
||||
|
||||
add(jss::AccountSet,
|
||||
|
||||
@@ -51,6 +51,7 @@ JSS(Amendments); // ledger type.
|
||||
JSS(Amount); // in: TransactionSign; field.
|
||||
JSS(Authorize); // field
|
||||
JSS(Attest);
|
||||
JSS(AttesterEntry);
|
||||
JSS(Attestation);
|
||||
JSS(Blob);
|
||||
JSS(Check); // ledger type.
|
||||
|
||||
Reference in New Issue
Block a user