1
1
import djson from '../../lib/djson.js' ;
2
2
3
+ const missingSyscall = Symbol ( 'missing transcript syscall' ) ;
4
+ const extraSyscall = Symbol ( 'extra transcript syscall' ) ;
5
+
6
+ /** @typedef {typeof missingSyscall | typeof extraSyscall | Error | undefined } CompareSyscallsResult */
7
+
8
+ /**
9
+ * @param {any } vatID
10
+ * @param {object } originalSyscall
11
+ * @param {object } newSyscall
12
+ * @returns {CompareSyscallsResult }
13
+ */
3
14
export function requireIdentical ( vatID , originalSyscall , newSyscall ) {
4
15
if ( djson . stringify ( originalSyscall ) !== djson . stringify ( newSyscall ) ) {
5
16
console . error ( `anachrophobia strikes vat ${ vatID } ` ) ;
@@ -10,6 +21,39 @@ export function requireIdentical(vatID, originalSyscall, newSyscall) {
10
21
return undefined ;
11
22
}
12
23
24
+ const vcSyscallRE = / ^ v c \. \d + \. \| (?: s c h e m a t a | l a b e l ) $ / ;
25
+
26
+ /**
27
+ * @param {any } vatID
28
+ * @param {object } originalSyscall
29
+ * @param {object } newSyscall
30
+ * @returns {CompareSyscallsResult }
31
+ */
32
+ export function requireIdenticalExceptStableVCSyscalls (
33
+ vatID ,
34
+ originalSyscall ,
35
+ newSyscall ,
36
+ ) {
37
+ const error = requireIdentical ( vatID , originalSyscall , newSyscall ) ;
38
+
39
+ if ( error ) {
40
+ if (
41
+ originalSyscall [ 0 ] === 'vatstoreGet' &&
42
+ vcSyscallRE . test ( originalSyscall [ 1 ] )
43
+ ) {
44
+ console . warn ( ` mitigation: ignoring extra vc syscall` ) ;
45
+ return extraSyscall ;
46
+ }
47
+
48
+ if ( newSyscall [ 0 ] === 'vatstoreGet' && vcSyscallRE . test ( newSyscall [ 1 ] ) ) {
49
+ console . warn ( ` mitigation: falling through to syscall handler` ) ;
50
+ return missingSyscall ;
51
+ }
52
+ }
53
+
54
+ return error ;
55
+ }
56
+
13
57
export function makeTranscriptManager (
14
58
vatKeeper ,
15
59
vatID ,
@@ -59,13 +103,31 @@ export function makeTranscriptManager(
59
103
let replayError ;
60
104
61
105
function simulateSyscall ( newSyscall ) {
62
- const s = playbackSyscalls . shift ( ) ;
63
- const newReplayError = compareSyscalls ( vatID , s . d , newSyscall ) ;
64
- if ( newReplayError ) {
65
- replayError = newReplayError ;
66
- throw replayError ;
106
+ while ( playbackSyscalls . length ) {
107
+ const compareError = compareSyscalls (
108
+ vatID ,
109
+ playbackSyscalls [ 0 ] . d ,
110
+ newSyscall ,
111
+ ) ;
112
+
113
+ if ( compareError === missingSyscall ) {
114
+ return undefined ;
115
+ }
116
+
117
+ const s = playbackSyscalls . shift ( ) ;
118
+
119
+ if ( ! compareError ) {
120
+ return s . response ;
121
+ } else if ( compareError !== extraSyscall ) {
122
+ replayError = compareError ;
123
+ break ;
124
+ }
125
+ }
126
+
127
+ if ( ! replayError ) {
128
+ replayError = new Error ( `historical inaccuracy in replay of ${ vatID } ` ) ;
67
129
}
68
- return s . response ;
130
+ throw replayError ;
69
131
}
70
132
71
133
function finishReplayDelivery ( dnum ) {
0 commit comments