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

consider adding getCurrentTimestamp() -only timer device node #5616

Closed
warner opened this issue Jun 16, 2022 · 2 comments · Fixed by #5847
Closed

consider adding getCurrentTimestamp() -only timer device node #5616

warner opened this issue Jun 16, 2022 · 2 comments · Fixed by #5847
Labels
enhancement New feature or request SwingSet package: SwingSet

Comments

@warner
Copy link
Member

warner commented Jun 16, 2022

What is the Problem Being Solved?

@michaelfig said that the smart wallet would benefit from a way to synchronously retrieve the current timestamp.

Currently, the only way to get the current timestamp synchronously is through D(devices.timer).getLastPolled(). This is exposed asynchronously through E(timerService).getCurrentTimestamp() (hosted in vat-timer).

Both devices.timer and timerService have a lot of additional power. timerService has setWakeup and makeRepeater. And the timer device has a slew of non-ocap-safe APIs (to overcome limitations of the swingset "deviceslots" library), like deleting repeaters by their integer index.

So it might be interesting to create an object and/or a device node with a narrower API, just getCurrentTimestamp(). If hosted in vat-timer, the object would provide async access to the current time, but not any wakeup services. If hosted in device-timer, the device node would provide synchronous access to the current time, and nothing else.

Description of the Design

Security Considerations

Test Plan

@warner warner added enhancement New feature or request SwingSet package: SwingSet labels Jun 16, 2022
@warner
Copy link
Member Author

warner commented Jun 20, 2022

Another approach to consider would be a syscall.getCurrentTimestamp(). This could then be exposed via vatPowers.getCurrentTimestamp(). On the plus side, most traditional operating systems include "time" as a first-class process resource, and having synchronous access is certainly convenient for a lot of use cases. On the other hand:

  • 1: we treat access to a clock as a powerful authority, to be managed correspondingly, both because it grants a sort of coarse-grained non-determinism (otherwise confined code can behave differently depending upon non-obvious properties like when exactly you call it), and because fine-grained clocks enable otherwise-confined code to read an unpreventable covert channel emitted by fully-confined code
    • this encourages the clock to be represented with an ocap which can be passed around
    • using vatPowers would share this authority with the top-level code of every vat, unless we also add a createVat option like enableClock or something
    • however the top-level code could wrap vatPowers.getCurrentTimestamp in a separate object and then share it selectively elsewhere within the vat
  • 2: having swingset/liveslots provide a singular clock would elevate one particular source of time to a special status, which creates an attractive nuisance: contracts could say "valid until date XYZ" without also specifying the source of the timestamp, leading to disagreements and attacks when multiple sources of time are equally plausible.
    • OTOH it might be fair to say that any given swingset host application will have a single "native" source of time: for a blockchain, it would be the consensus time of each block

If we really need synchronous access, I'm more inclined to make the device node work, than a syscall/vatPowers thing. One wrinkle is that we currently need both vatPowers.D() and the device node itself, which looks like a rights-amplification pattern, but I didn't really intend it that way. We need to think through what it would mean to share the device node with confined code but not give it the D() necessary to invoke it, and whether that makes sense to maintain. In general I'd like to get rid of D() (qv #1233).

warner added a commit that referenced this issue Aug 11, 2022
vat-timer is now fully virtualized, durablized, and upgradeable. RAM
usage should be O(N) in the number of:

* pending Promise wakeups (`wakeAt`, `delay`)
* active Notifier promises (`makeNotifier`)
* active Iterator promises (`makeNotifier()[Symbol.asyncIterator]`)

Pending promises will be disconnected (rejected) during upgrade, as
usual.

All handlers and Promises will fire with the most recent timestamp
available, which (under load) may be somewhat later than the scheduled
wakeup time. However Notifiers will always report a scheduled
time (some multiple of the interval). The opaque `updateCount` used in
Notifier updates is now a time value, not a counter, so user tests
should refrain from asserting sequentiality.

Asking for a wakeup in the past or present will fire immediately.

Most API calls will accept an arbitrary Far object as a CancelToken,
which can be used to cancel the wakeup/repeater. `makeRepeater` is the
exception.

This does not change the device-timer API or implementation, however
vat-timer now only uses a single device-side wakeup, and only exposes
a single handler object, to minimize the memory usage and object
retention by the device (since devices do not participate in GC).

This introduces a `Clock` which can return time values without also
providing scheduling authority, and a `TimerBrand` which can validate
time values without providing clock or scheduling authority.

`packages/SwingSet/tools/manual-timer.js` offers a manually-driven
timer service, which can help with unit tests.

closes #5668
closes #5709
closes #4282
refs #4286
closes #4296
closes #5616
closes #5709
refs #5798
warner added a commit that referenced this issue Aug 16, 2022
vat-timer is now fully virtualized, durablized, and upgradeable. RAM
usage should be O(N) in the number of:

* pending Promise wakeups (`wakeAt`, `delay`)
* active Notifier promises (`makeNotifier`)
* active Iterator promises (`makeNotifier()[Symbol.asyncIterator]`)

Pending promises will be disconnected (rejected) during upgrade, as
usual.

All handlers and Promises will fire with the most recent timestamp
available, which (under load) may be somewhat later than the scheduled
wakeup time.

Until cancellation, Notifiers will always report a scheduled time
(i.e. `start` plus some multiple of the interval). The opaque
`updateCount` used in Notifier updates is a counter starting from 1n.
When a Notifier is cancelled, the final/"finish" value is the
timestamp of cancellation, which may or may not be a multiple of the
interval (and might be a duplicate of the last non-final value). Once
in the cancelled state, `getUpdateSince(anything)` yields `{ value:
cancellationTimestamp, updateCount: undefined }`, and the
corresponding `iterator.next()` resolves to `{ value:
cancellationTimestamp, done: true }`. Neither will ever reject their
Promises (except due to upgrade).

Asking for a wakeup in the past or present will fire immediately.

Most API calls will accept an arbitrary Far object as a CancelToken,
which can be used to cancel the wakeup/repeater. `makeRepeater` is the
exception.

This does not change the device-timer API or implementation, however
vat-timer now only uses a single device-side wakeup, and only exposes
a single handler object, to minimize the memory usage and object
retention by the device (since devices do not participate in GC).

This introduces a `Clock` which can return time values without also
providing scheduling authority, and a `TimerBrand` which can validate
time values without providing clock or scheduling
authority. Timestamps are not yet Branded, but the scaffolding is in
place.

`packages/SwingSet/tools/manual-timer.js` offers a manually-driven
timer service, which can help with unit tests.

closes #5668
closes #5709
closes #4282
refs #4286
closes #4296
closes #5616
closes #5709
refs #5798
warner added a commit that referenced this issue Aug 16, 2022
vat-timer is now fully virtualized, durablized, and upgradeable. RAM
usage should be O(N) in the number of:

* pending Promise wakeups (`wakeAt`, `delay`)
* active Notifier promises (`makeNotifier`)
* active Iterator promises (`makeNotifier()[Symbol.asyncIterator]`)

Pending promises will be disconnected (rejected) during upgrade, as
usual.

All handlers and Promises will fire with the most recent timestamp
available, which (under load) may be somewhat later than the scheduled
wakeup time.

Until cancellation, Notifiers will always report a scheduled time
(i.e. `start` plus some multiple of the interval). The opaque
`updateCount` used in Notifier updates is a counter starting from 1n.
When a Notifier is cancelled, the final/"finish" value is the
timestamp of cancellation, which may or may not be a multiple of the
interval (and might be a duplicate of the last non-final value). Once
in the cancelled state, `getUpdateSince(anything)` yields `{ value:
cancellationTimestamp, updateCount: undefined }`, and the
corresponding `iterator.next()` resolves to `{ value:
cancellationTimestamp, done: true }`. Neither will ever reject their
Promises (except due to upgrade).

