Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
1165f63
bump to protocol v10
MonsieurNicolas Nov 27, 2017
03174c9
added "exists" method to testAccount
MonsieurNicolas Jan 30, 2018
44bd9e7
removed obsolete calls to setCurrentLedgerVersion in txEnvelopeTests
MonsieurNicolas Jan 30, 2018
534caf7
move tests for bound checking into their own sections
MonsieurNicolas Jan 30, 2018
10179d6
Move to new meta format
MonsieurNicolas Jan 30, 2018
69dda2e
Process sequence number during apply
MonsieurNicolas Jan 30, 2018
f879d41
reworked herder test to be a bit more representative of what is going on
MonsieurNicolas Jan 30, 2018
2e67acb
reworked logic for testing transactions (applyCheck)
MonsieurNicolas Jan 30, 2018
e82be46
Add the BumpSequence Operation & Tests
JeremyRubin Sep 22, 2017
7e5e2a0
Fix to make BumpSequence target the source
JeremyRubin Sep 22, 2017
805c759
small refactors, load account instead of direct access
JeremyRubin Sep 23, 2017
7506448
Refactor to use native tx_NOACCOUNT error
JeremyRubin Sep 25, 2017
d2d7871
updated Visual Studio project with BumpSeq files
MonsieurNicolas Mar 20, 2018
cbd8d6f
clang-format & renamed BUMP_SEQ -> BUMP_SEQUENCE
MonsieurNicolas Feb 1, 2018
e5a7110
updated BumpSequence to be compliant with specification dated 13-Oct-…
MonsieurNicolas Feb 1, 2018
7a15050
introduce opNOT_SUPPORTED when operations are not supported (yet/anym…
MonsieurNicolas Feb 3, 2018
e9ed4c5
remove BUMP_SEQUENCE_NOT_SUPPORTED_YET, use operation level failure i…
MonsieurNicolas Feb 3, 2018
1f05651
added safeConvertToSigned utility function
MonsieurNicolas Feb 5, 2018
1082eb0
make it safe for sequence numbers to use the entire uint64 space
MonsieurNicolas Feb 5, 2018
4fe0945
update BumpSequence to allow bumping through the entire uint64 space
MonsieurNicolas Feb 5, 2018
6257cb2
make AccountMerge fail when the current sequence number is too far
MonsieurNicolas Feb 5, 2018
474ece9
added tests for sequence number overflow
MonsieurNicolas Feb 5, 2018
d7a12fd
added missing merge test (signers)
MonsieurNicolas Feb 6, 2018
f9f9187
make SequenceNumber a signed integer (BumpSeq proposal 08-Feb-2018)
MonsieurNicolas Feb 9, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
make SequenceNumber a signed integer (BumpSeq proposal 08-Feb-2018)
  • Loading branch information
MonsieurNicolas committed Mar 20, 2018
commit f9f9187ed4721cec0f53bd208ba3451e61d7c0d9
4 changes: 4 additions & 0 deletions src/invariant/LedgerEntryIsValid.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,10 @@ LedgerEntryIsValid::checkIsValid(AccountEntry const& ae) const
{
return fmt::format("Account balance ({}) is negative", ae.balance);
}
if (ae.seqNum < 0)
{
return fmt::format("Account seqNum ({}) is negative", ae.seqNum);
}
if (ae.numSubEntries > INT32_MAX)
{
return fmt::format("Account numSubEntries ({}) exceeds limit ({})",
Expand Down
8 changes: 2 additions & 6 deletions src/ledger/AccountFrame.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -233,10 +233,9 @@ AccountFrame::loadAccount(AccountID const& accountID, Database& db)
"inflationdest, homedomain, thresholds, "
"flags, lastmodified "
"FROM accounts WHERE accountid=:v1");
int64 seqNumS;
auto& st = prep.statement();
st.exchange(into(account.balance));
st.exchange(into(seqNumS));
st.exchange(into(account.seqNum));
st.exchange(into(account.numSubEntries));
st.exchange(into(inflationDest, inflationDestInd));
st.exchange(into(homeDomain));
Expand All @@ -255,7 +254,6 @@ AccountFrame::loadAccount(AccountID const& accountID, Database& db)
return nullptr;
}

account.seqNum = static_cast<uint64>(seqNumS);
account.homeDomain = homeDomain;

bn::decode_b64(thresholds.begin(), thresholds.end(),
Expand Down Expand Up @@ -459,12 +457,10 @@ AccountFrame::storeUpdate(LedgerDelta& delta, Database& db, bool insert)
string thresholds(bn::encode_b64(mAccountEntry.thresholds));

{
int64 seqNumS = safeConvertToSigned<int64>(mAccountEntry.seqNum);

soci::statement& st = prep.statement();
st.exchange(use(actIDStrKey, "id"));
st.exchange(use(mAccountEntry.balance, "v1"));
st.exchange(use(seqNumS, "v2"));
st.exchange(use(mAccountEntry.seqNum, "v2"));
st.exchange(use(mAccountEntry.numSubEntries, "v3"));
st.exchange(use(inflationDestStrKey, inflation_ind, "v4"));
string homeDomain(mAccountEntry.homeDomain);
Expand Down
8 changes: 7 additions & 1 deletion src/ledger/LedgerHeaderFrame.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,10 +61,16 @@ LedgerHeaderFrame::getHash() const
return mHash;
}

SequenceNumber
LedgerHeaderFrame::getStartingSequenceNumber(uint32 ledgerSeq)
{
return static_cast<SequenceNumber>(ledgerSeq) << 32;
}

SequenceNumber
LedgerHeaderFrame::getStartingSequenceNumber() const
{
return static_cast<uint64_t>(mHeader.ledgerSeq) << 32;
return getStartingSequenceNumber(mHeader.ledgerSeq);
}

uint64_t
Expand Down
1 change: 1 addition & 0 deletions src/ledger/LedgerHeaderFrame.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ class LedgerHeaderFrame
Hash const& getHash() const;

// returns the first sequence number to use for new accounts
static SequenceNumber getStartingSequenceNumber(uint32 ledgerSeq);
SequenceNumber getStartingSequenceNumber() const;

// methods to generate IDs
Expand Down
4 changes: 4 additions & 0 deletions src/ledger/LedgerTestUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,10 @@ makeValid(AccountEntry& a)
}
}
a.numSubEntries = (uint32)a.signers.size();
if (a.seqNum < 0)
{
a.seqNum = -a.seqNum;
}
a.flags = a.flags & MASK_ACCOUNT_FLAGS;
}

