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

feat(undelegate): use Timestamp instead of Date #9646

Merged
merged 4 commits into from
Jul 3, 2024

Conversation

0xpatrickdev
Copy link
Member

@0xpatrickdev 0xpatrickdev commented Jul 3, 2024

refs: #9042

Description

This PR primarily improves unit testing around the .undelegate() flow and was motivated by a failure (inability to decode completionTime) discovered in E2E testing.

  • Add tests for cosmos-orchestration-account staking flows using mocked IBC messages
  • Use Timestamp (from google/protobuf/timestamp.proto) instead of Date for @agoric/cosmic-proto codegen for better endo compatibility
  • Update undelegate() to use Timestamp for wakeAt() calculation

Testing Considerations

This PR includes additional tests for cosmos-orchestration-account flows.

Upgrade Considerations

This is a breaking change for @agoric/cosmic-proto, but not for the agoric namespace.

@@ -87,7 +88,9 @@ export const prepareLocalOrchestrationAccountKit = (
{
holder: HolderI,
undelegateWatcher: M.interface('undelegateWatcher', {
onFulfilled: M.call([M.splitRecord({ completionTime: M.string() })])
onFulfilled: M.call([
M.splitRecord({ completionTime: TimestampProtoShape }),
Copy link
Member Author

Choose a reason for hiding this comment

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

Using splitRecord here to make this forward compatible (cosmos v0.50 adds amount: Coin to the response: https://buf.build/cosmos/cosmos-sdk/docs/main:cosmos.staking.v1beta1#cosmos.staking.v1beta1.MsgUndelegateResponse)

Are there other places we might need to consider this approach? Should we be guarding watcher's more loosely?

Copy link
Member Author

Choose a reason for hiding this comment

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

I guess the local-orch-account is less likely to get an unexpected upgrade to v0.50, more the cosmos-orch-account. We do not have something similar in those interface guards since the value is still a base64 byte string at that point.

Copy link
Member

Choose a reason for hiding this comment

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

Good question tho. Thanks for raising and resolving.

Copy link

cloudflare-workers-and-pages bot commented Jul 3, 2024

Deploying agoric-sdk with  Cloudflare Pages  Cloudflare Pages

Latest commit: 3d4ab30
Status: ✅  Deploy successful!
Preview URL: https://a95a73a6.agoric-sdk.pages.dev
Branch Preview URL: https://pc-cosmos-orch-account-tests.agoric-sdk.pages.dev

View logs

@0xpatrickdev 0xpatrickdev force-pushed the pc/cosmos-orch-account-tests branch 4 times, most recently from ba3e74e to 433ded2 Compare July 3, 2024 13:42
@0xpatrickdev 0xpatrickdev marked this pull request as ready for review July 3, 2024 13:46
@0xpatrickdev 0xpatrickdev requested review from turadg and dckc July 3, 2024 13:46
const responseJson: JsonSafe<typeof response> = null as any;
expectType<string>(responseJson.completionTime);
// FIXME: should be a string. UNTIL: github.com/cosmology-tech/telescope/pull/632
expectType<bigint>(responseJson.completionTime.seconds);
Copy link
Member Author

Choose a reason for hiding this comment

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

FYI. didn't seem worth checking in a patch, but happy to make one

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.

Thanks for the clearly described separate commits.

Only minor issues. Approving assuming they'll be addressed before merge.

});
t.is(delegation, undefined, 'delegation returns void');

// TODO, fixme!
Copy link
Member

Choose a reason for hiding this comment

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

I was reviewing by commit so I drafted a comment asking when, then I saw the fix in a subsequent PR.

I support this style of queuing up work for other commits in the PR. Consider being more specific for the reader, e.g. FIXME in this PR

Copy link
Member Author

Choose a reason for hiding this comment

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

Acknowledged for the future

},
);

const redelgation = await E(account).redelegate(
Copy link
Member

Choose a reason for hiding this comment

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

typo

Comment on lines +174 to +185
...validatorAddr,
address: 'cosmosvaloper2test',
Copy link
Member

Choose a reason for hiding this comment

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

our composite "address" object reads so weirdly. I hope we can come up with a better name.

Copy link
Member

Choose a reason for hiding this comment

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

@@ -87,7 +88,9 @@ export const prepareLocalOrchestrationAccountKit = (
{
holder: HolderI,
undelegateWatcher: M.interface('undelegateWatcher', {
onFulfilled: M.call([M.splitRecord({ completionTime: M.string() })])
onFulfilled: M.call([
M.splitRecord({ completionTime: TimestampProtoShape }),
Copy link
Member

Choose a reason for hiding this comment

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

Good question tho. Thanks for raising and resolving.

Comment on lines +107 to +108
* for google/protobuf/timestamp.proto, not to be confused with TimestampShape
* from `@agoric/time`
Copy link
Member

Choose a reason for hiding this comment

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

excellent comment

* @param {Date} date
* @returns {bigint}
*/
export const dateInSeconds = date => BigInt(Math.floor(date.getTime() / 1000));
Copy link
Member

Choose a reason for hiding this comment

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

reduction in code affirms your idea to switch to Timestamp

Comment on lines 57 to 65
/**
* returns Timestamp record 5 seconds from unix epoch.
*/
const getCompletionTime = (): Timestamp => {
return {
seconds: UNBOND_PERIOD_SECONDS,
nanos: 0,
};
};
Copy link
Member

Choose a reason for hiding this comment

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

it's only five because of UNBOND_PERIOD_SECONDS. if someone changes that they won't know to change this comment.

the 0+ is thoughtful, but I don't think the "since unix epoch" is relevant to the test

please simplify and make more explicit what it gets

Suggested change
/**
* returns Timestamp record 5 seconds from unix epoch.
*/
const getCompletionTime = (): Timestamp => {
return {
seconds: UNBOND_PERIOD_SECONDS,
nanos: 0,
};
};
const getUnbondingTime = () => new Date(Number(UNBOND_PERIOD_SECONDS * MILLISECONDS_PER_SECOND));

Copy link
Member Author

@0xpatrickdev 0xpatrickdev Jul 3, 2024

Choose a reason for hiding this comment

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

Simplified but kept the return type a Timestamp

Copy link
Member

Choose a reason for hiding this comment

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

oh good. I made the suggestion on an earlier commit and when I pulled it to the PR level I forgot to adjust the return type

@dckc dckc requested a review from dtribble July 3, 2024 14:52
@@ -212,6 +212,13 @@ export type LiquidStakingMethods = {
liquidStake: (amount: AmountArg) => Promise<void>;
};

export type LocalAccountMethods = {
/** deposit payment from zoe to the account */
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
/** deposit payment from zoe to the account */
/** deposit payment (from zoe, for example) to the account */

Zoe isn't the only source of payments.

@@ -68,6 +68,8 @@ const sendItFn = async (
const { chainId } = info;
assert(typeof chainId === 'string', 'bad chainId');
const { [kw]: pmtP } = await withdrawFromSeat(zcf, seat, give);
// #9212 types for chain account helpers
// @ts-expect-error LCA should have .deposit() method
Copy link
Member

Choose a reason for hiding this comment

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

👏

* deposit payment from zoe to the account. For remote accounts,
* an IBC Transfer will be executed to transfer funds there.
*/
deposit: (payment: Payment<'nat'>) => Promise<void>;
Copy link
Member

Choose a reason for hiding this comment

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

cc @dtribble - change to orchestration-api.ts

Copy link
Member

Choose a reason for hiding this comment

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

cc @mitdralla too

Copy link
Member Author

Choose a reason for hiding this comment

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

Similar story to: #9591 (comment)

Copy link
Member

Choose a reason for hiding this comment

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

lgtm

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.

very nicely done!

@@ -92,7 +99,7 @@ const makeScenario = () => {

'/cosmos.staking.v1beta1.MsgBeginRedelegate': _m => {
const response = MsgBeginRedelegateResponse.fromPartial({
completionTime: new Date('2025-12-17T03:24:00Z'),
completionTime: dateToTimestamp(new Date('2025-12-17T03:24:00Z')),
Copy link
Member

Choose a reason for hiding this comment

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

here's hoping we manage to completely replace the mock stuff here with using ibc-mocks

Copy link
Member Author

@0xpatrickdev 0xpatrickdev Jul 3, 2024

Choose a reason for hiding this comment

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

Agree. It seems there's parity here with stake-ica.test.ts minus the wallet offers.

Will +1 that we should be able to use a macro and test LocalOrchestrationAccount in the same flow. Currently there are two small blockers to that:

  • LOA delegate and undelegate should accept a ChainAddress obj instead of a string
  • LOA undelegate should accept an array of delegations

Comment on lines -189 to +193
// TODO clean up date handling once we have real data
dateInSeconds(new Date(completionTime)) + maxClockSkew,
// ignore nanoseconds and just use seconds from Timestamp
BigInt(completionTime.seconds) + maxClockSkew,
Copy link
Member

Choose a reason for hiding this comment

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

👏 good to see the TODOs getting to-done.

@@ -155,17 +159,23 @@ test('delegate, undelegate, redelegate, withdrawReward', async t => {
});
t.is(delegation, undefined, 'delegation returns void');

// TODO, fixme!
Copy link
Member

Choose a reason for hiding this comment

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

👏

t.is(
await undelegateP,
undefined,
'undelegate returns void after completion_time',
Copy link
Member

Choose a reason for hiding this comment

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

you can test that it actually waited that long by racing with timer.wakeAt(expectedFullfillment - 1n)

Copy link
Member Author

Choose a reason for hiding this comment

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

Updated to include, ty. Also realized I don't need to provide a brand to the zone manual timer.

@dckc dckc requested a review from mitdralla July 3, 2024 15:12
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.

oops; some comments pending from another window

@turadg turadg added the force:integration Force integration tests to run on PR label Jul 3, 2024
- removes .deposit() from CosmosOrchestrationAccount as #9193 stipulates this will be done via an LCA
- adds LocalAccountMethods type, although unused, for documenatation purposes. and, eventually, to support #9212
- test cosmos-orchestration-account.js via stakeIca.contract.js using mocked messages
- updates typingsFormat.timestamp to 'timestamp' instead of 'date' for better SES compatability
- this Timestamp is from google/protobuf/timestamp.proto and looks like { seconds: bigint; nanos: number }
- removes dateInSeconds, as cosmic-proto now returns { seconds: bigint; nanos: number }
  - nanoseconds are ignored for the wakeAt() calculation, as these seem immaterial
- adds undelegate() tests for LOA and COA that advance timer service to verify behavior
- updates LOA to return undefined instead of a TimestampRecord on .delegate()
@0xpatrickdev 0xpatrickdev added the automerge:rebase Automatically rebase updates, then merge label Jul 3, 2024
@mergify mergify bot merged commit c2222f8 into master Jul 3, 2024
80 of 85 checks passed
@mergify mergify bot deleted the pc/cosmos-orch-account-tests branch July 3, 2024 19:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
automerge:rebase Automatically rebase updates, then merge force:integration Force integration tests to run on PR
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants