Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Config Setting upgrades #3674

Merged
merged 15 commits into from
Apr 6, 2023
Merged

Conversation

sisuresh
Copy link
Contributor

@sisuresh sisuresh commented Mar 9, 2023

Description

Resolves stellar/rs-soroban-env#664.

Add a mechanism to propose upgrades that are stored in ContractData ledger entries. This PR is built on top of #3522, and starts with the "ConfigSettingEntry upgrades" commit.

Related xdr change - stellar/stellar-xdr#75.

xdr has not been merged in yet so this PR will fail until that happens.

Checklist

  • Reviewed the contributing document
  • Rebased on top of master (no merge commits)
  • Ran clang-format v8.0.0 (via make format or the Visual Studio extension)
  • Compiles
  • Ran all tests
  • If change impacts performance, include supporting evidence per the performance document

@sisuresh sisuresh requested a review from dmkozh March 9, 2023 23:25
src/bucket/test/BucketListTests.cpp Outdated Show resolved Hide resolved
src/herder/Upgrades.cpp Outdated Show resolved Hide resolved
@@ -252,6 +330,12 @@ Upgrades::toString(LedgerUpgrade const& upgrade)
upgrade.newBaseReserve());
case LEDGER_UPGRADE_FLAGS:
return fmt::format(FMT_STRING("flags={:d}"), upgrade.newFlags());
#ifdef ENABLE_NEXT_PROTOCOL_VERSION_UNSAFE_FOR_PRODUCTION
case LEDGER_UPGRADE_CONFIG:
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm not sure if this has the same format as all the other entries (with '='). Also, this will return JSON, right? So the formatting might be a bit weird due to it being multiline. Not sure though where we're using the toString though...

src/herder/Upgrades.cpp Outdated Show resolved Hide resolved
src/herder/Upgrades.cpp Show resolved Hide resolved
src/herder/Upgrades.cpp Outdated Show resolved Hide resolved
src/herder/test/UpgradesTests.cpp Show resolved Hide resolved
src/herder/test/UpgradesTests.cpp Outdated Show resolved Hide resolved
src/herder/test/UpgradesTests.cpp Show resolved Hide resolved
auto upgradeHash = autocheck::generator<Hash>()(5);
auto ledgerUpgrade = LedgerUpgrade{LEDGER_UPGRADE_CONFIG};
ledgerUpgrade.newConfig() = ConfigUpgradeKey{contractID, upgradeHash};
REQUIRE_THROWS_AS(executeUpgrade(*app, ledgerUpgrade),
Copy link
Contributor

Choose a reason for hiding this comment

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

NB: I believe exception is fine here as we shouldn't get to upgrade execution for the invalid/unknown upgrades. But we need to make sure we don't crash during validation itself.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

So this is still an open question I have. If a valid configUpgrade is nominated, is it possible so change the underlying ContractData entry that holds the ConfigUpgradeSet before the upgrade is applied? If so, that scenario needs to be handled.

Copy link
Contributor

Choose a reason for hiding this comment

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

Hmm, yeah, it might change, so we need to verify that hash in the key matches the content hash. That can happen at validation time though, as upgrades happen after all the transactions. At apply time the upgrade set should be guaranteed to be correct and hence it should be ok to throw an exception (as that would be a bug)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The hash is already verified in ConfigUpgradeSetFrame::isValidXDR.

Copy link
Contributor

Choose a reason for hiding this comment

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

So we should be good, right? Also we load the actual entry just once anyway, so there shouldn't be mismatch between the config upgrade set at validation and application time.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We load the entry at validation and at apply (every time we call makeFromKey). It's possible that the ledger the upgrade should be included in changes the entry, making the upgrade invalid. In that case, an exception would be thrown here -

throw std::runtime_error(
We need to take this into account and handle the invalid upgrade case instead of crashing.

Copy link
Contributor Author

@sisuresh sisuresh Mar 23, 2023

Choose a reason for hiding this comment

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

Updated code to ignore invalid upgrades instead of throwing an exception.

@sisuresh sisuresh force-pushed the config_setting_le branch 3 times, most recently from a07289b to b330107 Compare March 20, 2023 18:38
src/herder/test/UpgradesTests.cpp Show resolved Hide resolved
src/herder/Upgrades.cpp Outdated Show resolved Hide resolved
src/herder/Upgrades.cpp Outdated Show resolved Hide resolved
auto upgradeHash = autocheck::generator<Hash>()(5);
auto ledgerUpgrade = LedgerUpgrade{LEDGER_UPGRADE_CONFIG};
ledgerUpgrade.newConfig() = ConfigUpgradeKey{contractID, upgradeHash};
REQUIRE_THROWS_AS(executeUpgrade(*app, ledgerUpgrade),
Copy link
Contributor

Choose a reason for hiding this comment

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

Hmm, yeah, it might change, so we need to verify that hash in the key matches the content hash. That can happen at validation time though, as upgrades happen after all the transactions. At apply time the upgrade set should be guaranteed to be correct and hence it should be ok to throw an exception (as that would be a bug)

auto ltxe = ltx.loadWithoutRecord(ConfigUpgradeSetFrame::getLedgerKey(key));
if (!ltxe)
{
return nullptr;
Copy link
Contributor

Choose a reason for hiding this comment

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

Just wanted to make sure, how the downstream code handles nullptr here? Would it just act as if we didn't have such upgrade armed?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It depends. In the CommandHandler, we actually check after setting to make sure something was set. In applyTo, we throw an exception (this shouldn't happen, but if it does, it'll be caught). In isValidForApply, we return XDR_INVALID. In isValidForNomination, we return false.

@sisuresh sisuresh force-pushed the config_setting_le branch 2 times, most recently from 78a46c4 to 7e47c86 Compare March 23, 2023 22:28
@sisuresh sisuresh marked this pull request as ready for review March 23, 2023 22:30
src/herder/Upgrades.cpp Outdated Show resolved Hide resolved
src/bucket/test/BucketListTests.cpp Show resolved Hide resolved
src/herder/Upgrades.cpp Outdated Show resolved Hide resolved
src/herder/Upgrades.cpp Show resolved Hide resolved
src/herder/Upgrades.cpp Outdated Show resolved Hide resolved
hexAbbrev(key.contentHash));
return false;
}
if (std::adjacent_find(
Copy link
Contributor

Choose a reason for hiding this comment

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

is_sorted above already does not allow for duplicates

Copy link
Contributor

Choose a reason for hiding this comment

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

That's not true - it 'Checks if the elements in range [first, last) are sorted in non-descending order'

Copy link
Contributor

Choose a reason for hiding this comment

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

bleh yes! I always get is_sorted wrong

So I guess the suggestion becomes: as we use a custom predicate we should just use >= for adjacent_find which should do what we want (can't use this with is_sorted as >= is not Compare).

src/herder/Upgrades.cpp Show resolved Hide resolved
src/herder/Upgrades.cpp Outdated Show resolved Hide resolved
src/main/CommandHandler.cpp Show resolved Hide resolved
@sisuresh sisuresh force-pushed the config_setting_le branch from 80b11d3 to 77bcdd3 Compare March 28, 2023 00:45
@MonsieurNicolas
Copy link
Contributor

Change looks good now!

@sisuresh sisuresh force-pushed the config_setting_le branch from 14f73ba to ed002c2 Compare March 30, 2023 00:20
dmkozh added 5 commits March 29, 2023 17:21
This is to support how the new XDR is generated.
While this can be supported from the ledger standpoint, I think that semantically these shouldn't be removed and hence it's better to introduce some harness to make sure we don't accidentally remove it.
- Add methods to generate unique entries, so that we don't need to exclude `CONFIG_SETTING` entry from the fuzzer due to them having key collisions
- Add methods to generate entries of given type and entries with exclusions to be more explicit about including/excluding the entry types where relevant
@sisuresh sisuresh force-pushed the config_setting_le branch from ed002c2 to 1b2f664 Compare March 30, 2023 00:22
@sisuresh
Copy link
Contributor Author

I cleaned up history and merged in the xdr change. One thing I'm trying to figure out though - I only updated the C++ and not env, but the xdr mismatch check isn't triggering for me locally.

@sisuresh sisuresh force-pushed the config_setting_le branch from 1b2f664 to 27bf0bd Compare March 30, 2023 00:42
@MonsieurNicolas
Copy link
Contributor

I cleaned up history and merged in the xdr change. One thing I'm trying to figure out though - I only updated the C++ and not env, but the xdr mismatch check isn't triggering for me locally.

@graydon do you think this is related to the fix you made?

@sisuresh
Copy link
Contributor Author

I cleaned up history and merged in the xdr change. One thing I'm trying to figure out though - I only updated the C++ and not env, but the xdr mismatch check isn't triggering for me locally.

@graydon do you think this is related to the fix you made?

Looks like the github action correctly failed though. Weird.

@sisuresh
Copy link
Contributor Author

I cleaned up history and merged in the xdr change. One thing I'm trying to figure out though - I only updated the C++ and not env, but the xdr mismatch check isn't triggering for me locally.

@graydon do you think this is related to the fix you made?

Looks like the github action correctly failed though. Weird.

Ah I see this in my make output. I got a new laptop recently which is why I haven't run into this before. I'll try to get this to fail the build.

../hash-xdrs.sh: line 25: sha256sum: command not found

@sisuresh sisuresh force-pushed the config_setting_le branch from 29f2490 to cd3d956 Compare March 30, 2023 22:35
@graydon
Copy link
Contributor

graydon commented Apr 6, 2023

r+ cd3d956

@graydon
Copy link
Contributor

graydon commented Apr 6, 2023

(@MonsieurNicolas is on vacation but I believe all his concerns were addressed, I'm going to dismiss his change-request)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add a function that can store configuration ledger entries
5 participants