Expand Down
5 changes: 3 additions & 2 deletions src/simulation/LoadGenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -487,7 +487,8 @@ LoadGenerator::createAccount(size_t i, uint32_t ledgerNum)
auto accountName = "Account-" + to_string(i);
return make_shared<AccountInfo>(
i, txtest::getAccount(accountName.c_str()), 0,
(static_cast<SequenceNumber>(ledgerNum) << 32), ledgerNum, *this);
LedgerHeaderFrame::getStartingSequenceNumber(ledgerNum), ledgerNum,
*this);
}

vector<LoadGenerator::AccountInfoPtr>
Expand Down Expand Up @@ -755,7 +756,7 @@ LoadGenerator::AccountInfo::createDirectly(Application& app)
AccountEntry& account = a.getAccount();
auto ledger = app.getLedgerManager().getLedgerNum();
account.balance = LOADGEN_ACCOUNT_BALANCE;
account.seqNum = ((SequenceNumber)ledger) << 32;
account.seqNum = LedgerHeaderFrame::getStartingSequenceNumber(ledger);
a.touch(ledger);
LedgerDelta delta(app.getLedgerManager().getCurrentLedgerHeader(),
app.getDatabase());
Expand Down
2 changes: 2 additions & 0 deletions src/test/TestExceptions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,8 @@ throwIf(BumpSequenceResult const& result)
{
case BUMP_SEQUENCE_SUCCESS:
break;
case BUMP_SEQUENCE_BAD_SEQ:
throw ex_BUMP_SEQUENCE_BAD_SEQ{};
default:
throw ex_UNKNOWN{};
}
Expand Down
2 changes: 2 additions & 0 deletions src/test/TestExceptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ TEST_EXCEPTION(ex_ALLOW_TRUST_TRUST_NOT_REQUIRED)
TEST_EXCEPTION(ex_ALLOW_TRUST_CANT_REVOKE)
TEST_EXCEPTION(ex_ALLOW_TRUST_SELF_NOT_ALLOWED)

TEST_EXCEPTION(ex_BUMP_SEQUENCE_BAD_SEQ)

TEST_EXCEPTION(ex_CREATE_ACCOUNT_MALFORMED)
TEST_EXCEPTION(ex_CREATE_ACCOUNT_UNDERFUNDED)
TEST_EXCEPTION(ex_CREATE_ACCOUNT_LOW_RESERVE)
Expand Down
8 changes: 8 additions & 0 deletions src/transactions/BumpSequenceOpFrame.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,14 @@ BumpSequenceOpFrame::doApply(Application& app, LedgerDelta& delta,
bool
BumpSequenceOpFrame::doCheckValid(Application& app)
{
if (mBumpSequenceOp.bumpTo < 0)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

bumping to 0 is OK (always no-op)?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

0 is a valid sequence number, so yes

{
app.getMetrics()
.NewMeter({"op-bump-sequence", "invalid", "bad-seq"}, "operation")
.Mark();
innerResult().code(BUMP_SEQUENCE_BAD_SEQ);
return false;
}
return true;
}
}
10 changes: 8 additions & 2 deletions src/transactions/BumpSequenceTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,10 @@ TEST_CASE("bump sequence", "[tx][bumpsequence]")
}
SECTION("large bump")
{
auto newSeq = UINT64_MAX;
auto newSeq = INT64_MAX;
a.bumpSequence(newSeq);
REQUIRE(a.loadSequenceNumber() == newSeq);
SECTION("no more tx when UINT64_MAX is reached")
SECTION("no more tx when INT64_MAX is reached")
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so this is second way to lock account, next to setting master weight to 0, nice!

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no it doesn't lock the account, it just cannot be used as source account for a transaction

{
REQUIRE_THROWS_AS(a.pay(root, 1), ex_txBAD_SEQ);
}
Expand All @@ -63,6 +63,12 @@ TEST_CASE("bump sequence", "[tx][bumpsequence]")
// tx consumes sequence, bumpSequence doesn't do anything
REQUIRE(a.loadSequenceNumber() == oldSeq + 1);
}
SECTION("bad seq")
{
REQUIRE_THROWS_AS(a.bumpSequence(-1), ex_BUMP_SEQUENCE_BAD_SEQ);
REQUIRE_THROWS_AS(a.bumpSequence(INT64_MIN),
ex_BUMP_SEQUENCE_BAD_SEQ);
}
});
}
SECTION("not supported")
Expand Down
10 changes: 6 additions & 4 deletions src/transactions/MergeOpFrame.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

#include "transactions/MergeOpFrame.h"
#include "database/Database.h"
#include "ledger/LedgerHeaderFrame.h"
#include "ledger/TrustFrame.h"
#include "main/Application.h"
#include "medida/meter.h"
Expand Down Expand Up @@ -94,11 +95,12 @@ MergeOpFrame::doApply(Application& app, LedgerDelta& delta,

if (ledgerManager.getCurrentLedgerVersion() >= 10)
{
SequenceNumber maxSeqNum =
ledgerManager.getCurrentLedgerHeader().ledgerSeq;
maxSeqNum = (maxSeqNum << 32) - 1;
SequenceNumber maxSeq = LedgerHeaderFrame::getStartingSequenceNumber(
ledgerManager.getCurrentLedgerHeader().ledgerSeq);

if (mSourceAccount->getSeqNum() > maxSeqNum)
// don't allow the account to be merged if recreating it would cause it
// to jump backwards
if (mSourceAccount->getSeqNum() >= maxSeq)
{
app.getMetrics()
.NewMeter({"op-merge", "failure", "too-far"}, "operation")
Expand Down
22 changes: 16 additions & 6 deletions src/transactions/MergeTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -623,22 +623,32 @@ TEST_CASE("merge", "[tx][merge]")
SECTION("merge too far")
{
for_versions_from(10, *app, [&]() {
SequenceNumber maxSeqNum = app->getLedgerManager().getLedgerNum();
maxSeqNum = (maxSeqNum << 32) - 1;
maxSeqNum--; // a1.merge will increment at the transaction level
SequenceNumber curStartSeqNum =
LedgerHeaderFrame::getStartingSequenceNumber(
app->getLedgerManager().getLedgerNum());
auto maxSeqNum = curStartSeqNum - 1;

auto txFrame = root.tx({a1.op(accountMerge(b1))});
txFrame->addSignature(a1.getSecretKey());

SECTION("at max = success")
{
a1.bumpSequence(maxSeqNum);
REQUIRE(a1.loadSequenceNumber() == maxSeqNum);
a1.merge(b1);
REQUIRE(applyCheck(txFrame, *app));
}
SECTION("passed max = failure")
{
maxSeqNum++;
a1.bumpSequence(maxSeqNum);
REQUIRE(a1.loadSequenceNumber() == maxSeqNum);
REQUIRE_THROWS_AS(a1.merge(b1),
ex_ACCOUNT_MERGE_SEQNUM_TOO_FAR);

REQUIRE(!applyCheck(txFrame, *app));
REQUIRE(txFrame->getResult()
.result.results()[0]
.tr()
.accountMergeResult()
.code() == ACCOUNT_MERGE_SEQNUM_TOO_FAR);
}
});
}
Expand Down
2 changes: 1 addition & 1 deletion src/transactions/TransactionFrame.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -310,7 +310,7 @@ TransactionFrame::commonValid(SignatureChecker& signatureChecker,
{
current = mSigningAccount->getSeqNum();
}
if (current == UINT64_MAX || current + 1 != mEnvelope.tx.seqNum)
if (current == INT64_MAX || current + 1 != mEnvelope.tx.seqNum)
{
app.getMetrics()
.NewMeter({"transaction", "invalid", "bad-seq"}, "transaction")
Expand Down
20 changes: 0 additions & 20 deletions src/util/types.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,24 +80,4 @@ bool iequals(std::string const& a, std::string const& b);
bool operator>=(Price const& a, Price const& b);
bool operator>(Price const& a, Price const& b);
bool operator==(Price const& a, Price const& b);

template <typename T, typename UT = std::make_unsigned<T>::type,
class = typename std::enable_if<std::is_signed<T>::value>::type>
T
safeConvertToSigned(UT x)
{
T res;
UT m = static_cast<UT>(std::numeric_limits<T>::max());
if (x <= m)
{
res = x;
}
else
{
UT d = (x - m - 1);
assert(d <= static_cast<UT>(std::numeric_limits<T>::max()));
res = std::numeric_limits<T>::min() + static_cast<T>(d);
}
return res;
}
}
2 changes: 1 addition & 1 deletion src/xdr/Stellar-ledger-entries.x
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ typedef PublicKey AccountID;
typedef opaque Thresholds[4];
typedef string string32<32>;
typedef string string64<64>;
typedef uint64 SequenceNumber;
typedef int64 SequenceNumber;
typedef opaque DataValue<64>;

enum AssetType
Expand Down
4 changes: 2 additions & 2 deletions src/xdr/Stellar-transaction.x
Original file line number Diff line number Diff line change
Expand Up @@ -671,9 +671,9 @@ default:
enum BumpSequenceResultCode
{
// codes considered as "success" for the operation
BUMP_SEQUENCE_SUCCESS = 0
BUMP_SEQUENCE_SUCCESS = 0,
// codes considered as "failure" for the operation
// (this operation never fails)
BUMP_SEQUENCE_BAD_SEQ = -1 // `bumpTo` is not within bounds
};

union BumpSequenceResult switch (BumpSequenceResultCode code)
Expand Down