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

5346 replace uses of makeNotifierKit with makeNotifierFromSubscriber #5704

Merged
merged 10 commits into from
Jul 18, 2022

Conversation

turadg
Copy link
Member

@turadg turadg commented Jun 30, 2022

refs: #5346

Description

This with #5739 will enable #5386

This one removes makeNotifierKit from VaultFactory without changing its API. Next will update the external API to provide Subscriber, for off-chain reads.

Review recommendation: by commit

Security Considerations

--

Documentation Considerations

--

Testing Considerations

Tests needed updates for refactors, but there should be no change in behavior.
Also test locally agoric start --reset to ensure sim-chain hasn't broken on making storageNode and marshaller no longer optional.

Comment on lines 74 to 77
if (!storageNode) {
return {};
}
return E(storageNode).getStoreKey();
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 surprised by this divergence between storageNode being falsy vs. fulfilling with a falsy value, but it probably won't come up in practice.

Copy link
Member Author

Choose a reason for hiding this comment

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

do you mean you'd expect this to return falsy when storageNode is falsy? agreed. I tried returning null but ran into a type error.

I'll leave this conversation open to come back to it. Let me know if you're talking about somethign else

Copy link
Member

Choose a reason for hiding this comment

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

That, and also that a falsy storageNode is accepted while a storageNode that resolves to a falsy value (e.g., Promise.resolve(undefined)) results in an exception. I think this also intersects my concern about allowing invocation without a valid storage node, which seems to unnecessarily complicate things (e.g., note how the output from getStoreKey is meaningless in such a configuration).

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 agree with the perspective. In production, the storageNode and marshaller should always be there so it would be fine to require it. In tests, they aren't always. I think it would be better to solve that, but pragmatically I'm not sure it's worth it.

If I can't remove the kludge in the tests, I'll at least remove it from @agoric/notifier and make the contracts deal with it.

Copy link
Member

Choose a reason for hiding this comment

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

In production, the storageNode and marshaller should always be there

We have the sim chain, which while perhaps not production, is supported for smart contract development work. In the sim chain, there's no chainStorage.

Copy link
Member Author

Choose a reason for hiding this comment

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

Thanks, that's the thing I was trying to remember. Since it's a "sim" chain, would it be reasonable to simulate chainStorage? E.g. in-memory stoageNode, identity marshaller.

Copy link
Member

Choose a reason for hiding this comment

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

oh. yeah. in-memory chainStorage would be great.

identity doesn't work as a marshaller, cuz the output has to be a string and the input is not constrained that way. But I think you can always use a vanilla output from makeMarshal().

Copy link
Member Author

Choose a reason for hiding this comment

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

Made it required and updated bootstrap to always provide it cbaa70b, falling back to a no-op "NullStorageNode" when ChainStorage isn't available.

packages/notifier/src/storesub.js Outdated Show resolved Hide resolved
packages/notifier/src/storesub.js Outdated Show resolved Hide resolved
packages/notifier/src/storesub.js Outdated Show resolved Hide resolved
packages/notifier/src/storesub.js Outdated Show resolved Hide resolved
packages/notifier/src/types.js Outdated Show resolved Hide resolved
publisher.publish(initialValue);
const storesub = makeStoredSubscriber(subscriber, storage);

t.deepEqual(await E(storesub).getStoreKey(), await E(storage).getStoreKey());
Copy link
Member

Choose a reason for hiding this comment

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

This may be highlighting a gap in makeFakeStorage; I would expect the key to be defined as part of its initialization rather than dynamic like this.

packages/notifier/test/test-stored-subscription.js Outdated Show resolved Hide resolved
packages/notifier/test/test-stored-subscription.js Outdated Show resolved Hide resolved
@dckc
Copy link
Member

dckc commented Jul 12, 2022

use case: list of vaults by risk

cc @btulloh

@dckc
Copy link
Member

dckc commented Jul 12, 2022

Where is the code that makes a published.vault.23423423432 thingy? Or is that yet to be done?

@turadg
Copy link
Member Author

turadg commented Jul 12, 2022

Where is the code that makes a published.vault.23423423432 thingy? Or is that yet to be done?

YTBD. Right now just trying to refactor existing behavior to use makeNotifierFromSubscriber. After that I can come back and put in the proper storage nodes and add tests.

@turadg turadg requested a review from gibson042 July 13, 2022 20:58
@turadg turadg changed the title ta/vault off chain 5346 replace uses of makeNotifierKit with makeNotifierFromSubsciber Jul 13, 2022
@turadg turadg changed the base branch from master to gh-5413-makeNotifierFromSubscriber July 13, 2022 22:35
Base automatically changed from gh-5413-makeNotifierFromSubscriber to master July 14, 2022 00:18
@turadg turadg requested a review from dckc July 14, 2022 15:07
@turadg turadg marked this pull request as ready for review July 14, 2022 15:07
@turadg turadg requested a review from dtribble as a code owner July 14, 2022 15:08
@turadg turadg marked this pull request as draft July 14, 2022 15:09
@turadg turadg force-pushed the ta/vault-off-chain branch 2 times, most recently from d7c5b6c to 6e2ebd5 Compare July 18, 2022 15:57
@turadg turadg marked this pull request as ready for review July 18, 2022 15:58
@turadg turadg force-pushed the ta/vault-off-chain branch 2 times, most recently from b33b192 to cbaa70b Compare July 18, 2022 17:39
@turadg turadg added the automerge:rebase Automatically rebase updates, then merge label Jul 18, 2022
@turadg turadg changed the title 5346 replace uses of makeNotifierKit with makeNotifierFromSubsciber 5346 replace uses of makeNotifierKit with makeNotifierFromSubscriber Jul 18, 2022
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 pretty good... at least: I don't see any serious problems.

I'm a little fuzzy on the details; I'm relying somewhat on test coverage, static typing, and discussion with @gibson042 and co.

packages/run-protocol/src/vaultFactory/vault.js Outdated Show resolved Hide resolved
Comment on lines 584 to 591
getNotifier: ({ state }) => state.assetNotifier,
getNotifier: ({ state }) => makeNotifierFromSubscriber(state.assetSubscriber),
Copy link
Member

Choose a reason for hiding this comment

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

Perhaps add a "we make a new notifier on each call that has no memory of previous states" comment?

The difference between these is subtle. I was a about to ask why we make a new one on each call when I remembered the whole prefix-lossy concept.

Comment on lines 668 to 675
getNotifier: ({ state }) => state.assetNotifier,
getNotifier: ({ state }) => state.assetSubscriber,
Copy link
Member

Choose a reason for hiding this comment

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

is this an internal API? rename it to getSubscriber?

Copy link
Member

Choose a reason for hiding this comment

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

looks like it got renamed later

@@ -662,7 +666,8 @@ test('update liquidator', async t => {
}),
);
await eventLoopIteration();
govNotify = await d.managerNotified();
// ??? why is AT_NEXT necessary now
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 know; I wonder if I'm sufficiently up-to-speed to review this...

Copy link
Member

Choose a reason for hiding this comment

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

looks like that went away in a later commit

*/
export const makeVaultKit = (vault, assetSubscriber) => {
const { holder, helper } = makeVaultHolder(vault);
const vaultKit = harden({
publicNotifiers: {
vault: holder.getNotifier(),
asset: assetSubscriber,
asset: makeNotifierFromSubscriber(assetSubscriber),
Copy link
Member

Choose a reason for hiding this comment

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

we make this notifier just once? not a new prefix-lossy one on demand?

Copy link
Member Author

Choose a reason for hiding this comment

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

right, this is interim. the contract shouldn't be making Notifiers at all because that costs state tracking. Change in next PR.

@@ -50,7 +50,7 @@ export async function start(zcf, privateArgs) {

const { zcfSeat: stage } = zcf.makeEmptySeatKit();

const { notifier: managerNotifier } = makeNotifierKit();
const { subscriber: assetSubscriber } = makePublishKit();
Copy link
Member

Choose a reason for hiding this comment

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

we throw away the publisher? how does it every get updated?

Copy link
Member Author

Choose a reason for hiding this comment

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

It doesn't, this is the fake contract

locked: aeth.makeEmpty(),
updateCount: undefined,
},
// ??? why is AT_NEXT necessary now
Copy link
Member

Choose a reason for hiding this comment

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

again, good question

* @property {ERef<Notifier<Timestamp>>} notifier
* @property {ERef<Notifier<unknown>>} notifier
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 a relaxation of a type constraint? Any particular reason?

Copy link
Member Author

Choose a reason for hiding this comment

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

It was wrong

chainStorageP.resolve(undefined);
chainStorageP.resolve(null);
Copy link
Member

Choose a reason for hiding this comment

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

why change undefined to null?

You were considering an in-memory chainStorage; that didn't work out?

Copy link
Member Author

Choose a reason for hiding this comment

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

Because when there's no chain storage available, it's defined to be missing. I think that's better expressed as null.

@mergify mergify bot merged commit 00e3c5c into master Jul 18, 2022
@mergify mergify bot deleted the ta/vault-off-chain branch July 18, 2022 21:17
@turadg turadg mentioned this pull request Jul 18, 2022
1 task
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
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants