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

Kernel Panic: E(agoric.chainTimerService).removeWakeup(0) #4296

Closed
b4d2 opened this issue Jan 14, 2022 · 10 comments · Fixed by #5847
Closed

Kernel Panic: E(agoric.chainTimerService).removeWakeup(0) #4296

b4d2 opened this issue Jan 14, 2022 · 10 comments · Fixed by #5847
Assignees
Labels
bug Something isn't working security SwingSet package: SwingSet z~audit-zestival Vulnerability assessment of ERTP + Zoe
Milestone

Comments

@b4d2
Copy link
Contributor

b4d2 commented Jan 14, 2022

Describe the bug

Calling E(agoric.chainTimerService).removeWakeup(0) results in immediate kernel panic

To Reproduce

Steps to reproduce the behavior:

  1. start chain: agoric start local-chain --reset
  2. start solo: agoric start local-solo --reset
  3. open repl: open -a "Google Chrome" $(agoric open --repl --no-browser | grep http)
  4. wait for chain to boot
  5. Issue E(agoric.chainTimerService).removeWakeup(0)
  6. The chain will stop due to the following stack
2022-01-14T00:19:14.461Z SwingSet: kernel: ##### KERNEL PANIC: error during syscall/device.invoke: Error: Cannot pass non-frozen objects like (an object). Use harden() #####
Logging sent error stack (Error#1)
Error#1: syscall.callNow failed, prepare to die: you killed my kernel. prepare to die
Error: syscall.callNow failed, prepare to die: you killed my kernel. prepare to die
 at apply ()
 at Error (/Users/b4d2/agoric-sdk/packages/SwingSet/src/kernel/vatManager/lockdown-subprocess-xsnap.js:7001)
 at doSyscall (/Users/b4d2/agoric-sdk/packages/SwingSet/src/kernel/vatManager/supervisor-subprocess-xsnap.js:9562)
 at (/Users/b4d2/agoric-sdk/packages/SwingSet/src/kernel/vatManager/supervisor-subprocess-xsnap.js:8913)
 at apply ()
 at apply ()
 at dispatchToHandler (/Users/b4d2/agoric-sdk/packages/SwingSet/src/kernel/vatManager/lockdown-subprocess-xsnap.js:10195)
 at (/Users/b4d2/agoric-sdk/packages/SwingSet/src/kernel/vatManager/lockdown-subprocess-xsnap.js:9834)
 at win (/Users/b4d2/agoric-sdk/packages/SwingSet/src/kernel/vatManager/lockdown-subprocess-xsnap.js:10534)
 at ()

Error#1 ERROR_NOTE: Thrown from: (Error#2) : 65 . 0
Error#1 ERROR_NOTE: Sent as error:liveSlots:v16#70001
Error#2: Event: 64.1
Error: Event: 64.1
 at construct ()
 at Error (/Users/b4d2/agoric-sdk/packages/SwingSet/src/kernel/vatManager/lockdown-subprocess-xsnap.js:7003)
 at trackTurns (/Users/b4d2/agoric-sdk/packages/SwingSet/src/kernel/vatManager/lockdown-subprocess-xsnap.js:9818)
 at handle (/Users/b4d2/agoric-sdk/packages/SwingSet/src/kernel/vatManager/lockdown-subprocess-xsnap.js:10525)
 at deliver (/Users/b4d2/agoric-sdk/packages/SwingSet/src/kernel/vatManager/supervisor-subprocess-xsnap.js:8979)
 at dispatchToUserspace (/Users/b4d2/agoric-sdk/packages/SwingSet/src/kernel/vatManager/supervisor-subprocess-xsnap.js:9296)
 at runWithoutMetering (/Users/b4d2/agoric-sdk/packages/SwingSet/src/kernel/vatManager/supervisor-subprocess-xsnap.js:9683)
 at ()

2022-01-14T00:19:14.466Z block-manager: END_BLOCK error: (Error#1)
Error#1: Cannot pass non-frozen objects like [] . Use harden()

  at passStyleOfInternal (.../marshal/src/passStyleOf.js:131:13)
  at passStyleOfRecur (.../marshal/src/passStyleOf.js:102:25)
  at passStyleOf (.../marshal/src/passStyleOf.js:180:12)
  at encode (.../marshal/src/marshal.js:159:25)
  at Object.serialize (.../marshal/src/marshal.js:266:21)
  at Object.invoke (.../swingset-vat/src/kernel/deviceSlots.js:209:34)
  at Object.invoke (.../swingset-vat/src/kernel/deviceManager.js:80:36)
  at invoke (.../swingset-vat/src/kernel/kernelSyscall.js:228:28)
  at Object.doKernelSyscall (.../swingset-vat/src/kernel/kernelSyscall.js:291:16)
  at vatSyscallHandler (.../swingset-vat/src/kernel/kernel.js:911:39)
  at Object.syscallFromWorker (.../swingset-vat/src/kernel/vatManager/manager-helper.js:251:18)
  at handleUpstream (.../swingset-vat/src/kernel/vatManager/manager-subprocess-xsnap.js:88:23)
  at handleCommand (.../swingset-vat/src/kernel/vatManager/manager-subprocess-xsnap.js:110:22)
  at runToIdle (packages/xsnap/src/xsnap.js:197:42)

portHandler threw (Error#1)
4:19PM ERR CONSENSUS FAILURE!!!

Expected behavior

Calling removeWakup with invalid arguments should not result in a kernel panic

Platform Environment

  • what OS are you using? what version of Node.js?
    macOS 12.1, node v16.13.1
  • is there anything special/unusual about your platform?
    I only have 16gb of ram
  • what version of the Agoric-SDK are you using? (run git describe --tags --always)
    72cc8d6bcf428596653593708959446fb0a29596

ref #4264

@b4d2 b4d2 added the bug Something isn't working label Jan 14, 2022
@jessysaurusrex jessysaurusrex added z~audit-zestival Vulnerability assessment of ERTP + Zoe security labels Jan 14, 2022
@erights erights added the resource-exhaustion Threats to availability from resource exhaustion attacks label Jan 18, 2022
@warner
Copy link
Member

warner commented Jan 19, 2022

That looks like you convinced vat-timer (which holds exclusive access to the timer device's root device-node) to invoke it with something that caused the timer device to return a non-harden()-ed empty list. And it looks like the device manager doesn't auto-harden() the return values (unlike liveslots, which harden()s promise resolutions on their way back out of method calls). Serialization of a non-harden()-ed value is an error. Currently, any errors thrown during a device-node invocation is kernel-fatal.

Things we should fix:

  • device invocation should auto-harden return values (although I know @erights wasn't excited about this when we added it to vats and return values)
  • errors during device invocation should cause the caller to see an error, instead of killing the entire kernel
    • (this makes me slightly nervous, since some errors mean we don't know what state the device was left in, however I think the programming model is easier overall if devices can throw errors as part of their normal or non-critical-but-accidental API)
  • the timer device code should be examined to see what provoked the empty list return, make sure it's not buggy, and pre-harden the result

@erights erights removed the resource-exhaustion Threats to availability from resource exhaustion attacks label Jan 20, 2022
@erights
Copy link
Member

erights commented Jan 20, 2022

device invocation should auto-harden return values (although I know @erights wasn't excited about this when we added it to vats and return values)

Correct. It masks errors. The current liveSlots behavior does indeed mask such errors, which possibly contributed to the coding habits causing the error here.

OTOH, the far wrapper approach I'm working towards will enable us to harden much less while still writing strongly defensive code. If it works out. It is still an experiment in progress that I hope to find the time to get back to.

@erights
Copy link
Member

erights commented Jan 20, 2022

Btw, I should admit that I have written a few such hardens myself for local convenience, fully aware that it might be masking such bugs elsewhere. We ran across one of these during the zestival.

@Tartuffo Tartuffo added the MN-1 label Jan 20, 2022
@Tartuffo
Copy link
Contributor

Tartuffo commented Feb 3, 2022

@warner @Chris-Hibbert This does not have an area label that is covered by our weekly tech / planning meetings. Can you assign the proper label? We cover: agd, agoric-cosmos, amm, core economy, cosmic-swingset, endo, getrun, governance, installation-bundling, metering, run-protocol, staking, swingset, swingset-runner, token economy, ui, wallet, zoe, zoe contract

@Tartuffo
Copy link
Contributor

Tartuffo commented Feb 5, 2022

@warner @Chris-Hibbert Bump. For proper project planning and tracking, this needs an area label covered by one of our weekly planning meetings. Please pick the appropriate one from: agd, agoric-cli, agoric-cosmos, amm, core economy, cosmic-swingset, endo, ertp, getrun, governance, installation-bundling, metering, oracle, pegasus, run-protocol, ses, staking, swingset, swingset-runner, tc39, token economy, tooling, ui, wallet, xsnap, zoe, zoe contract

@Tartuffo
Copy link
Contributor

Tartuffo commented Feb 5, 2022

This also needs an assignee.

@Chris-Hibbert Chris-Hibbert added the SwingSet package: SwingSet label Feb 7, 2022
@Chris-Hibbert
Copy link
Contributor

This is a bug in the timerService that was uncovered during Zestival. The timerService needs to be hardened against user calls with unexpected parameters.
I'm assigning to @warner. He can re-assign to whatever resource makes sense. (I'm familiar with the timerService, but my availability is low.)

@warner
Copy link
Member

warner commented Jun 25, 2022

I see an assertion in removeWakeup that should convert this kernel panic into a rejection of the removeWakeup(0) message, but I also don't see a unit test for it. So I think the task is to add one in test/timer/test-timer.js / bootstrap-timer.js.

@Tartuffo
Copy link
Contributor

Tartuffo commented Jul 20, 2022

Maybe fix this by requiring an authority to do this. And/or pull the Timer out of terms of the contract.

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 #5847 Aug 19, 2022
@mergify mergify bot closed this as completed in 34cff5f Aug 19, 2022
@warner
Copy link
Member

warner commented Aug 19, 2022

removeWakeup is no longer part of the vat-timer API.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working security SwingSet package: SwingSet z~audit-zestival Vulnerability assessment of ERTP + Zoe
Projects
None yet
Development

Successfully merging a pull request may close this issue.

7 participants