-
Notifications
You must be signed in to change notification settings - Fork 217
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
feat(inter-protocol): write liquidation auction results to Vstorage #8994
base: master
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the PR. Sorry it has taken us so long to get to this review.
packages/vats/test/bootstrapTests/liquidationVisibility/vaultFactory/AttackersGuide.md
Outdated
Show resolved
Hide resolved
packages/vats/test/bootstrapTests/liquidationVisibility/test-liquidation-compatibility.js
Outdated
Show resolved
Hide resolved
Important for commit Jorge-Lopes@984f55bAs With this commit, we've introduced a new message in FYI @Chris-Hibbert |
What branch should we target going forward? Ideally(for us) what ever code is running on the mainnet right now but I'm aware there might be some nuances over there. What do you think? @Chris-Hibbert |
Please target |
Problem when type checking causes CI to failThe CI fails because of a failure in type checking. Here's the error message;
And specific line is:
The weird thing is the actual test runs with no problems. It's just that typescript is not able detect The other odd thing is, this PR has nothing to with the file throwing the error. And as far as I can see/figure the type definitions we add don't touch the definitions |
It doesn't show up in test results for this PR. Do you have a link to the test log? |
Oh sure, sorry about that => https://github.com/Jorge-Lopes/agoric-sdk/actions/runs/9613583517/job/26516739469
|
Could you please approve CI workflows to run? @Chris-Hibbert |
It's weirder than that. Those lines of code haven't changed in your PR. On master, the type of the LHS of that comparison is |
If we explicitly declare the types as /** @type bigint */
const numerator = quoteValue.amountOut.value;
/** @type bigint */
const denominator = quoteValue.amountIn.value;
t.is(numerator / denominator, highPrice); |
# This is the 1st commit message: create dedicated files for test assertions and tools # This is the commit message #2: Add new test file for liquidation visibility # This is the commit message #3: auctioneer snapshot # This is the commit message #4: Update visibility tests and helper functions # This is the commit message #5: add tools and assertions to match subscriber with vstorage data # This is the commit message #6: update test visibility of vault liquidation # This is the commit message #7: fix(liquidationVisibility): fix linting errors # This is the commit message #8: fix(liquidationVisibility): type error # This is the commit message #9: chore(liquidationVisibility): #4 testing tools setup # This is the commit message #10: chore(liquidationVisibility): #4 improve testing tools # This is the commit message #11: chore(liquidationVisibility): #4 improve testing tools # This is the commit message #12: fix(liquidationVisibility): linting fixes # This is the commit message #13: chore(liquidationVisibility): fix test names # This is the commit message #14: fix(liquidationVisibility): lint fix # This is the commit message #15: chore(liquidationVisibility): #4 implement `assertNodeInStorage` # This is the commit message #16: fix(liquidationVisibility): #4 lint fix # This is the commit message #17: chore(liquidationVisibility): #4 test skeleton is ready # This is the commit message #18: chore(liquidationVisibility): #4 add marshaller for comparing data from the vstorage # This is the commit message #19: chore(liquidationVisibility): sample test for `preAuction` and `postAuction` data fields # This is the commit message #20: chore(liquidationVisibility): make sure `assertStorageData` works # This is the commit message #21: chore(liquidationVisibility): #4 add test for case 2b, uncomment assertions for running the tests # This is the commit message #22: feat(liquidationVisibility): create liquidation storageNodes and recorderKits BREAKING CHANGE: Introduced the `_timestamp` as an argument for the vaultManager liquidateVaults method. feat(liquidationVisibility): write preAuctionState and auctionResultState to Vstorage BREAKING CHANGE: a getVaultId method was included in the Vault interface, which returns the vault `idInManager` fix(liquidationVisibility): fix type definitions errors and concurrently await multiple promises feat(liquidationVisibility): write postAuctionState to Vstorage BREAKING CHANGE: the getVaultId method of vaults interface was updated to getVaultState, which will return the vault phase as well chore(liquidationVisibility): update helper methods, type definitions and names fix(liquidationVisibility): lint fix fix(liquidationVisibility): update sequence to write auction state to Vstorage and its structure The helper methods built for this purpose became unnecessary and were removed. fix(liquidationVisibility): update postAuctionState structure and change to writeFinal recorder method fix(liquidationVisibility): remove temporary changes made to tests fix(liquidationVisibility): #4 test for scenario 2b passed, test api updated, #7 is fixed chore(liquidationVisibility): #4 test for scenario 2a passed chore(liquidationVisibility): #4 update scenario 1 Squashed commit of the following: commit 728d695 Author: anilhelvaci <[email protected]> Date: Wed Jan 31 14:28:14 2024 +0300 chore(liquidationVisibility): uncomment post auction assertion in `liq-result-scenario-1` commit dd3fbdb Author: anilhelvaci <[email protected]> Date: Wed Jan 31 14:25:22 2024 +0300 fix(liquidationVisibility): lint fix commit 6920d1a Author: anilhelvaci <[email protected]> Date: Wed Jan 31 14:22:28 2024 +0300 fix(liquidationVisibility): explain Promise.allSettled commit 732e1d7 Author: anilhelvaci <[email protected]> Date: Wed Jan 31 11:37:45 2024 +0300 feat(liquidationVisibility): handle errors that might arise from other vats commit 683f56d Author: anilhelvaci <[email protected]> Date: Tue Jan 30 14:31:13 2024 +0300 feat(liquidationVisibility): add LiquidationVisibilityWriters to improve readability, fetch schedule during the auction itself commit 4c45f2a Author: anilhelvaci <[email protected]> Date: Tue Jan 30 10:30:02 2024 +0300 fix(liquidationVisibility): add pattern matcher to `getVaultState` chore(liquidationVisibility): #4 add auctioneer wrapper and update setupBasics chore(liquidationVisibility): #4 add mock makeChainStorageNode chore(liquidationVisibility): #4 add tests for no vaults and rejected schedule fix(liquidationVisibility): #4 add setBlockMakeChildNode method and update file name fix(liquidationVisibility): #4 update import path chore(liquidationVisibility): #4 add liq-rejected-timestampStorageNode test fix(liquidationVisibility): #4 fix bug with at makeChildNode fix(liquidationVisibility): #4 update test names and comments fix(liquidationVisibility): #4 lint fix chore(internal): create key-value pairs for Promise.allSettled values fix(internal): make allValuesSettled a mapper for resolved promises and silently handles rejected ones fix(internal): fix doc fix(liquidationVisibility): make sure promises are assigned in key-value fashion, lint fixes. chore(liquidationVisibility): extend liq-rejected-timestampStorageNode and clean outdated comments fix(liquidationVisibility): revert update made to package.json chore(liquidationVisibility): update snapshot generated by unit tests fix(liquidationVisibility): lint fix chore(liquidationVisibility) #4 test multiple vaultManagers fix(liquidationVisibility): #4 lint fix fix(liquidationVisibility): add pattern matcher to `getVaultState` feat(liquidationVisibility): add LiquidationVisibilityWriters to improve readability, fetch schedule during the auction itself chore(liquidationVisibility): init work for bootstrap tests chore(liquidationVisibility): created test-liquidation-visibility.ts and started building a test suite chore(liquidationVisibility): upgrade tests are implemented. Refs: #15 fix(liquidationVisibility): vaults are now displayed in the correct order at `vaults.preAuction` Refs: #13 fix(liquidationVisibility): vault phases are now displayed correctly at `vaults.postAuction` Refs: #14 chore(liquidationVisibility): add storage snapshot Refs: #15 fix(liquidationVisibility): don't reverse `vaultData` for preAuction storage node Refs: #13
fix(liquidationVisibility): fix dependency errors
Refs: #24 fix(liquidationVisibility): fix race condition when running tests concurrently fix(liquidationVisibility): fix test-vaultLiquidation.js
author anilhelvaci <[email protected]> 1708371947 +0300 committer anilhelvaci <[email protected]> 1708960452 +0300 fix(liquidationVisibility): lint fix fix(liquidationVisibility): lint fix fix(liquidationVisibility): lint fix fix(liquidationVisibility): fix paths fix(liquidationVisibility): lint and type fixes fix(liquidationVisibility): lint fixes
…date dependencies
…ara instead of state. Refs: #15
…e for readability (WiP) fix(liquidationVisibility): fix unit tests after rebase updates
…ty` in core-eval Refs: #35
…s` and update tests accordingly Refs: #35
…ove `writeLiqVisibility` Refs: #35
…onVisibilityWriters` resulted with below changes; * Use `Promise.all` instead of `allValuesSettled` * Remove `liq-rejected-schedule` and `liq-rejected-timestampStorageNode` as we don't need to handle those cases anymore * Write an error message in postAuction and auctionResults recorder kits in the case of an error in distributing plans Refs: #35
…lated artifacts. Refs: #35
…sibility method and respective snapshot
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I just came across this. I wasn't requested as reviewer. I don't think I have enough context to fully review but I notice some things that will need changing.
Also please squash the fixup commits into what they're fixing. E.g. fix(liquidationVisibility): rebase fixes does not belong in the commit history for master. This will require a force push but I notice you already are doing that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the builds should not be checked in as they may drift from the sources. instead add the core-eval build output dirs to .gitignore
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So are you suggesting;
- We build the bundles when running the test?
- Fetch them from a GH release ?
- Build them manually before running the tests and put them in some directory that its contents do not get pushed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We build the bundles when running the test?
Sort of. We have a step that runs in CI to build whatever bundles need building: https://github.com/Agoric/agoric-sdk/blob/master/a3p-integration/scripts/build-all-submissions.sh
Here's an example that builds several core-evals:
"source": "subdir", | |
"sdk-generate": [ | |
"smart-wallet/build-wallet-factory2-upgrade.js", | |
"testing/start-valueVow.js start-valueVow", | |
"testing/restart-valueVow.js restart-valueVow", | |
"vats/init-orchestration.js" | |
] |
The left side is the path under packages/builders/scripts
and the right side is an optional local dir name.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Understood, started converting to submission
with this commit bd8a071
[ | ||
{ | ||
src: './artifacts/src/vaultFactory/vaultFactoryV2.js', | ||
dest: '/usr/src/agoric-sdk/packages/inter-protocol/src/vaultFactory/vaultFactoryV2.js', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
there should never be a vaultFactoryV2.js
in the SDK paths. There is simply vaultFactory.js
which is whatever the HEAD version is. The earlier version is on-chain.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I understand where you are coming from. The reason I felt comfortable doing what you've highlighted is that vaultFactoryV2.js
never persists to the next build as we run post.liquidation.js
in the TEST
phase of the a3p process. See here.
The reason why we make changes to the HEAD is, we are trying to trigger a liquidation. In order to test the things that depend on a liquidation we need to control the liquidation process. This means we need to have a timerService
we can control which is used by both auctioneer
and vaultFactory
.
Triggering and controlling a liquidation is crucial for us as we try to test the state after a liquidation. I hope this justifies having a vaultFactoryV2.js
in the SDK path in non-persisting TEST
phase.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If it never persists, why put it under agoric-sdk/packages/inter-protocol
? Can't you build it from somewhere in this proposal path?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Building vaultFactory
outside of the sdk path seemed a little tricky at the time given all the dependencies and all that. Maybe I can copy interProtocol
in the proposal path then build it there 🤔
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, true. So you need a special version of vaultFactory
that's just for testing purposes? We havezcf.setTestJig
for in-place testing logic, but a3p tests are for designed for production fidelity and so can't reach into that.
If this contract is just for testing, and not a hypothetical upgrade, then I don't see a problem with it being under agoric-sdk but with a name like 'vaultFactoryForTesting.js`. In which case I even think we should consider having it in master so it can be used again in the future and it doesn't stagnate from regular VF.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[DEPRECATED]
Please do not take into account what is being said in comment. #8994 (comment) has up to date content. @turadg
If this contract is just for testing, and not a hypothetical upgrade, then I don't see a problem with it being under agoric-sdk but with a name like 'vaultFactoryForTesting.js`. In which case I even think we should consider having it in master so it can be used again in the future and it doesn't stagnate from regular VF.
Yeah I can totally agree with that and believe this is to be the case for us. However, this stagnation problem keeps me from moving forward with creating a liquidation in a3p
as auctioneer
is also a part of this liquidation. The best solution I can think of is;
- Put
manualTimer
inside a contract and deploy itcreatorFacet
will have methods for advancing timepublicFacet
will hand out the reference to themanualTimer
- Spin up a new instance of
auctioneer
using the original auctioneer's installation(assuming auctioneer is not upgradable)- Have the fakeAuctioneer use
manualTimer
as its timer service
- Have the fakeAuctioneer use
- Upgrade
vaultFactory
by usingvaultFactoryForTesting.js
as its entry point when bundling which usesmanualTimer
andfakeAuctioneer
- The thing is we need
vaultFactoryForTesting.js
to havevaultFactory
accept its timer service fromprivateArgs
. I see thatvaultFactory
recently movedauctioneerPF
to its private args. If we do the same for timer service, we won't needvaultFactoryForTesting.js
at all.
- The thing is we need
I am curious about any suggestions you might have as well as what you think about this strategy.
Apologies for not making time to review this in detail. I've been assigned other tasks at higher priority. I look forward to spending time looking at this in details. To respond to some of your questions above:
If the auction doesn't respond, there's no way to automatically recovery. The most plausible cause is that the auciton is busted or vaults has
The heap state can be lost when doing a full-upgrade, a null-upgrade, or just when a vat is paged out. "Null upgrade" just means intentionally starting from scratch without a change to the source code. The same restart takes place if a vat is paged out because of inactivity--this is less likely for auctions or vaults, but the mechanism is the same. In those cases, the code starts up by reading state from bagage, wihich includes the state of all durable kinds as well as other values recorded using provide(). The snapshot links are 404. Would you replace them with github permalinks? Those may become outdated, but that's better than broken links. |
…o `eval-liquidation-visibility.js` Refs: #35
Yeah we have switched to
Yeah, we right now rely on the
Done. |
Overlap between
|
vm.CoreProposalStepForModules("@agoric/builders/scripts/vats/add-auction.js"), | |
// upgrade vaultFactory. | |
vm.CoreProposalStepForModules("@agoric/builders/scripts/vats/upgradeVaults.js"), |
When running a3p-integration
tests, proposals run on the ghcr.io/agoric/agoric-sdk:unreleased
image which includes current(whatever branch a3p
tests are running on) version of agoric-sdk
. In the context of this PR, current version is aimed to be Agoric:master
and my tests are running on Jorge-Lopes:develop
.
This situation leads to when a:upgrade-next
upgrades vaultFactory
, the features in this PR are also deployed. So d:liquidation-visiblity
proposal ends up being merely a null upgrade. Here are some I can think of;
- If OpCo considers including
liquidataion-visibility
intoa:upgrade-next
then I suggest not having a separated:liquidation-visibility
proposal at all and implementing aliquidationVisibility.test.js
undera:upgrade-next
to test if our features work as expected. I expect, in this context, testing would require a fairly less overhead as upgradeVaults.test.js already triggers a liquidation and all we need to wait for that liquidation finish and we read its results. The thing to consider here, if we wait for the liquidation to end the test might take more 10 mins to complete. - If OpCo decides to ship this PR in a later time with its own proposal then here's the work we need to do;
- Write a new core eval code for vault factory upgrade since the one used for
a:upgrade-next
does some tricks with the auctioneer and price feeds, see upgrade-vaults.js - Trigger liquidation
- For this we might follow the approach in
a:upgrade-next
due to the stagnation problems of our original approach (This comment explains from a high level). If we end up followinga:upgrade-next
's approach theTEST
phase of the build will probably take around 5-15 mins.
- For this we might follow the approach in
- Write a new core eval code for vault factory upgrade since the one used for
Would appreciate a discussion about above.
@anilhelvaci I think @turadg and/or @Chris-Hibbert are better equipped to answer this when they next get the opportunity |
closes: #8993
Description
The current state of the inter-protocol package lacks sufficient detail regarding the vault's liquidation process. This PR enhances visibility into vault liquidation by recording three stages on Vstorage:
Refer to this snapshot for the defined structure of the Vstorage tree and the data being written to newly created nodes.
Key changes to the source code were focused on the vaultManager, including:
liquidateVaults
method now receives thetimestamp
as an argument, which will be provided by thevaultDirector
when theliquidationWaker
is triggered.allValuesSettled
in theliquidateVaults
method to resolve promises while ensuring the liquidation process proceeds despite any failures.liquidations
storage node at thestart
method, being the parent node themanager<id>
.makeLiquidationVisibilityWriters
,writeLiqVisibility
, andmakeLiquidationRecorderKits
.Security Considerations
We've two main security considerations;
chainStorage
andauctioneer
.chainStorage
: To create new child nodes in the case of there are vaults to liquidateauctioneer
: Get the currentschedule
at a specific point in timeephemera
instead ofthis.state
because we can't add a new property to it after initializationMaking calls to other vats
When making calls to other vats, we wanted to make sure we're not breaking the liquidations process in the case of a promise rejection arising from either
chainStorage
orauctioneer
. So we've implemented allValuesSettled which doesn't throw even if any of those calls rejected. Here's part of the code we're exercising this feature;And we handle the errors coming from
chainStorage
silently like below;We're not too worried about
E(auctionPF).getSchedules()
since it's result is just forwarded to the storage;The biggest consideration here to make is;
auctioneer
andchainStorage
hangs forever instead of rejecting? Is there a timeout mechanism built for this?If there's a chance that one those promises never resolve at all, we might end up blocking the
liquidateVaults
. In that case we might consider usingE.when
. Curious what OpCo is going to say about this.Storing
liquidationsStorageNode
in ephemeral stateWe decided to put all data related to liquidations under a storage node called
liquidationsStorageNode
. The way we keep track of this node was used to be throughstate
variable by defining it as new property underthis.state
. However we've noticed that we're not able define new properties underthis.state
after it's initialization as described in virtual-objects.md. So we've found that storing our reference toliquidationsStorageNode
in ephemera was working fine and was able to survive an upgrade. So our main assumption here is;vaultFactory
vat must be able to recover it's ephemera in case it loses its heap state. We know that it's possible during upgrades thanks to the provide pattern. However, we're not aware of how it can recover if the heap dumped for another reason.Scaling Considerations
The main resource that can be impacted by this PR is the
on-chain storage
.For each
vaultManager
, when an auction is initiated with liquidatable vaults, a new node is created underliquidations
, being its key thestart time
of the open auction.This node will have as children the
auctionResult
stage andvaults
. Under vaults, it be the remaining two stages,preAuction
andpostAuction
, detailed per liquidated vault.Example of the Vstorage tree after an auction with start time set to
3600
, see snapshot:It is important to highlight that, we've ensured by design, that the data written to each node does not grow.
Although, continuous monitoring of on-chain storage impact is necessary to address any unforeseen issues.
Documentation Considerations
The data being published for each auction liquidation stage should be documented, so the users and developers can understand the meaning of it, and how it could be used in their bidding strategies or integrations with other components.
Testing Considerations
For this PR, we built a set of unit tests for the new features implemented, as well as bootstrap tests to ensure that the contract behaves as expected when facing a contract upgrade or restart.
Test files:
For the liquidation compatibility bootstrap test we were forced to copy the original source code so we could initiate the test environment with that version and later upgrade it with the current one.
The existing CI tests have passed successfully.
Upgrade Considerations
The changes made to the inter-protocol in this PR require an upgrade to the vaultFactory contract. With this in mind, we have built and tested a core-eval proposal, as it is mentioned above.
The vaultFactory proposal installation and execution were tested in the a3p-integration, confirming the expected behavior at the EVAL stage.