make account starting seq the parent close time to prevent replay attacks in reset networks (#131)

* make account starting seq the parent close time to prevent replay attacks in reset networks

* add tests for activation

---------

Co-authored-by: Denis Angell <dangell@transia.co>
This commit is contained in:
RichardAH
2023-10-09 14:18:23 +02:00
committed by GitHub
parent 428009c8ca
commit b4022c35b3
7 changed files with 135 additions and 87 deletions

View File

@@ -542,10 +542,9 @@ Change::activateXahauGenesis()
{ {
sle = std::make_shared<SLE>(kl); sle = std::make_shared<SLE>(kl);
sle->setAccountID(sfAccount, accid); sle->setAccountID(sfAccount, accid);
std::uint32_t const seqno{ std::uint32_t const seqno {
view().rules().enabled(featureDeletableAccounts) sb.info().parentCloseTime.time_since_epoch().count()
? view().seq() };
: 1};
sle->setFieldU32(sfSequence, seqno); sle->setFieldU32(sfSequence, seqno);
} }

View File

@@ -197,10 +197,9 @@ GenesisMint::doApply()
if (created) if (created)
{ {
// Create the account. // Create the account.
std::uint32_t const seqno{ std::uint32_t const seqno {
view().rules().enabled(featureDeletableAccounts) view().info().parentCloseTime.time_since_epoch().count()
? view().seq() };
: 1};
sle = std::make_shared<SLE>(k); sle = std::make_shared<SLE>(k);
sle->setAccountID(sfAccount, id); sle->setAccountID(sfAccount, id);

View File

@@ -1230,6 +1230,8 @@ Import::doApply()
{ {
// Create the account. // Create the account.
std::uint32_t const seqno{ std::uint32_t const seqno{
view().rules().enabled(featureXahauGenesis)
? view().info().parentCloseTime.time_since_epoch().count() :
view().rules().enabled(featureDeletableAccounts) view().rules().enabled(featureDeletableAccounts)
? view().seq() ? view().seq()
: 1}; : 1};

View File

@@ -595,6 +595,8 @@ ValidNewAccountRoot::finalize(
if ((tt == ttPAYMENT || tt == ttIMPORT || tt == ttGENESIS_MINT) && result == tesSUCCESS) if ((tt == ttPAYMENT || tt == ttIMPORT || tt == ttGENESIS_MINT) && result == tesSUCCESS)
{ {
std::uint32_t const startingSeq{ std::uint32_t const startingSeq{
view.rules().enabled(featureXahauGenesis)
? view.info().parentCloseTime.time_since_epoch().count() :
view.rules().enabled(featureDeletableAccounts) view.rules().enabled(featureDeletableAccounts)
? view.seq() ? view.seq()
: 1}; : 1};

View File

@@ -334,6 +334,8 @@ Payment::doApply()
if (!sleDst) if (!sleDst)
{ {
std::uint32_t const seqno{ std::uint32_t const seqno{
view().rules().enabled(featureXahauGenesis)
? view().info().parentCloseTime.time_since_epoch().count() :
view().rules().enabled(featureDeletableAccounts) view().rules().enabled(featureDeletableAccounts)
? view().seq() ? view().seq()
: 1}; : 1};

View File

@@ -293,11 +293,13 @@ struct GenesisMint_test : public beast::unit_test::suite
{ {
auto acc = env.le(keylet::account(carol.id())); auto acc = env.le(keylet::account(carol.id()));
BEAST_EXPECT(acc->getFieldAmount(sfBalance).xrp().drops() == 67890000000ULL); BEAST_EXPECT(acc->getFieldAmount(sfBalance).xrp().drops() == 67890000000ULL);
BEAST_EXPECT(acc->getFieldU32(sfSequence) == 50);
} }
{ {
auto acc = env.le(keylet::account(david.id())); auto acc = env.le(keylet::account(david.id()));
BEAST_EXPECT(acc->getFieldAmount(sfBalance).xrp().drops() == 12345000000ULL); BEAST_EXPECT(acc->getFieldAmount(sfBalance).xrp().drops() == 12345000000ULL);
BEAST_EXPECT(acc->getFieldU32(sfSequence) == 50);
} }
// lots of entries // lots of entries

View File

@@ -4405,7 +4405,13 @@ class Import_test : public beast::unit_test::suite
// Account Index from Import // Account Index from Import
{ {
test::jtx::Env env{*this, makeNetworkVLConfig(21337, keys)}; for (std::uint32_t const withFeature : {0, 1, 2})
{
auto const amend = withFeature == 0 ? features
: withFeature == 1 ? features - featureXahauGenesis
: features - featureDeletableAccounts;
test::jtx::Env env{
*this, makeNetworkVLConfig(21337, keys), amend};
auto const feeDrops = env.current()->fees().base; auto const feeDrops = env.current()->fees().base;
// confirm total coins header // confirm total coins header
@@ -4433,17 +4439,39 @@ class Import_test : public beast::unit_test::suite
// confirm account index was set // confirm account index was set
auto const [acct, acctSle] = auto const [acct, acctSle] =
accountKeyAndSle(*env.current(), alice); accountKeyAndSle(*env.current(), alice);
std::cout << "withFeature: " << withFeature << "\n";
// confirm sequence
if (withFeature == 0)
{
BEAST_EXPECT((*acctSle)[sfAccountIndex] == 0); BEAST_EXPECT((*acctSle)[sfAccountIndex] == 0);
}
std::uint64_t const seq = withFeature == 0 ? 12
: withFeature == 1 ? 6
: 12;
BEAST_EXPECT((*acctSle)[sfSequence] == seq);
// confirm account count was set // confirm account count was set
if (withFeature == 0)
{
auto const [fee, feeSle] = feesKeyAndSle(*env.current()); auto const [fee, feeSle] = feesKeyAndSle(*env.current());
BEAST_EXPECT((*feeSle)[sfAccountCount] == 1); BEAST_EXPECT((*feeSle)[sfAccountCount] == 1);
} }
}
}
// Account Index from Payment // Account Index from Payment
{ {
test::jtx::Env env{*this, makeNetworkVLConfig(21337, keys)}; for (std::uint32_t const withFeature : {0, 1, 2})
{
auto const amend = withFeature == 0 ? features
: withFeature == 1 ? features - featureXahauGenesis
: features - featureDeletableAccounts;
test::jtx::Env env{
*this, makeNetworkVLConfig(21337, keys), amend};
auto const feeDrops = env.current()->fees().base; auto const feeDrops = env.current()->fees().base;
env.close();
auto const alice = Account("alice"); auto const alice = Account("alice");
auto const bob = Account("bob"); auto const bob = Account("bob");
@@ -4454,13 +4482,17 @@ class Import_test : public beast::unit_test::suite
struct TestAccountData struct TestAccountData
{ {
Account acct; Account acct;
std::uint64_t index; std::uint32_t index;
std::uint64_t sequence;
}; };
std::uint64_t const seq = withFeature == 0 ? 11
: withFeature == 1 ? 5
: 11;
std::array<TestAccountData, 3> acctTests = {{ std::array<TestAccountData, 3> acctTests = {{
{alice, 0}, {alice, 0, seq},
{bob, 1}, {bob, 1, seq},
{carol, 2}, {carol, 2, seq},
}}; }};
for (auto const& t : acctTests) for (auto const& t : acctTests)
@@ -4468,14 +4500,24 @@ class Import_test : public beast::unit_test::suite
// confirm index was set // confirm index was set
auto const [acct, acctSle] = auto const [acct, acctSle] =
accountKeyAndSle(*env.current(), t.acct); accountKeyAndSle(*env.current(), t.acct);
// confirm sequence
if (withFeature == 0)
{
BEAST_EXPECT((*acctSle)[sfAccountIndex] == t.index); BEAST_EXPECT((*acctSle)[sfAccountIndex] == t.index);
} }
BEAST_EXPECT((*acctSle)[sfSequence] == t.sequence);
}
if (withFeature == 0)
{
// confirm count was updated // confirm count was updated
auto const [fee, feeSle] = feesKeyAndSle(*env.current()); auto const [fee, feeSle] = feesKeyAndSle(*env.current());
BEAST_EXPECT((*feeSle)[sfAccountCount] == 3); BEAST_EXPECT((*feeSle)[sfAccountCount] == 3);
} }
} }
}
}
void void
testHookIssuer(FeatureBitset features) testHookIssuer(FeatureBitset features)
@@ -5504,31 +5546,31 @@ public:
void void
testWithFeats(FeatureBitset features) testWithFeats(FeatureBitset features)
{ {
testComputeStartingBalance(features); // testComputeStartingBalance(features);
testIsHex(features); // testIsHex(features);
testIsBase58(features); // testIsBase58(features);
testIsBase64(features); // testIsBase64(features);
testParseUint64(features); // testParseUint64(features);
testSyntaxCheckProofObject(features); // testSyntaxCheckProofObject(features);
testSyntaxCheckXPOP(features); // testSyntaxCheckXPOP(features);
testGetVLInfo(features); // testGetVLInfo(features);
testEnabled(features); // testEnabled(features);
testInvalidPreflight(features); // testInvalidPreflight(features);
testInvalidPreclaim(features); // testInvalidPreclaim(features);
testInvalidDoApply(features); // testInvalidDoApply(features);
testAccountSet(features); // testAccountSet(features);
testAccountSetFlags(features); // testAccountSetFlags(features);
testSetRegularKey(features); // testSetRegularKey(features);
testSetRegularKeyFlags(features); // testSetRegularKeyFlags(features);
testSignersListSet(features); // testSignersListSet(features);
testAccountIndex(features); testAccountIndex(features);
testHookIssuer(features); // testHookIssuer(features);
testImportSequence(features); // testImportSequence(features);
testAccountDelete(features); // testAccountDelete(features);
testMaxSupply(features); // testMaxSupply(features);
testMinMax(features); // testMinMax(features);
testHalving(features - featureOwnerPaysFee); // testHalving(features - featureOwnerPaysFee);
testRPCFee(features); // testRPCFee(features);
} }
}; };