Asking for a wakeup in the past or present will fire immediately.

Most API calls will accept an arbitrary Far object as a CancelToken,
which can be used to cancel the wakeup/repeater. `makeRepeater` is the
exception.

This does not change the device-timer API or implementation, however
vat-timer now only uses a single device-side wakeup, and only exposes
a single handler object, to minimize the memory usage and object
retention by the device (since devices do not participate in GC).

This introduces a `Clock` which can return time values without also
providing scheduling authority, and a `TimerBrand` which can validate
time values without providing clock or scheduling
authority. Timestamps are not yet Branded, but the scaffolding is in
place.

`packages/SwingSet/tools/manual-timer.js` offers a manually-driven
timer service, which can help with unit tests.

closes #5668
closes #5709
closes #4282
refs #4286
closes #4296
closes #5616
closes #5709
refs #5798
warner added a commit that referenced this issue Aug 16, 2022
vat-timer is now fully virtualized, durablized, and upgradeable. RAM
usage should be O(N) in the number of:

* pending Promise wakeups (`wakeAt`, `delay`)
* active Notifier promises (`makeNotifier`)
* active Iterator promises (`makeNotifier()[Symbol.asyncIterator]`)

Pending promises will be disconnected (rejected) during upgrade, as
usual.

All handlers and Promises will fire with the most recent timestamp
available, which (under load) may be somewhat later than the scheduled
wakeup time.

Until cancellation, Notifiers will always report a scheduled time
(i.e. `start` plus some multiple of the interval). The opaque
`updateCount` used in Notifier updates is a counter starting from 1n.
When a Notifier is cancelled, the final/"finish" value is the
timestamp of cancellation, which may or may not be a multiple of the
interval (and might be a duplicate of the last non-final value). Once
in the cancelled state, `getUpdateSince(anything)` yields `{ value:
cancellationTimestamp, updateCount: undefined }`, and the
corresponding `iterator.next()` resolves to `{ value:
cancellationTimestamp, done: true }`. Neither will ever reject their
Promises (except due to upgrade).

Asking for a wakeup in the past or present will fire immediately.

Most API calls will accept an arbitrary Far object as a CancelToken,
which can be used to cancel the wakeup/repeater. `makeRepeater` is the
exception.

This does not change the device-timer API or implementation, however
vat-timer now only uses a single device-side wakeup, and only exposes
a single handler object, to minimize the memory usage and object
retention by the device (since devices do not participate in GC).

This introduces a `Clock` which can return time values without also
providing scheduling authority, and a `TimerBrand` which can validate
time values without providing clock or scheduling
authority. Timestamps are not yet Branded, but the scaffolding is in
place.

`packages/SwingSet/tools/manual-timer.js` offers a manually-driven
timer service, which can help with unit tests.

closes #5668
closes #5709
closes #4282
refs #4286
closes #4296
closes #5616
closes #5709
refs #5798
warner added a commit that referenced this issue Aug 16, 2022
vat-timer is now fully virtualized, durablized, and upgradeable. RAM
usage should be O(N) in the number of:

* pending Promise wakeups (`wakeAt`, `delay`)
* active Notifier promises (`makeNotifier`)
* active Iterator promises (`makeNotifier()[Symbol.asyncIterator]`)

Pending promises will be disconnected (rejected) during upgrade, as
usual.

All handlers and Promises will fire with the most recent timestamp
available, which (under load) may be somewhat later than the scheduled
wakeup time.

Until cancellation, Notifiers will always report a scheduled time
(i.e. `start` plus some multiple of the interval). The opaque
`updateCount` used in Notifier updates is a counter starting from 1n.
When a Notifier is cancelled, the final/"finish" value is the
timestamp of cancellation, which may or may not be a multiple of the
interval (and might be a duplicate of the last non-final value). Once
in the cancelled state, `getUpdateSince(anything)` yields `{ value:
cancellationTimestamp, updateCount: undefined }`, and the
corresponding `iterator.next()` resolves to `{ value:
cancellationTimestamp, done: true }`. Neither will ever reject their
Promises (except due to upgrade).

Asking for a wakeup in the past or present will fire immediately.

Most API calls will accept an arbitrary Far object as a CancelToken,
which can be used to cancel the wakeup/repeater. `makeRepeater` is the
exception.

This does not change the device-timer API or implementation, however
vat-timer now only uses a single device-side wakeup, and only exposes
a single handler object, to minimize the memory usage and object
retention by the device (since devices do not participate in GC).

This introduces a `Clock` which can return time values without also
providing scheduling authority, and a `TimerBrand` which can validate
time values without providing clock or scheduling
authority. Timestamps are not yet Branded, but the scaffolding is in
place.

`packages/SwingSet/tools/manual-timer.js` offers a manually-driven
timer service, which can help with unit tests.

closes #4282
refs #4286
closes #4296
closes #5616
closes #5668
closes #5709
refs #5798
warner added a commit that referenced this issue Aug 16, 2022
vat-timer is now fully virtualized, durablized, and upgradeable. RAM
usage should be O(N) in the number of:

* pending Promise wakeups (`wakeAt`, `delay`)
* active Notifier promises (`makeNotifier`)
* active Iterator promises (`makeNotifier()[Symbol.asyncIterator]`)

Pending promises will be disconnected (rejected) during upgrade, as
usual.

All handlers and Promises will fire with the most recent timestamp
available, which (under load) may be somewhat later than the scheduled
wakeup time.

Until cancellation, Notifiers will always report a scheduled time
(i.e. `start` plus some multiple of the interval). The opaque
`updateCount` used in Notifier updates is a counter starting from 1n.
When a Notifier is cancelled, the final/"finish" value is the
timestamp of cancellation, which may or may not be a multiple of the
interval (and might be a duplicate of the last non-final value). Once
in the cancelled state, `getUpdateSince(anything)` yields `{ value:
cancellationTimestamp, updateCount: undefined }`, and the
corresponding `iterator.next()` resolves to `{ value:
cancellationTimestamp, done: true }`. Neither will ever reject their
Promises (except due to upgrade).

Asking for a wakeup in the past or present will fire immediately.

Most API calls will accept an arbitrary Far object as a CancelToken,
which can be used to cancel the wakeup/repeater. `makeRepeater` is the
exception.

This does not change the device-timer API or implementation, however
vat-timer now only uses a single device-side wakeup, and only exposes
a single handler object, to minimize the memory usage and object
retention by the device (since devices do not participate in GC).

This introduces a `Clock` which can return time values without also
providing scheduling authority, and a `TimerBrand` which can validate
time values without providing clock or scheduling
authority. Timestamps are not yet Branded, but the scaffolding is in
place.

`packages/SwingSet/tools/manual-timer.js` offers a manually-driven
timer service, which can help with unit tests.

closes #4282
refs #4286
closes #4296
closes #5616
closes #5668
closes #5709
refs #5798
warner added a commit that referenced this issue Aug 16, 2022
vat-timer is now fully virtualized, durablized, and upgradeable. RAM
usage should be O(N) in the number of:

* pending Promise wakeups (`wakeAt`, `delay`)
* active Notifier promises (`makeNotifier`)
* active Iterator promises (`makeNotifier()[Symbol.asyncIterator]`)

Pending promises will be disconnected (rejected) during upgrade, as
usual.

All handlers and Promises will fire with the most recent timestamp
available, which (under load) may be somewhat later than the scheduled
wakeup time.

Until cancellation, Notifiers will always report a scheduled time
(i.e. `start` plus some multiple of the interval). The opaque
`updateCount` used in Notifier updates is a counter starting from 1n.
When a Notifier is cancelled, the final/"finish" value is the
timestamp of cancellation, which may or may not be a multiple of the
interval (and might be a duplicate of the last non-final value). Once
in the cancelled state, `getUpdateSince(anything)` yields `{ value:
cancellationTimestamp, updateCount: undefined }`, and the
corresponding `iterator.next()` resolves to `{ value:
cancellationTimestamp, done: true }`. Neither will ever reject their
Promises (except due to upgrade).

Asking for a wakeup in the past or present will fire immediately.

Most API calls will accept an arbitrary Far object as a CancelToken,
which can be used to cancel the wakeup/repeater. `makeRepeater` is the
exception.

This does not change the device-timer API or implementation, however
vat-timer now only uses a single device-side wakeup, and only exposes
a single handler object, to minimize the memory usage and object
retention by the device (since devices do not participate in GC).

This introduces a `Clock` which can return time values without also
providing scheduling authority, and a `TimerBrand` which can validate
time values without providing clock or scheduling
authority. Timestamps are not yet Branded, but the scaffolding is in
place.

`packages/SwingSet/tools/manual-timer.js` offers a manually-driven
timer service, which can help with unit tests.

closes #4282
refs #4286
closes #4296
closes #5616
closes #5668
closes #5709
refs #5798
warner added a commit that referenced this issue Aug 19, 2022
vat-timer is now fully virtualized, durablized, and upgradeable. RAM
usage should be O(N) in the number of:

* pending Promise wakeups (`wakeAt`, `delay`)
* active Notifier promises (`makeNotifier`)
* active Iterator promises (`makeNotifier()[Symbol.asyncIterator]`)

Pending promises will be disconnected (rejected) during upgrade, as
usual.

All handlers and Promises will fire with the most recent timestamp
available, which (under load) may be somewhat later than the scheduled
wakeup time.

Until cancellation, Notifiers will always report a scheduled time
(i.e. `start` plus some multiple of the interval). The opaque
`updateCount` used in Notifier updates is a counter starting from 1n.
When a Notifier is cancelled, the final/"finish" value is the
timestamp of cancellation, which may or may not be a multiple of the
interval (and might be a duplicate of the last non-final value). Once
in the cancelled state, `getUpdateSince(anything)` yields `{ value:
cancellationTimestamp, updateCount: undefined }`, and the
corresponding `iterator.next()` resolves to `{ value:
cancellationTimestamp, done: true }`. Neither will ever reject their
Promises (except due to upgrade).

Asking for a wakeup in the past or present will fire immediately.

Most API calls will accept an arbitrary Far object as a CancelToken,
which can be used to cancel the wakeup/repeater. `makeRepeater` is the
exception.

This does not change the device-timer API or implementation, however
vat-timer now only uses a single device-side wakeup, and only exposes
a single handler object, to minimize the memory usage and object
retention by the device (since devices do not participate in GC).

This introduces a `Clock` which can return time values without also
providing scheduling authority, and a `TimerBrand` which can validate
time values without providing clock or scheduling
authority. Timestamps are not yet Branded, but the scaffolding is in
place.

`packages/SwingSet/tools/manual-timer.js` offers a manually-driven
timer service, which can help with unit tests.

closes #4282
refs #4286
closes #4296
closes #5616
closes #5668
closes #5709
refs #5798
warner added a commit that referenced this issue Aug 19, 2022
vat-timer is now fully virtualized, durablized, and upgradeable. RAM
usage should be O(N) in the number of:

* pending Promise wakeups (`wakeAt`, `delay`)
* active Notifier promises (`makeNotifier`)
* active Iterator promises (`makeNotifier()[Symbol.asyncIterator]`)

Pending promises will be disconnected (rejected) during upgrade, as
usual.

All handlers and Promises will fire with the most recent timestamp
available, which (under load) may be somewhat later than the scheduled
wakeup time.

Until cancellation, Notifiers will always report a scheduled time
(i.e. `start` plus some multiple of the interval). The opaque
`updateCount` used in Notifier updates is a counter starting from 1n.
When a Notifier is cancelled, the final/"finish" value is the
timestamp of cancellation, which may or may not be a multiple of the
interval (and might be a duplicate of the last non-final value). Once
in the cancelled state, `getUpdateSince(anything)` yields `{ value:
cancellationTimestamp, updateCount: undefined }`, and the
corresponding `iterator.next()` resolves to `{ value:
cancellationTimestamp, done: true }`. Neither will ever reject their
Promises (except due to upgrade).

Asking for a wakeup in the past or present will fire immediately.

Most API calls will accept an arbitrary Far object as a CancelToken,
which can be used to cancel the wakeup/repeater. `makeRepeater` is the
exception.

This does not change the device-timer API or implementation, however
vat-timer now only uses a single device-side wakeup, and only exposes
a single handler object, to minimize the memory usage and object
retention by the device (since devices do not participate in GC).

This introduces a `Clock` which can return time values without also
providing scheduling authority, and a `TimerBrand` which can validate
time values without providing clock or scheduling
authority. Timestamps are not yet Branded, but the scaffolding is in
place.

`packages/SwingSet/tools/manual-timer.js` offers a manually-driven
timer service, which can help with unit tests.

closes #4282
refs #4286
closes #4296
closes #5616
closes #5668
closes #5709
refs #5798
warner added a commit that referenced this issue Aug 19, 2022
vat-timer is now fully virtualized, durablized, and upgradeable. RAM
usage should be O(N) in the number of:

* pending Promise wakeups (`wakeAt`, `delay`)
* active Notifier promises (`makeNotifier`)
* active Iterator promises (`makeNotifier()[Symbol.asyncIterator]`)

Pending promises will be disconnected (rejected) during upgrade, as
usual.

All handlers and Promises will fire with the most recent timestamp
available, which (under load) may be somewhat later than the scheduled
wakeup time.

Until cancellation, Notifiers will always report a scheduled time
(i.e. `start` plus some multiple of the interval). The opaque
`updateCount` used in Notifier updates is a counter starting from 1n.
When a Notifier is cancelled, the final/"finish" value is the
timestamp of cancellation, which may or may not be a multiple of the
interval (and might be a duplicate of the last non-final value). Once
in the cancelled state, `getUpdateSince(anything)` yields `{ value:
cancellationTimestamp, updateCount: undefined }`, and the
corresponding `iterator.next()` resolves to `{ value:
cancellationTimestamp, done: true }`. Neither will ever reject their
Promises (except due to upgrade).

Asking for a wakeup in the past or present will fire immediately.

Most API calls will accept an arbitrary Far object as a CancelToken,
which can be used to cancel the wakeup/repeater. `makeRepeater` is the
exception.

This does not change the device-timer API or implementation, however
vat-timer now only uses a single device-side wakeup, and only exposes
a single handler object, to minimize the memory usage and object
retention by the device (since devices do not participate in GC).

This introduces a `Clock` which can return time values without also
providing scheduling authority, and a `TimerBrand` which can validate
time values without providing clock or scheduling
authority. Timestamps are not yet Branded, but the scaffolding is in
place.

`packages/SwingSet/tools/manual-timer.js` offers a manually-driven
timer service, which can help with unit tests.

closes #4282
refs #4286
closes #4296
closes #5616
closes #5668
closes #5709
refs #5798
@mergify mergify bot closed this as completed in 34cff5f Aug 19, 2022
@mergify mergify bot closed this as completed in #5847 Aug 19, 2022
@warner
Copy link
Member Author

warner commented Aug 19, 2022

The new timer service has a Clock which is read-only (getCurrentTimestamp() and getTimerBrand(), but no scheduling features).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request SwingSet package: SwingSet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant