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

test(fast-usdc): multichain test for forward #10963

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

samsiegart
Copy link
Contributor

closes: #10623

Description

Adds multichain-testing scenarios for:

  • insufficient LP funds; forward path
  • minted before observed; forward path
  • insufficient LP funds and forward failed

Changed the behavior of the settler to go to forwardFailed state if it tries to forward to an invalid/un-registered chain. The previous behavior was to get stuck at observed.

Also added a test advance failed (e.g. to missing chain) which is currently skipped because in the missing chain case, it actually just stays at the observed state. Should we change this to advanceFailed/forwardFailed?

Testing Considerations

Did this in multichain-testing rather than bootstrap because it's closer to a real environment. I previously observed the stuck-at-observed behavior when attempting to write a bootstrap test but couldn't figure out if it was an issue with my test logic.

@samsiegart samsiegart requested a review from a team as a code owner February 7, 2025 05:14
Copy link
Member

@0xpatrickdev 0xpatrickdev left a comment

Choose a reason for hiding this comment

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

Nice job

Comment on lines 464 to 466
// XXX Not sure if the behavior should actually be ADVANCE_FAILED.
// It only reaches that state if the destination chain is valid.
await assertTxStatus(evidence.txHash, 'OBSERVED');
Copy link
Member

Choose a reason for hiding this comment

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

This is expected with the current implementation* - we'll only see AdvanceFailed if an advance was actually attempted. Here it seems chainHub.makeChainAddress, a precondition step, is failing since the ChainInfo / corresponding bech32 prefix is not present.

An approach to get AdvanceFailed in the test would be to add fake cosmos chain info (by extending commonBuilderOpts.chainInfo. If the connections or asset info are missing, this should trigger the transferHandler.onRejected block (AdvanceFailed). If that info is present but the connection/channel doesn't exist in the environment, it should also trigger a failure from golang.

*I wonder if it's worth using .skipAdvance instead of .observe in the advancer's catch block when pre-condition checks fail. We could serialize the error to vstorage for observability.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Just added the chain info and asserted ADVANCE_FAILED now that #10980 is merged, it worked as expected.

I wonder if it's worth using .skipAdvance instead of .observe in the advancer's catch block when pre-condition checks fail. We could serialize the error to vstorage for observability.

I'm impartial to that. I think it ends up forward failed either way right? But we'd find out sooner I guess if we serialize the error. Yea maybe it's better. Can that be a follow-up on this PR?

Copy link
Member

Choose a reason for hiding this comment

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

Can that be a follow-up on this PR?

Definitely, we should create a ticket if we think it's worth it. The main advantage I see is error/pre-condition observability via vstorage instead of swingset logs.

multichain-testing/test/fast-usdc/fast-usdc.test.ts Outdated Show resolved Hide resolved
multichain-testing/test/fast-usdc/fast-usdc.test.ts Outdated Show resolved Hide resolved
Comment on lines +341 to +348
let dest;
try {
dest = chainHub.makeChainAddress(EUD);
} catch (e) {
log('⚠️ forward transfer failed!', e, txHash);
return statusManager.forwarded(txHash, false);
}
Copy link
Member

Choose a reason for hiding this comment

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

👍

Copy link
Member

Choose a reason for hiding this comment

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

The mutable dest is a smell.

Not a blocker for this testing PR, but I think we need a more general error handling solution.

Also not a blocker but this change should not be part of a test commit. It's a runtime change, specifically a fix.

Copy link
Member

Choose a reason for hiding this comment

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

previously observed the stuck-at-observed behavior when attempting to write a bootstrap test

Was that bootstrap test hurdle due to the problem here? I.e. could we port these multichain-testing tests to bootstrap style and they'll work?

We might want to do that, to help uncover where errors are not handled correctly (eg where the test can't be written, like you ran into)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Could we port these multichain-testing tests to bootstrap style and they'll work?

I'm not sure unless I try. Maybe I can follow up after this PR?

Copy link
Member

Choose a reason for hiding this comment

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

If that's the case let's wait until #10811

Copy link

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

Deploying agoric-sdk with  Cloudflare Pages  Cloudflare Pages

Latest commit: a1f13a5
Status: ✅  Deploy successful!
Preview URL: https://6dab6bb2.agoric-sdk.pages.dev
Branch Preview URL: https://test-forward-fail.agoric-sdk.pages.dev

View logs

Comment on lines +342 to +348
let dest;
try {
dest = chainHub.makeChainAddress(EUD);
} catch (e) {
log('⚠️ forward transfer failed!', e, txHash);
return statusManager.forwarded(txHash, false);
}
Copy link
Member

Choose a reason for hiding this comment

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

statusManager.forwarded is void so we don't need to return it. Let's keep the const. One way:

Suggested change
let dest;
try {
dest = chainHub.makeChainAddress(EUD);
} catch (e) {
log('⚠️ forward transfer failed!', e, txHash);
return statusManager.forwarded(txHash, false);
}
const dest = (() => {
try {
return chainHub.makeChainAddress(EUD);
} catch (e) {
log('⚠️ forward transfer failed!', e, txHash);
statusManager.forwarded(txHash, false);
return null;
}});
if (!dest) return;

Though actually it looks like the log message should apply if any of this function threw, so best to wrap the whole thing in this try/catch.

Copy link
Member

Choose a reason for hiding this comment

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

Separately, this change is appearing in a test commit but it changes the runtime behavior. It's a fix or feat.

Comment on lines +24 to +25
const maxRetries = 5;
const retryDelayMS = 500;
Copy link
Member

Choose a reason for hiding this comment

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

don't we have a general "retry promise up to N times with M delay" utility? cc @dckc

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.

fusdc: bootstrap tx observability coverage
3 participants