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

Internal JSDoc for fastUSDC and state transition diagram #11061

Open
wants to merge 3 commits into
base: master
Choose a base branch
from

Conversation

Chris-Hibbert
Copy link
Contributor

Description

Add some prose description about how Advancer and Settler work together, and improve the state transition diagram.

Security Considerations

None

Scaling Considerations

None

Documentation Considerations

Internal documentation only. No implications for user docs.

Testing Considerations

None

Upgrade Considerations

None

@Chris-Hibbert Chris-Hibbert added documentation Improvements or additions to documentation code-style defensive correctness patterns; readability thru consistency labels Feb 27, 2025
@Chris-Hibbert Chris-Hibbert self-assigned this Feb 27, 2025
@Chris-Hibbert Chris-Hibbert requested a review from a team as a code owner February 27, 2025 01:28
Copy link

cloudflare-workers-and-pages bot commented Feb 27, 2025

Deploying agoric-sdk with  Cloudflare Pages  Cloudflare Pages

Latest commit: 3a43f53
Status: ✅  Deploy successful!
Preview URL: https://93c8ec95.agoric-sdk.pages.dev
Branch Preview URL: https://cth-fastusdc-doc.agoric-sdk.pages.dev

View logs

@Chris-Hibbert
Copy link
Contributor Author

@0xpatrickdev, would you mind giving me an initial review? Once you've made a pass over it, I'll ask the rest of the team to also look.

@@ -17,6 +17,12 @@ import {
} from '../type-guards.js';
import { makeFeeTools } from '../utils/fees.js';

/**
* @file Advancer subscribes (handleTransactionEvent) to events published by the
Copy link
Member

@dckc dckc Feb 27, 2025

Choose a reason for hiding this comment

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

@file docs don't tend to show up when navigating code in an IDE, generating docs, etc. How about putting this on prepareAdvancer?

Copy link
Member

Choose a reason for hiding this comment

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

a 1-line /** @file main export: @see {prepareAdvancer} */ at the top could help when looking at the file itself.

Copy link
Member

Choose a reason for hiding this comment

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

I think this @file comment is good but file-level comments should be at the top of the file

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

* Add a new transaction with OBSERVED status
* Add a new transaction with OBSERVED status.
*
* This message isn't currently being sent.
Copy link
Member

Choose a reason for hiding this comment

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

really? it's not?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Please convince me I'm wrong. I couldn't find any instances of it.

Copy link
Member

Choose a reason for hiding this comment

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

I only see it in tests.

I wonder if this is left-over from a design change.

Copy link
Member

@turadg turadg Feb 27, 2025

Choose a reason for hiding this comment

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

Changed in,

Let's remove the function since it's not used.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

Copy link
Member

@dckc dckc left a comment

Choose a reason for hiding this comment

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

looks useful

@Chris-Hibbert Chris-Hibbert requested a review from turadg February 27, 2025 18:53
Advancing --> AdvanceFailed
Forwarding --> ForwardFailed
```
[*] --> AdvanceSkipped : Risks identified
Copy link
Member

Choose a reason for hiding this comment

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

Please retain the Observed state as it is part of the sequence written to vstorage:

const publishEvidence = (hash, evidence) => {
// Don't await, just writing to vstorage.
void publishTxnRecord(
hash,
harden({ evidence, status: TxStatus.Observed }),
);
};

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

[*] --> Advancing : No risks, can advance
[*] --> Forwarding* : No risks, Mint deposited before advance

state Advancer {
Copy link
Member

Choose a reason for hiding this comment

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

this works visually but if someone knows this syntax, composite states, they might thing that these are composite states.

It's all states of the Transaction and not a composite. The boxes indicate what exo can set transition to that state.

I'm not sure that's useful but if you want to keep it please clarify in a comment on this sytnax.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I thought it was clarifying to separate advancer actions from settler actions, but I can see how calling them composites would be confusing.

I also tried to find a way to use different colors for actions in Advancer and Settler, but I could only see how to color states, and that didn't carry the right meaning.

```
[*] --> AdvanceSkipped : Risks identified
[*] --> Advancing : No risks, can advance
[*] --> Forwarding* : No risks, Mint deposited before advance
Copy link
Member

Choose a reason for hiding this comment

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

I don't think this is accurate. If there is no observation there is no transaction to have a state

log('⚠️ tap: minted before observed', nfa, amount);
// XXX consider capturing in vstorage
// we would need a new key, as this does not have a txHash
this.state.mintedEarly.add(makeMintedEarlyKey(nfa, amount));
}

Copy link
Contributor Author

Choose a reason for hiding this comment

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

finessed.

}

Forwarding* --> Forwarded : settler.forward() succeeds
Advancing --> Advanced : advancer's transferHandler detects success
Copy link
Member

Choose a reason for hiding this comment

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

while you're bringing in more sophisticated diagram features, consider using choice for success conditions

Copy link
Contributor Author

Choose a reason for hiding this comment

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

thanks. that's hepful

Forwarding* --> ForwardFailed : settler.forward() fails
```

* There is no actual state for **Forwarding**. It is used here to represent the
Copy link
Member

Choose a reason for hiding this comment

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

maybe better expressed within the diagram as a note

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I turned Forwarding into a choice rather than a state, so I don't need the note. What do you think of this version?

It also let me get rid of the transition on "Mint deposited before Advance".

@@ -17,6 +17,12 @@ import {
} from '../type-guards.js';
import { makeFeeTools } from '../utils/fees.js';

/**
* @file Advancer subscribes (handleTransactionEvent) to events published by the
Copy link
Member

Choose a reason for hiding this comment

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

I think this @file comment is good but file-level comments should be at the top of the file

/** @param {ZCFSeat} lp */
async handle(lp) {
/** @param {ZCFSeat} lpSeat */
async handle(lpSeat) {
Copy link
Member

Choose a reason for hiding this comment

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

I lightly oppose having the type in the name. I think the existing names were clear

Copy link
Contributor Author

Choose a reason for hiding this comment

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

mint was very confusing to me. "mint" is a kind in ERTP (the shareMint is used nearby), a verb, a generic noun, and several other things. I don't know how it distinguishes the zcfSeat that hold lpShares that will be transferred to the liquidity provider.

mintedShares might be okay, but it's a seat holding shares, not the shares themselves, and it's certainly not a "mint".

Copy link
Member

Choose a reason for hiding this comment

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

Good reasons against mint but not to retain Seat. The union of our points yields: lp and sharePayout.

@@ -14,6 +14,13 @@ import {
makeNatAmountShape,
} from '../type-guards.js';

/**
* @file Settler is responsible for monitoring (receiveUpcall) deposits to the
Copy link
Member

Choose a reason for hiding this comment

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

ditto about file at top

@Chris-Hibbert Chris-Hibbert requested a review from turadg February 28, 2025 00:37
Copy link
Member

@turadg turadg left a comment

Choose a reason for hiding this comment

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

Significant improvement! The choice fields really clarify things. I never tried them before.

Approving contingent on fixing AcvancingChoice and the Shares suffix

/** @param {ZCFSeat} lp */
async handle(lp) {
/** @param {ZCFSeat} lpSeat */
async handle(lpSeat) {
Copy link
Member

Choose a reason for hiding this comment

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

Good reasons against mint but not to retain Seat. The union of our points yields: lp and sharePayout.

Advancing --> AdvanceFailed
Forwarding --> ForwardFailed
```
AcvancingChoice --> AdvanceFailed : advancer's transferHandler detects failure
Copy link
Member

Choose a reason for hiding this comment

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

typo, breaking the image.

but it's not really a choice. Please use AdvancingSuccess or something that describes the range of values.

Copy link
Member

Choose a reason for hiding this comment

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

I’m also not crazy about AdvancingChoice - it seems like a TxStatus.

We are waiting for a cross-chain call to settle here - specifically Success Ack, Error Ack, Timeout from the IBC protocol. Maybe:

Advancing --> Advanced : IBC Success Ack
Advancing --> AdvanceFailed : IBC Error Ack or Timeout

Advancing --> AdvanceFailed
Forwarding --> ForwardFailed
```
AcvancingChoice --> AdvanceFailed : advancer's transferHandler detects failure
Copy link
Member

Choose a reason for hiding this comment

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

I’m also not crazy about AdvancingChoice - it seems like a TxStatus.

We are waiting for a cross-chain call to settle here - specifically Success Ack, Error Ack, Timeout from the IBC protocol. Maybe:

Advancing --> Advanced : IBC Success Ack
Advancing --> AdvanceFailed : IBC Error Ack or Timeout

Forwarding --> ForwardFailed
```
AcvancingChoice --> AdvanceFailed : advancer's transferHandler detects failure
Forwarding --> ForwardFailed : settler.forward() fails
Copy link
Member

Choose a reason for hiding this comment

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

Should we see Forwarding? Not seeing it in the rendered diagram for some reason.

image


```mermaid
stateDiagram-v2
state Forwarding <<choice>>
state AdvancingChoice <<choice>>
Observed --> AdvanceSkipped : Risks identified
Observed --> Advancing : No risks, can advance
Observed --> Forwarding : No risks, Mint deposited before advance
Copy link
Member

@0xpatrickdev 0xpatrickdev Feb 28, 2025

Choose a reason for hiding this comment

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

Observed --> Forwarding : No risks, Mint deposited before advance

We should expand this more because it's no longer accurate. An invariant is that the contract never Forwards without seeing evidence. When Settler.receiveUpcall fires and there are no matches in StatusManager's pendingTxs, or the found match is Advancing, it goes into the mintedEarly store. Each time Advancer.handleTransactionEvent is invoked, it will call Settler.notifier.checkMintedEarly() and early return if true. checkMintedEarly will clear the item from mintedEarly and initiate a .forward(). Settler.notifier.notifyAdvancingResult, which is called at the end of the Advancing state transition, also checks mintedEarly.

@@ -103,6 +105,10 @@ export const stateShape = harden({
});

/**
* Advancer subscribes (using handleTransactionEvent) to events published by the
* transaction feed. When notified of an appropriate opportunity, it is
Copy link
Member

Choose a reason for hiding this comment

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

nb: this could be helpful for navigation:

Suggested change
* transaction feed. When notified of an appropriate opportunity, it is
* {@link TransactionFeedKit}. When notified of an appropriate opportunity, it is

With this up top:

 * @import {TransactionFeedKit} from './transaction-feed.js';


### Complete state diagram (starting from Transaction Feed into Advancer)
The Settler is responsible for monitoring (via `receiveUpcall`) deposits to the
settlementAccount. It either `disburse`s funds to the Pool (if funds were
Copy link
Member

Choose a reason for hiding this comment

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

The Settler is responsible for monitoring (via receiveUpcall) deposits to the
settlementAccount.

Is it worth mentioning how receiveUpcall works? The Settler also needs to register a handler for the settlementAccount: OrchestrationAccount - that's what sets up the events:

E(settlementAccount).monitorTransfers(settler.tap); // "tap" is any durable exo with a `receiveUpcall` handler

* Settler is responsible for monitoring (using receiveUpcall) deposits to the
* settlementAccount. It either "disburses" funds to the Pool (if funds were
* "advance"d to the payee), or "forwards" funds to the payee (if pool funds
* were not advanced).
Copy link
Member

Choose a reason for hiding this comment

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

I think it's worth mentioning:

  • it needs to register it's tap facet (receiveUpcall) via the settlementAccount so it gets events
  • something about the mintedEarly flow - we don't .forward() until notifier.checkMinted is called by the Advancer.

@@ -300,6 +307,9 @@ export const prepareSettler = (
},
self: {
/**
* The intended payee received an advance from the pool. When the funds
* are minted disburse them to the pool.
Copy link
Member

@0xpatrickdev 0xpatrickdev Feb 28, 2025

Choose a reason for hiding this comment

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

Suggested change
* are minted disburse them to the pool.
* are minted disburse them to the pool and fee seats.

observe(evidence) {
initPendingTx(evidence, PendingTxStatus.Observed);
},

Copy link
Member

Choose a reason for hiding this comment

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

Thanks. I think we also need some cleanup in status-manager.test.ts. Some tests can be removed, and others should be updated to use .advanceSkipped.

@@ -103,6 +105,10 @@ export const stateShape = harden({
});

/**
* Advancer subscribes (using handleTransactionEvent) to events published by the
* transaction feed. When notified of an appropriate opportunity, it is
* responsible for advancing funds to fastUSDC payees.
Copy link
Member

Choose a reason for hiding this comment

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

fastUSDC payees

Might be worth working in EUD.

@0xpatrickdev
Copy link
Member

0xpatrickdev commented Feb 28, 2025

@Chris-Hibbert P.S. i worked on these at one point, but they were never completed / checked in. It includes:

And this was an attempt to get everything into one diagram, but it didn't end being very readable. It was created with LLM-assistance and might contain mistakes, but i think the bulk of it is accurate:
https://gist.github.com/0xpatrickdev/d343549f12f7754e25f3f13795025583#file-diagram-md

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
code-style defensive correctness patterns; readability thru consistency documentation Improvements or additions to documentation
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants