@rootzero/contracts 0.9.3 → 0.9.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Commands.sol +3 -2
- package/Core.sol +4 -3
- package/Cursors.sol +1 -1
- package/Events.sol +2 -3
- package/README.md +18 -24
- package/blocks/Cursors.sol +316 -337
- package/blocks/Keys.sol +40 -57
- package/blocks/Schema.sol +57 -208
- package/blocks/Writers.sol +376 -135
- package/commands/Base.sol +6 -48
- package/commands/Burn.sol +2 -2
- package/commands/Credit.sol +3 -3
- package/commands/Debit.sol +3 -2
- package/commands/Deposit.sol +11 -8
- package/commands/Provision.sol +11 -8
- package/commands/Transfer.sol +2 -2
- package/commands/Withdraw.sol +3 -3
- package/commands/admin/AllowAssets.sol +1 -1
- package/commands/admin/Allowance.sol +1 -1
- package/commands/admin/Authorize.sol +1 -1
- package/commands/admin/DenyAssets.sol +1 -1
- package/commands/admin/Execute.sol +7 -6
- package/commands/admin/Unauthorize.sol +1 -1
- package/core/Access.sol +11 -0
- package/core/Calls.sol +5 -5
- package/core/Context.sol +3 -4
- package/core/Host.sol +25 -20
- package/core/Payable.sol +57 -0
- package/core/Pipeline.sol +55 -0
- package/docs/Schema.md +196 -0
- package/events/Command.sol +1 -2
- package/events/Introduction.sol +22 -0
- package/events/{Piped.sol → Rooted.sol} +3 -3
- package/package.json +2 -2
- package/peer/AllowAssets.sol +1 -1
- package/peer/Allowance.sol +1 -1
- package/peer/BalancePull.sol +1 -1
- package/peer/DenyAssets.sol +1 -1
- package/peer/Pipe.sol +38 -0
- package/peer/Settle.sol +1 -1
- package/queries/Assets.sol +4 -3
- package/queries/Balances.sol +2 -1
- package/queries/Positions.sol +12 -12
- package/utils/Value.sol +8 -14
- package/commands/Pipe.sol +0 -67
- package/docs/GETTING_STARTED.md +0 -294
- package/events/Governed.sol +0 -21
- package/events/Host.sol +0 -22
- package/interfaces/IHostDiscovery.sol +0 -16
package/blocks/Cursors.sol
CHANGED
|
@@ -4,7 +4,6 @@ pragma solidity ^0.8.33;
|
|
|
4
4
|
import {AssetAmount, AccountAsset, AccountAmount, HostAmount, HostAccountAsset, Tx} from "../core/Types.sol";
|
|
5
5
|
import {Sizes} from "./Schema.sol";
|
|
6
6
|
import {Keys} from "./Keys.sol";
|
|
7
|
-
import {Writer, Writers} from "./Writers.sol";
|
|
8
7
|
|
|
9
8
|
/// @notice Zero-copy view into a calldata block stream.
|
|
10
9
|
/// All positions (`i`, `bound`) are byte offsets relative to the start of the source region.
|
|
@@ -47,6 +46,7 @@ library Cursors {
|
|
|
47
46
|
error UnexpectedValue();
|
|
48
47
|
/// @dev Prime block counts are not divisible by, or do not match, their declared group sizes.
|
|
49
48
|
error BadRatio();
|
|
49
|
+
|
|
50
50
|
// -------------------------------------------------------------------------
|
|
51
51
|
// Cursor construction and navigation
|
|
52
52
|
// -------------------------------------------------------------------------
|
|
@@ -65,6 +65,17 @@ library Cursors {
|
|
|
65
65
|
cur.len = source.length;
|
|
66
66
|
}
|
|
67
67
|
|
|
68
|
+
/// @notice Create a cursor and prime it for a grouped iteration pass.
|
|
69
|
+
/// Equivalent to `open(source)` followed by `primeRun(group)`.
|
|
70
|
+
/// @param source Calldata slice that forms the block stream.
|
|
71
|
+
/// @param group Expected block group size (e.g. 1 for single, 2 for paired).
|
|
72
|
+
/// @return cur Cursor with `bound` set to the end of the first run.
|
|
73
|
+
/// @return groups Number of block groups in the run (`prime block count / group`).
|
|
74
|
+
function init(bytes calldata source, uint group) internal pure returns (Cur memory cur, uint groups) {
|
|
75
|
+
cur = open(source);
|
|
76
|
+
(, groups) = cur.primeRun(group);
|
|
77
|
+
}
|
|
78
|
+
|
|
68
79
|
/// @notice Move the cursor to an absolute position within the source region.
|
|
69
80
|
/// @param cur Cursor to update.
|
|
70
81
|
/// @param i New read position (byte offset relative to source start).
|
|
@@ -75,6 +86,26 @@ library Cursors {
|
|
|
75
86
|
return cur;
|
|
76
87
|
}
|
|
77
88
|
|
|
89
|
+
/// @notice Advance the cursor by `n` bytes within the source region.
|
|
90
|
+
/// Reverts with `IncompleteCursor` if `n` exceeds the remaining cursor region length.
|
|
91
|
+
/// @param cur Cursor to advance.
|
|
92
|
+
/// @param n Number of bytes to skip from the current read position.
|
|
93
|
+
function skip(Cur memory cur, uint n) internal pure returns (Cur memory) {
|
|
94
|
+
if (n > cur.len - cur.i) revert IncompleteCursor();
|
|
95
|
+
cur.i += n;
|
|
96
|
+
return cur;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/// @notice Advance the cursor to a later absolute position within the source region.
|
|
100
|
+
/// Reverts with `IncompleteCursor` if `i` exceeds the cursor region length or is before `cur.i`.
|
|
101
|
+
/// @param cur Cursor to advance.
|
|
102
|
+
/// @param i New read position (byte offset relative to source start).
|
|
103
|
+
function skipTo(Cur memory cur, uint i) internal pure returns (Cur memory) {
|
|
104
|
+
if (i > cur.len || cur.i > i) revert IncompleteCursor();
|
|
105
|
+
cur.i = i;
|
|
106
|
+
return cur;
|
|
107
|
+
}
|
|
108
|
+
|
|
78
109
|
/// @notice Create a subcursor over the half-open range `[from, to)` within the source region.
|
|
79
110
|
/// The returned cursor starts at position zero within that sliced region.
|
|
80
111
|
/// @param cur Source cursor.
|
|
@@ -103,7 +134,19 @@ library Cursors {
|
|
|
103
134
|
/// @param to End byte offset within the source region (exclusive).
|
|
104
135
|
/// @return data Calldata view over the requested sub-range.
|
|
105
136
|
function raw(Cur memory cur, uint from, uint to) internal pure returns (bytes calldata data) {
|
|
106
|
-
|
|
137
|
+
if (from > to || to > cur.len) revert MalformedBlocks();
|
|
138
|
+
if (cur.len > msg.data.length || cur.offset > msg.data.length - cur.len) revert MalformedBlocks();
|
|
139
|
+
data = msg.data[cur.offset + from:cur.offset + to];
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/// @notice Hash a sub-range of the cursor region.
|
|
143
|
+
/// Does not advance the cursor; `from` and `to` are relative to the source region.
|
|
144
|
+
/// @param cur Source cursor.
|
|
145
|
+
/// @param from Start byte offset within the source region (inclusive).
|
|
146
|
+
/// @param to End byte offset within the source region (exclusive).
|
|
147
|
+
/// @return digest Keccak256 hash of the requested sub-range.
|
|
148
|
+
function hash(Cur memory cur, uint from, uint to) internal pure returns (bytes32 digest) {
|
|
149
|
+
digest = keccak256(cur.raw(from, to));
|
|
107
150
|
}
|
|
108
151
|
|
|
109
152
|
/// @notice Read a block header at position `i` without advancing the cursor.
|
|
@@ -112,11 +155,11 @@ library Cursors {
|
|
|
112
155
|
/// @return key Four-byte block type identifier.
|
|
113
156
|
/// @return len Payload byte length declared in the header.
|
|
114
157
|
function peek(Cur memory cur, uint i) internal pure returns (bytes4 key, uint len) {
|
|
115
|
-
if (i +
|
|
158
|
+
if (i + Sizes.Header > cur.len) revert MalformedBlocks();
|
|
116
159
|
uint abs = cur.offset + i;
|
|
117
160
|
key = bytes4(msg.data[abs:abs + 4]);
|
|
118
161
|
len = uint32(bytes4(msg.data[abs + 4:abs + 8]));
|
|
119
|
-
if (i +
|
|
162
|
+
if (i + Sizes.Header + len > cur.len) revert MalformedBlocks();
|
|
120
163
|
}
|
|
121
164
|
|
|
122
165
|
/// @notice Return the byte offset immediately past the block at the current cursor position.
|
|
@@ -128,34 +171,49 @@ library Cursors {
|
|
|
128
171
|
return cur.i + Sizes.Header + len;
|
|
129
172
|
}
|
|
130
173
|
|
|
174
|
+
/// @notice Return true if position `i` is at a block header with the given key.
|
|
175
|
+
/// Returns false when `i` is out of bounds or the key differs.
|
|
176
|
+
/// @param cur Source cursor.
|
|
177
|
+
/// @param i Byte offset of the block header within the source region.
|
|
178
|
+
/// @param key Expected block type identifier.
|
|
179
|
+
/// @return Whether the block header at `i` uses `key`.
|
|
180
|
+
function hasAt(Cur memory cur, uint i, bytes4 key) internal pure returns (bool) {
|
|
181
|
+
if (i > cur.len || Sizes.Header > cur.len - i) return false;
|
|
182
|
+
uint abs = cur.offset + i;
|
|
183
|
+
return bytes4(msg.data[abs:abs + 4]) == key;
|
|
184
|
+
}
|
|
185
|
+
|
|
131
186
|
/// @notice Return true if the current cursor position is at a block header with the given key.
|
|
132
187
|
/// Returns false when `cur.i` is out of bounds or the key differs.
|
|
133
188
|
/// @param cur Source cursor.
|
|
134
189
|
/// @param key Expected block type identifier.
|
|
135
190
|
/// @return Whether the block header at `cur.i` uses `key`.
|
|
136
191
|
function isAt(Cur memory cur, bytes4 key) internal pure returns (bool) {
|
|
137
|
-
|
|
138
|
-
uint abs = cur.offset + cur.i;
|
|
139
|
-
return bytes4(msg.data[abs:abs + 4]) == key;
|
|
192
|
+
return cur.hasAt(cur.i, key);
|
|
140
193
|
}
|
|
141
194
|
|
|
142
|
-
/// @notice
|
|
143
|
-
///
|
|
144
|
-
///
|
|
145
|
-
///
|
|
146
|
-
/// @param
|
|
147
|
-
/// @
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
195
|
+
/// @notice Enter a block at the current position and return its next offset.
|
|
196
|
+
/// Advances `cur.i` past the block header so the payload can be parsed
|
|
197
|
+
/// directly from the same cursor. The returned `next` is the byte offset
|
|
198
|
+
/// immediately after the block payload, relative to the current cursor region.
|
|
199
|
+
/// @param cur Cursor positioned at the expected block; advanced past the 8-byte header.
|
|
200
|
+
/// @param key Expected block key.
|
|
201
|
+
/// @param min Minimum acceptable payload length.
|
|
202
|
+
/// @param max Maximum acceptable payload length; 0 means unbounded.
|
|
203
|
+
/// @return next Byte offset immediately after the block payload.
|
|
204
|
+
function enter(Cur memory cur, bytes4 key, uint min, uint max) internal pure returns (uint next) {
|
|
205
|
+
(bytes4 current, uint len) = peek(cur, cur.i);
|
|
206
|
+
if (current != key) revert InvalidBlock();
|
|
207
|
+
if (len < min || (max != 0 && len > max)) revert InvalidBlock();
|
|
208
|
+
next = cur.i + Sizes.Header + len;
|
|
209
|
+
cur.i += Sizes.Header;
|
|
153
210
|
}
|
|
154
211
|
|
|
155
212
|
/// @notice Validate a block at position `i` and return its payload location.
|
|
156
213
|
/// Does not advance the cursor.
|
|
157
214
|
/// @param cur Source cursor.
|
|
158
215
|
/// @param i Byte offset of the block within the source region.
|
|
216
|
+
/// @param end Required next offset after the block; 0 means no exact-end check.
|
|
159
217
|
/// @param key Expected block type key; reverts if actual key differs.
|
|
160
218
|
/// @param min Minimum acceptable payload length (inclusive).
|
|
161
219
|
/// @param max Maximum acceptable payload length (inclusive); 0 means unbounded.
|
|
@@ -164,15 +222,30 @@ library Cursors {
|
|
|
164
222
|
function expect(
|
|
165
223
|
Cur memory cur,
|
|
166
224
|
uint i,
|
|
225
|
+
uint end,
|
|
167
226
|
bytes4 key,
|
|
168
227
|
uint min,
|
|
169
228
|
uint max
|
|
170
229
|
) internal pure returns (uint abs, uint next) {
|
|
171
230
|
(bytes4 current, uint len) = peek(cur, i);
|
|
172
231
|
if (current != key) revert InvalidBlock();
|
|
173
|
-
abs = cur.offset + i + 8;
|
|
174
|
-
next = i + 8 + len;
|
|
175
232
|
if (len < min || (max != 0 && len > max)) revert InvalidBlock();
|
|
233
|
+
abs = cur.offset + i + Sizes.Header;
|
|
234
|
+
next = i + Sizes.Header + len;
|
|
235
|
+
if (end != 0 && next != end) revert IncompleteCursor();
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
/// @notice Validate and consume the current block, advancing `cur.i` past it.
|
|
239
|
+
/// @param cur Cursor to advance.
|
|
240
|
+
/// @param end Required next offset after the block; 0 means no exact-end check.
|
|
241
|
+
/// @param key Expected block type key.
|
|
242
|
+
/// @param min Minimum payload length.
|
|
243
|
+
/// @param max Maximum payload length (0 = unbounded).
|
|
244
|
+
/// @return abs Absolute calldata offset of the payload start.
|
|
245
|
+
function consume(Cur memory cur, uint end, bytes4 key, uint min, uint max) internal pure returns (uint abs) {
|
|
246
|
+
uint next;
|
|
247
|
+
(abs, next) = expect(cur, cur.i, end, key, min, max);
|
|
248
|
+
cur.i = next;
|
|
176
249
|
}
|
|
177
250
|
|
|
178
251
|
/// @notice Count consecutive blocks of the same key starting at `i`.
|
|
@@ -186,7 +259,7 @@ library Cursors {
|
|
|
186
259
|
while (next < cur.len) {
|
|
187
260
|
(bytes4 current, uint len) = peek(cur, next);
|
|
188
261
|
if (current != key) break;
|
|
189
|
-
next +=
|
|
262
|
+
next += Sizes.Header + len;
|
|
190
263
|
|
|
191
264
|
unchecked {
|
|
192
265
|
++total;
|
|
@@ -197,20 +270,19 @@ library Cursors {
|
|
|
197
270
|
/// @notice Initialise the cursor for a grouped iteration pass.
|
|
198
271
|
/// Reads the key of the first block, counts the consecutive run of that key,
|
|
199
272
|
/// stores the run end in `cur.bound`, validates that the count is a
|
|
200
|
-
/// multiple of `group`, and returns
|
|
201
|
-
/// normalized quotient (`count / group`).
|
|
273
|
+
/// multiple of `group`, and returns the run key and normalized group count.
|
|
202
274
|
/// @param cur Cursor to prime; `cur.bound` is updated in place.
|
|
203
275
|
/// @param group Expected group size (e.g. 1 for single-asset, 2 for paired input/output).
|
|
204
276
|
/// @return key Block type identifier of the run.
|
|
205
|
-
/// @return
|
|
206
|
-
|
|
207
|
-
function primeRun(Cur memory cur, uint group) internal pure returns (bytes4 key, uint count, uint quotient) {
|
|
277
|
+
/// @return groups Number of groups represented by the run (`block count / group`).
|
|
278
|
+
function primeRun(Cur memory cur, uint group) internal pure returns (bytes4 key, uint groups) {
|
|
208
279
|
if (group == 0) revert ZeroGroup();
|
|
209
280
|
key = cur.i + 4 > cur.len ? bytes4(0) : bytes4(msg.data[cur.offset + cur.i:cur.offset + cur.i + 4]);
|
|
281
|
+
uint count;
|
|
210
282
|
(count, cur.bound) = countRun(cur, cur.i, key);
|
|
211
283
|
if (count == 0) revert ZeroCursor();
|
|
212
284
|
if (count % group != 0) revert BadRatio();
|
|
213
|
-
|
|
285
|
+
groups = count / group;
|
|
214
286
|
}
|
|
215
287
|
|
|
216
288
|
/// @notice Scan forward from `i` for the first block matching `key`.
|
|
@@ -222,7 +294,7 @@ library Cursors {
|
|
|
222
294
|
while (i < cur.len) {
|
|
223
295
|
(bytes4 current, uint len) = peek(cur, i);
|
|
224
296
|
if (current == key) return i;
|
|
225
|
-
i +=
|
|
297
|
+
i += Sizes.Header + len;
|
|
226
298
|
}
|
|
227
299
|
return cur.len;
|
|
228
300
|
}
|
|
@@ -235,29 +307,6 @@ library Cursors {
|
|
|
235
307
|
return find(cur, cur.i, key);
|
|
236
308
|
}
|
|
237
309
|
|
|
238
|
-
/// @notice Validate and consume the current block, advancing `cur.i` past it.
|
|
239
|
-
/// @param cur Cursor to advance.
|
|
240
|
-
/// @param key Expected block type key.
|
|
241
|
-
/// @param min Minimum payload length.
|
|
242
|
-
/// @param max Maximum payload length (0 = unbounded).
|
|
243
|
-
/// @return abs Absolute calldata offset of the payload start.
|
|
244
|
-
function consume(Cur memory cur, bytes4 key, uint min, uint max) internal pure returns (uint abs) {
|
|
245
|
-
uint next;
|
|
246
|
-
(abs, next) = expect(cur, cur.i, key, min, max);
|
|
247
|
-
cur.i = next;
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
/// @notice Enter a Bundle block at the current position and return the next offset.
|
|
251
|
-
/// Advances `cur.i` past the bundle header so the bundled members can be parsed
|
|
252
|
-
/// directly from the same cursor. The returned `next` is the byte offset
|
|
253
|
-
/// immediately after the bundle payload, relative to the current cursor region.
|
|
254
|
-
/// @param cur Cursor positioned at a bundle block; advanced past the 8-byte header.
|
|
255
|
-
/// @return next Byte offset immediately after the bundle payload.
|
|
256
|
-
function bundle(Cur memory cur) internal pure returns (uint next) {
|
|
257
|
-
(, next) = expect(cur, cur.i, Keys.Bundle, 0, 0);
|
|
258
|
-
cur.i += 8;
|
|
259
|
-
}
|
|
260
|
-
|
|
261
310
|
/// @notice Enter a List block at the current position and return the next offset.
|
|
262
311
|
/// Advances `cur.i` past the list header so the list members can be parsed
|
|
263
312
|
/// directly from the same cursor. The returned `next` is the byte offset
|
|
@@ -265,8 +314,7 @@ library Cursors {
|
|
|
265
314
|
/// @param cur Cursor positioned at a list block; advanced past the 8-byte header.
|
|
266
315
|
/// @return next Byte offset immediately after the list payload.
|
|
267
316
|
function list(Cur memory cur) internal pure returns (uint next) {
|
|
268
|
-
|
|
269
|
-
cur.i += 8;
|
|
317
|
+
next = enter(cur, Keys.List, 0, 0);
|
|
270
318
|
}
|
|
271
319
|
|
|
272
320
|
/// @notice Consume a block with the given key at the current position and return a cursor over the full block slice.
|
|
@@ -276,11 +324,24 @@ library Cursors {
|
|
|
276
324
|
/// @param key Expected block type key.
|
|
277
325
|
/// @return out Cursor scoped to the full block.
|
|
278
326
|
function take(Cur memory cur, bytes4 key) internal pure returns (Cur memory out) {
|
|
279
|
-
(, uint next) = expect(cur, cur.i, key, 0, 0);
|
|
327
|
+
(, uint next) = expect(cur, cur.i, 0, key, 0, 0);
|
|
280
328
|
out = cur.slice(cur.i, next);
|
|
281
329
|
cur.i = next;
|
|
282
330
|
}
|
|
283
331
|
|
|
332
|
+
/// @notice Return whether the remaining cursor region is empty or exactly one block with `key`.
|
|
333
|
+
/// Returns false for an empty remaining region. Reverts if the next block has another key or
|
|
334
|
+
/// if a matching block is followed by trailing bytes.
|
|
335
|
+
/// @param cur Source cursor.
|
|
336
|
+
/// @param key Expected optional block key.
|
|
337
|
+
/// @return Whether the remaining region contains exactly one block with `key`.
|
|
338
|
+
function maybeOnly(Cur memory cur, bytes4 key) internal pure returns (bool) {
|
|
339
|
+
if (cur.i == cur.len) return false;
|
|
340
|
+
if (!cur.isAt(key)) revert InvalidBlock();
|
|
341
|
+
if (cur.past() != cur.len) revert IncompleteCursor();
|
|
342
|
+
return true;
|
|
343
|
+
}
|
|
344
|
+
|
|
284
345
|
/// @notice Consume an optional block with the given key and return a cursor over the full block slice.
|
|
285
346
|
/// If the current block key does not match, returns an empty cursor and leaves `cur.i` unchanged.
|
|
286
347
|
/// Otherwise behaves like `take(cur, key)`.
|
|
@@ -291,13 +352,13 @@ library Cursors {
|
|
|
291
352
|
return cur.isAt(key) ? take(cur, key) : cur.slice(cur.i, cur.i);
|
|
292
353
|
}
|
|
293
354
|
|
|
294
|
-
/// @notice Consume an optional
|
|
295
|
-
/// If the current block is not
|
|
296
|
-
/// Otherwise behaves like `take(cur, Keys.
|
|
297
|
-
/// @param cur Cursor positioned at an optional
|
|
298
|
-
/// @return out Cursor scoped to the full
|
|
299
|
-
function
|
|
300
|
-
return maybeTake(cur, Keys.
|
|
355
|
+
/// @notice Consume an optional DATA block at the current position and return a cursor over the full block slice.
|
|
356
|
+
/// If the current block is not DATA, returns an empty cursor and leaves `cur.i` unchanged.
|
|
357
|
+
/// Otherwise behaves like `take(cur, Keys.Data)`.
|
|
358
|
+
/// @param cur Cursor positioned at an optional DATA block.
|
|
359
|
+
/// @return out Cursor scoped to the full DATA block, or empty when no DATA block is present.
|
|
360
|
+
function maybeData(Cur memory cur) internal pure returns (Cur memory out) {
|
|
361
|
+
return maybeTake(cur, Keys.Data);
|
|
301
362
|
}
|
|
302
363
|
|
|
303
364
|
/// @notice Enter a List block, prime its member run, and return the group count.
|
|
@@ -307,56 +368,45 @@ library Cursors {
|
|
|
307
368
|
/// @return next Byte offset immediately after the list payload.
|
|
308
369
|
function list(Cur memory cur, uint group) internal pure returns (uint groups, uint next) {
|
|
309
370
|
next = list(cur);
|
|
310
|
-
(,
|
|
371
|
+
(, groups) = cur.primeRun(group);
|
|
311
372
|
if (cur.bound != next) revert IncompleteCursor();
|
|
312
373
|
}
|
|
313
374
|
|
|
375
|
+
/// @notice Exit a nested region at an exact boundary.
|
|
376
|
+
/// Reverts with `IncompleteCursor` if `end` exceeds the cursor region length
|
|
377
|
+
/// or `cur.i != end`.
|
|
378
|
+
/// @param cur Cursor to check.
|
|
379
|
+
/// @param end Relative end offset of the nested region.
|
|
380
|
+
function exit(Cur memory cur, uint end) internal pure {
|
|
381
|
+
if (end > cur.len || cur.i != end) revert IncompleteCursor();
|
|
382
|
+
}
|
|
383
|
+
|
|
314
384
|
/// @notice Assert that the cursor has consumed exactly up to `bound`.
|
|
315
385
|
/// Reverts with `IncompleteCursor` if `bound` is zero or `cur.i != cur.bound`.
|
|
316
386
|
/// @param cur Cursor to check.
|
|
317
|
-
function
|
|
387
|
+
function close(Cur memory cur) internal pure {
|
|
318
388
|
if (cur.bound == 0 || cur.i != cur.bound) revert IncompleteCursor();
|
|
319
389
|
}
|
|
320
390
|
|
|
321
391
|
/// @notice Assert that the cursor has consumed its entire source region.
|
|
322
392
|
/// Reverts with `IncompleteCursor` when `cur.i != cur.len`.
|
|
323
393
|
/// @param cur Cursor to check.
|
|
324
|
-
function
|
|
394
|
+
function complete(Cur memory cur) internal pure {
|
|
325
395
|
if (cur.i != cur.len) revert IncompleteCursor();
|
|
326
396
|
}
|
|
327
397
|
|
|
328
|
-
/// @notice Resume parsing after a nested region delimited by `resumeAt`.
|
|
329
|
-
/// Reverts with `IncompleteCursor` if `cur.i` has advanced past `resumeAt` or `resumeAt`
|
|
330
|
-
/// exceeds the cursor region length. Otherwise moves `cur.i` to `end`.
|
|
331
|
-
/// @param cur Cursor to advance.
|
|
332
|
-
/// @param resumeAt Relative end offset of the nested region to resume after.
|
|
333
|
-
function resume(Cur memory cur, uint resumeAt) internal pure {
|
|
334
|
-
if (resumeAt > cur.len || cur.i > resumeAt) revert IncompleteCursor();
|
|
335
|
-
cur.i = resumeAt;
|
|
336
|
-
}
|
|
337
|
-
|
|
338
|
-
/// @notice Ensure that parsing has reached an exact nested-region boundary.
|
|
339
|
-
/// Reverts with `IncompleteCursor` if `ensureAt` exceeds the cursor region length
|
|
340
|
-
/// or `cur.i != ensureAt`.
|
|
341
|
-
/// @param cur Cursor to check.
|
|
342
|
-
/// @param ensureAt Relative offset that `cur.i` must match exactly.
|
|
343
|
-
function ensure(Cur memory cur, uint ensureAt) internal pure {
|
|
344
|
-
if (ensureAt > cur.len || cur.i != ensureAt) revert IncompleteCursor();
|
|
345
|
-
}
|
|
346
|
-
|
|
347
|
-
/// @notice Assert completion and finalise a writer in one step.
|
|
348
|
-
/// @param cur Cursor to check.
|
|
349
|
-
/// @param writer Writer to finalise.
|
|
350
|
-
/// @return Trimmed output bytes from the writer.
|
|
351
|
-
function complete(Cur memory cur, Writer memory writer) internal pure returns (bytes memory) {
|
|
352
|
-
if (cur.bound == 0 || cur.i != cur.bound) revert IncompleteCursor();
|
|
353
|
-
return Writers.finish(writer);
|
|
354
|
-
}
|
|
355
|
-
|
|
356
398
|
// -------------------------------------------------------------------------
|
|
357
399
|
// Block factory helpers
|
|
358
400
|
// -------------------------------------------------------------------------
|
|
359
401
|
|
|
402
|
+
/// @notice Encode a block with a raw payload.
|
|
403
|
+
/// @param key Block type key.
|
|
404
|
+
/// @param data Raw payload bytes.
|
|
405
|
+
/// @return Encoded block bytes.
|
|
406
|
+
function createBlock(bytes4 key, bytes memory data) internal pure returns (bytes memory) {
|
|
407
|
+
return bytes.concat(key, bytes4(uint32(data.length)), data);
|
|
408
|
+
}
|
|
409
|
+
|
|
360
410
|
/// @notice Encode a block with a single 32-byte payload word.
|
|
361
411
|
/// @param key Block type key.
|
|
362
412
|
/// @param value 32-byte payload.
|
|
@@ -420,28 +470,11 @@ library Cursors {
|
|
|
420
470
|
return bytes.concat(key, bytes4(uint32(0xa0)), a, b, c, d, e);
|
|
421
471
|
}
|
|
422
472
|
|
|
423
|
-
/// @notice Encode a block with a
|
|
424
|
-
/// @param
|
|
425
|
-
/// @
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
function createBlockHead32(bytes4 key, bytes32 head, bytes memory tail) internal pure returns (bytes memory) {
|
|
429
|
-
return bytes.concat(key, bytes4(uint32(0x20 + tail.length)), head, tail);
|
|
430
|
-
}
|
|
431
|
-
|
|
432
|
-
/// @notice Encode a block with a 64-byte fixed head followed by a variable-length tail.
|
|
433
|
-
/// @param key Block type key.
|
|
434
|
-
/// @param a First fixed payload word.
|
|
435
|
-
/// @param b Second fixed payload word.
|
|
436
|
-
/// @param tail Variable-length payload bytes appended after the fixed head.
|
|
437
|
-
/// @return Encoded block bytes.
|
|
438
|
-
function createBlockHead64(
|
|
439
|
-
bytes4 key,
|
|
440
|
-
bytes32 a,
|
|
441
|
-
bytes32 b,
|
|
442
|
-
bytes memory tail
|
|
443
|
-
) internal pure returns (bytes memory) {
|
|
444
|
-
return bytes.concat(key, bytes4(uint32(0x40 + tail.length)), a, b, tail);
|
|
473
|
+
/// @notice Encode a BYTES block with a raw payload.
|
|
474
|
+
/// @param data Raw payload bytes.
|
|
475
|
+
/// @return Encoded BYTES block bytes.
|
|
476
|
+
function toBytesBlock(bytes memory data) internal pure returns (bytes memory) {
|
|
477
|
+
return createBlock(Keys.Bytes, data);
|
|
445
478
|
}
|
|
446
479
|
|
|
447
480
|
/// @notice Encode a BOUNTY block.
|
|
@@ -452,13 +485,32 @@ library Cursors {
|
|
|
452
485
|
return createBlock64(Keys.Bounty, bytes32(bounty), relayer);
|
|
453
486
|
}
|
|
454
487
|
|
|
488
|
+
/// @notice Encode a BALANCE block.
|
|
489
|
+
/// @param asset Asset identifier.
|
|
490
|
+
/// @param meta Asset metadata slot.
|
|
491
|
+
/// @param amount Token amount.
|
|
492
|
+
/// @return Encoded BALANCE block bytes.
|
|
493
|
+
function toBalanceBlock(bytes32 asset, bytes32 meta, uint amount) internal pure returns (bytes memory) {
|
|
494
|
+
return createBlock96(Keys.Balance, asset, meta, bytes32(amount));
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
/// @notice Encode a CUSTODY block.
|
|
498
|
+
/// @param host Host node ID holding the custody.
|
|
499
|
+
/// @param asset Asset identifier.
|
|
500
|
+
/// @param meta Asset metadata slot.
|
|
501
|
+
/// @param amount Token amount.
|
|
502
|
+
/// @return Encoded CUSTODY block bytes.
|
|
503
|
+
function toCustodyBlock(uint host, bytes32 asset, bytes32 meta, uint amount) internal pure returns (bytes memory) {
|
|
504
|
+
return createBlock128(Keys.Custody, bytes32(host), asset, meta, bytes32(amount));
|
|
505
|
+
}
|
|
506
|
+
|
|
455
507
|
/// @notice Encode a STEP block.
|
|
456
508
|
/// @param target Command target identifier.
|
|
457
509
|
/// @param value Native value forwarded with the step.
|
|
458
|
-
/// @param request
|
|
510
|
+
/// @param request Raw nested request payload.
|
|
459
511
|
/// @return Encoded STEP block bytes.
|
|
460
512
|
function toStepBlock(uint target, uint value, bytes memory request) internal pure returns (bytes memory) {
|
|
461
|
-
return
|
|
513
|
+
return createBlock(Keys.Step, bytes.concat(bytes32(target), bytes32(value), toBytesBlock(request)));
|
|
462
514
|
}
|
|
463
515
|
|
|
464
516
|
/// @notice Encode a CALL block.
|
|
@@ -467,105 +519,113 @@ library Cursors {
|
|
|
467
519
|
/// @param data Raw calldata payload for the target.
|
|
468
520
|
/// @return Encoded CALL block bytes.
|
|
469
521
|
function toCallBlock(uint target, uint value, bytes memory data) internal pure returns (bytes memory) {
|
|
470
|
-
return
|
|
522
|
+
return createBlock(Keys.Call, bytes.concat(bytes32(target), bytes32(value), toBytesBlock(data)));
|
|
471
523
|
}
|
|
472
524
|
|
|
473
|
-
/// @notice Encode a
|
|
474
|
-
/// @param
|
|
475
|
-
/// @param
|
|
476
|
-
/// @param
|
|
477
|
-
/// @return Encoded
|
|
478
|
-
function
|
|
479
|
-
return
|
|
525
|
+
/// @notice Encode a CONTEXT block.
|
|
526
|
+
/// @param account Command account identifier.
|
|
527
|
+
/// @param state Embedded state block stream.
|
|
528
|
+
/// @param request Embedded request block stream.
|
|
529
|
+
/// @return Encoded CONTEXT block bytes.
|
|
530
|
+
function toContextBlock(bytes32 account, bytes memory state, bytes memory request) internal pure returns (bytes memory) {
|
|
531
|
+
return createBlock(Keys.Context, bytes.concat(account, toBytesBlock(state), toBytesBlock(request)));
|
|
480
532
|
}
|
|
481
533
|
|
|
482
|
-
/// @notice Encode a
|
|
483
|
-
/// @param
|
|
484
|
-
/// @param
|
|
485
|
-
/// @param
|
|
486
|
-
/// @param
|
|
487
|
-
/// @
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
534
|
+
/// @notice Encode a RELAY block.
|
|
535
|
+
/// @param target Command target identifier.
|
|
536
|
+
/// @param value Native value assigned to the relay.
|
|
537
|
+
/// @param account Command account identifier.
|
|
538
|
+
/// @param state Embedded state block stream.
|
|
539
|
+
/// @param request Embedded request block stream.
|
|
540
|
+
/// @return Encoded RELAY block bytes.
|
|
541
|
+
function toRelayBlock(
|
|
542
|
+
uint target,
|
|
543
|
+
uint value,
|
|
544
|
+
bytes32 account,
|
|
545
|
+
bytes memory state,
|
|
546
|
+
bytes memory request
|
|
493
547
|
) internal pure returns (bytes memory) {
|
|
494
|
-
return
|
|
548
|
+
return createBlock(Keys.Relay, bytes.concat(bytes32(target), bytes32(value), toContextBlock(account, state, request)));
|
|
495
549
|
}
|
|
496
550
|
|
|
497
551
|
// -------------------------------------------------------------------------
|
|
498
552
|
// Raw calldata loaders
|
|
499
553
|
// -------------------------------------------------------------------------
|
|
500
554
|
|
|
501
|
-
/// @notice
|
|
502
|
-
/// @dev Performs no bounds, key, length, or cursor checks.
|
|
503
|
-
///
|
|
504
|
-
/// @
|
|
505
|
-
|
|
555
|
+
/// @notice Read the next calldata word from the cursor and advance by `n` bytes.
|
|
556
|
+
/// @dev Performs no bounds, key, length, or cursor checks. Always loads 32 bytes;
|
|
557
|
+
/// callers may cast the returned word to `bytesN` when `n < 32`.
|
|
558
|
+
/// @param cur Cursor whose current position is advanced by `n` bytes.
|
|
559
|
+
/// @param n Number of bytes to advance.
|
|
560
|
+
/// @return value Loaded word.
|
|
561
|
+
function read(Cur memory cur, uint n) internal pure returns (bytes32 value) {
|
|
562
|
+
uint abs = cur.offset + cur.i;
|
|
506
563
|
assembly ("memory-safe") {
|
|
507
|
-
|
|
564
|
+
value := calldataload(abs)
|
|
508
565
|
}
|
|
566
|
+
cur.i += n;
|
|
509
567
|
}
|
|
510
568
|
|
|
511
|
-
/// @notice
|
|
569
|
+
/// @notice Read the next 16 bytes from the cursor and advance by 16 bytes.
|
|
512
570
|
/// @dev Performs no bounds, key, length, or cursor checks.
|
|
513
|
-
/// @param
|
|
514
|
-
/// @return
|
|
515
|
-
|
|
516
|
-
|
|
571
|
+
/// @param cur Cursor whose current position is advanced by 16 bytes.
|
|
572
|
+
/// @return value Loaded bytes16 value.
|
|
573
|
+
function read16(Cur memory cur) internal pure returns (bytes16 value) {
|
|
574
|
+
uint abs = cur.offset + cur.i;
|
|
517
575
|
assembly ("memory-safe") {
|
|
518
|
-
|
|
519
|
-
b := calldataload(add(abs, 0x20))
|
|
576
|
+
value := calldataload(abs)
|
|
520
577
|
}
|
|
578
|
+
cur.i += 16;
|
|
521
579
|
}
|
|
522
580
|
|
|
523
|
-
/// @notice
|
|
581
|
+
/// @notice Read the next 32-byte word from the cursor and advance by one word.
|
|
524
582
|
/// @dev Performs no bounds, key, length, or cursor checks.
|
|
525
|
-
/// @param
|
|
526
|
-
/// @return
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
function load96(uint abs) internal pure returns (bytes32 a, bytes32 b, bytes32 c) {
|
|
583
|
+
/// @param cur Cursor whose current position is advanced by 32 bytes.
|
|
584
|
+
/// @return value Loaded word.
|
|
585
|
+
function read32(Cur memory cur) internal pure returns (bytes32 value) {
|
|
586
|
+
uint abs = cur.offset + cur.i;
|
|
530
587
|
assembly ("memory-safe") {
|
|
531
|
-
|
|
532
|
-
b := calldataload(add(abs, 0x20))
|
|
533
|
-
c := calldataload(add(abs, 0x40))
|
|
588
|
+
value := calldataload(abs)
|
|
534
589
|
}
|
|
590
|
+
cur.i += 32;
|
|
535
591
|
}
|
|
536
592
|
|
|
537
|
-
/// @notice
|
|
593
|
+
/// @notice Read the next two 32-byte words from the cursor and advance by 64 bytes.
|
|
538
594
|
/// @dev Performs no bounds, key, length, or cursor checks.
|
|
539
|
-
/// @param
|
|
595
|
+
/// @param cur Cursor whose current position is advanced by 64 bytes.
|
|
540
596
|
/// @return a First loaded word.
|
|
541
597
|
/// @return b Second loaded word.
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
function load128(uint abs) internal pure returns (bytes32 a, bytes32 b, bytes32 c, bytes32 d) {
|
|
598
|
+
function read64(Cur memory cur) internal pure returns (bytes32 a, bytes32 b) {
|
|
599
|
+
uint abs = cur.offset + cur.i;
|
|
545
600
|
assembly ("memory-safe") {
|
|
546
601
|
a := calldataload(abs)
|
|
547
602
|
b := calldataload(add(abs, 0x20))
|
|
548
|
-
c := calldataload(add(abs, 0x40))
|
|
549
|
-
d := calldataload(add(abs, 0x60))
|
|
550
603
|
}
|
|
604
|
+
cur.i += 64;
|
|
551
605
|
}
|
|
552
606
|
|
|
553
|
-
/// @notice
|
|
607
|
+
/// @notice Read the next three 32-byte words from the cursor and advance by 96 bytes.
|
|
554
608
|
/// @dev Performs no bounds, key, length, or cursor checks.
|
|
555
|
-
/// @param
|
|
609
|
+
/// @param cur Cursor whose current position is advanced by 96 bytes.
|
|
556
610
|
/// @return a First loaded word.
|
|
557
611
|
/// @return b Second loaded word.
|
|
558
612
|
/// @return c Third loaded word.
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
function load160(uint abs) internal pure returns (bytes32 a, bytes32 b, bytes32 c, bytes32 d, bytes32 e) {
|
|
613
|
+
function read96(Cur memory cur) internal pure returns (bytes32 a, bytes32 b, bytes32 c) {
|
|
614
|
+
uint abs = cur.offset + cur.i;
|
|
562
615
|
assembly ("memory-safe") {
|
|
563
616
|
a := calldataload(abs)
|
|
564
617
|
b := calldataload(add(abs, 0x20))
|
|
565
618
|
c := calldataload(add(abs, 0x40))
|
|
566
|
-
d := calldataload(add(abs, 0x60))
|
|
567
|
-
e := calldataload(add(abs, 0x80))
|
|
568
619
|
}
|
|
620
|
+
cur.i += 96;
|
|
621
|
+
}
|
|
622
|
+
|
|
623
|
+
/// @notice Consume the next 32-byte word and require it to match `expected`.
|
|
624
|
+
/// @dev Performs no bounds, key, length, or cursor checks beyond the value comparison.
|
|
625
|
+
/// @param cur Cursor whose current position is advanced by 32 bytes.
|
|
626
|
+
/// @param expected Required word value.
|
|
627
|
+
function require32(Cur memory cur, bytes32 expected) internal pure {
|
|
628
|
+
if (read32(cur) != expected) revert UnexpectedValue();
|
|
569
629
|
}
|
|
570
630
|
|
|
571
631
|
// -------------------------------------------------------------------------
|
|
@@ -580,17 +640,24 @@ library Cursors {
|
|
|
580
640
|
/// @param key Expected dynamic block key.
|
|
581
641
|
/// @return data Raw block payload bytes.
|
|
582
642
|
function unpackRaw(Cur memory cur, bytes4 key) internal pure returns (bytes calldata data) {
|
|
583
|
-
(uint abs, uint next) = expect(cur, cur.i, key, 0, 0);
|
|
643
|
+
(uint abs, uint next) = expect(cur, cur.i, 0, key, 0, 0);
|
|
584
644
|
data = msg.data[abs:cur.offset + next];
|
|
585
645
|
cur.i = next;
|
|
586
646
|
}
|
|
587
647
|
|
|
648
|
+
/// @notice Consume a reserved BYTES block and return its raw payload.
|
|
649
|
+
/// @param cur Cursor; advanced past the BYTES block.
|
|
650
|
+
/// @return data Raw BYTES payload.
|
|
651
|
+
function unpackBytes(Cur memory cur) internal pure returns (bytes calldata data) {
|
|
652
|
+
return unpackRaw(cur, Keys.Bytes);
|
|
653
|
+
}
|
|
654
|
+
|
|
588
655
|
/// @notice Consume a dynamic block with a single bytes32 payload.
|
|
589
656
|
/// @param cur Cursor; advanced past the block.
|
|
590
657
|
/// @param key Expected dynamic block key.
|
|
591
658
|
/// @return value Decoded bytes32.
|
|
592
659
|
function unpack32(Cur memory cur, bytes4 key) internal pure returns (bytes32 value) {
|
|
593
|
-
uint abs = consume(cur, key, 32, 32);
|
|
660
|
+
uint abs = consume(cur, 0, key, 32, 32);
|
|
594
661
|
value = bytes32(msg.data[abs:abs + 32]);
|
|
595
662
|
}
|
|
596
663
|
|
|
@@ -600,7 +667,7 @@ library Cursors {
|
|
|
600
667
|
/// @return a First decoded bytes32.
|
|
601
668
|
/// @return b Second decoded bytes32.
|
|
602
669
|
function unpack64(Cur memory cur, bytes4 key) internal pure returns (bytes32 a, bytes32 b) {
|
|
603
|
-
uint abs = consume(cur, key, 64, 64);
|
|
670
|
+
uint abs = consume(cur, 0, key, 64, 64);
|
|
604
671
|
a = bytes32(msg.data[abs:abs + 32]);
|
|
605
672
|
b = bytes32(msg.data[abs + 32:abs + 64]);
|
|
606
673
|
}
|
|
@@ -612,7 +679,7 @@ library Cursors {
|
|
|
612
679
|
/// @return b Second decoded bytes32.
|
|
613
680
|
/// @return c Third decoded bytes32.
|
|
614
681
|
function unpack96(Cur memory cur, bytes4 key) internal pure returns (bytes32 a, bytes32 b, bytes32 c) {
|
|
615
|
-
uint abs = consume(cur, key, 96, 96);
|
|
682
|
+
uint abs = consume(cur, 0, key, 96, 96);
|
|
616
683
|
a = bytes32(msg.data[abs:abs + 32]);
|
|
617
684
|
b = bytes32(msg.data[abs + 32:abs + 64]);
|
|
618
685
|
c = bytes32(msg.data[abs + 64:abs + 96]);
|
|
@@ -625,11 +692,8 @@ library Cursors {
|
|
|
625
692
|
/// @return b Second decoded bytes32.
|
|
626
693
|
/// @return c Third decoded bytes32.
|
|
627
694
|
/// @return d Fourth decoded bytes32.
|
|
628
|
-
function unpack128(
|
|
629
|
-
|
|
630
|
-
bytes4 key
|
|
631
|
-
) internal pure returns (bytes32 a, bytes32 b, bytes32 c, bytes32 d) {
|
|
632
|
-
uint abs = consume(cur, key, 128, 128);
|
|
695
|
+
function unpack128(Cur memory cur, bytes4 key) internal pure returns (bytes32 a, bytes32 b, bytes32 c, bytes32 d) {
|
|
696
|
+
uint abs = consume(cur, 0, key, 128, 128);
|
|
633
697
|
a = bytes32(msg.data[abs:abs + 32]);
|
|
634
698
|
b = bytes32(msg.data[abs + 32:abs + 64]);
|
|
635
699
|
c = bytes32(msg.data[abs + 64:abs + 96]);
|
|
@@ -648,7 +712,7 @@ library Cursors {
|
|
|
648
712
|
Cur memory cur,
|
|
649
713
|
bytes4 key
|
|
650
714
|
) internal pure returns (bytes32 a, bytes32 b, bytes32 c, bytes32 d, bytes32 e) {
|
|
651
|
-
uint abs = consume(cur, key, 160, 160);
|
|
715
|
+
uint abs = consume(cur, 0, key, 160, 160);
|
|
652
716
|
a = bytes32(msg.data[abs:abs + 32]);
|
|
653
717
|
b = bytes32(msg.data[abs + 32:abs + 64]);
|
|
654
718
|
c = bytes32(msg.data[abs + 64:abs + 96]);
|
|
@@ -656,102 +720,6 @@ library Cursors {
|
|
|
656
720
|
e = bytes32(msg.data[abs + 128:abs + 160]);
|
|
657
721
|
}
|
|
658
722
|
|
|
659
|
-
/// @notice Consume a dynamic block with a single uint payload.
|
|
660
|
-
/// @param cur Cursor; advanced past the block.
|
|
661
|
-
/// @param key Expected dynamic block key.
|
|
662
|
-
/// @return value Decoded uint value.
|
|
663
|
-
function unpackUint(Cur memory cur, bytes4 key) internal pure returns (uint value) {
|
|
664
|
-
value = uint(unpack32(cur, key));
|
|
665
|
-
}
|
|
666
|
-
|
|
667
|
-
/// @notice Consume a dynamic block with two uint payload words.
|
|
668
|
-
/// @param cur Cursor; advanced past the block.
|
|
669
|
-
/// @param key Expected dynamic block key.
|
|
670
|
-
/// @return a First decoded uint.
|
|
671
|
-
/// @return b Second decoded uint.
|
|
672
|
-
function unpack2Uint(Cur memory cur, bytes4 key) internal pure returns (uint a, uint b) {
|
|
673
|
-
(bytes32 x, bytes32 y) = unpack64(cur, key);
|
|
674
|
-
return (uint(x), uint(y));
|
|
675
|
-
}
|
|
676
|
-
|
|
677
|
-
/// @notice Consume a dynamic block with three uint payload words.
|
|
678
|
-
/// @param cur Cursor; advanced past the block.
|
|
679
|
-
/// @param key Expected dynamic block key.
|
|
680
|
-
/// @return a First decoded uint.
|
|
681
|
-
/// @return b Second decoded uint.
|
|
682
|
-
/// @return c Third decoded uint.
|
|
683
|
-
function unpack3Uint(Cur memory cur, bytes4 key) internal pure returns (uint a, uint b, uint c) {
|
|
684
|
-
(bytes32 x, bytes32 y, bytes32 z) = unpack96(cur, key);
|
|
685
|
-
return (uint(x), uint(y), uint(z));
|
|
686
|
-
}
|
|
687
|
-
|
|
688
|
-
// Generic fixed-head decoders
|
|
689
|
-
|
|
690
|
-
/// @notice Consume a dynamic block with a 32-byte fixed head followed by a variable-length tail.
|
|
691
|
-
/// @param cur Cursor; advanced past the block.
|
|
692
|
-
/// @param key Expected dynamic block key.
|
|
693
|
-
/// @return head Fixed 32-byte head.
|
|
694
|
-
/// @return tail Variable-length payload bytes after the fixed head.
|
|
695
|
-
function unpackHead32(Cur memory cur, bytes4 key) internal pure returns (bytes32 head, bytes calldata tail) {
|
|
696
|
-
uint abs = consume(cur, key, 32, 0);
|
|
697
|
-
head = bytes32(msg.data[abs:abs + 32]);
|
|
698
|
-
tail = msg.data[abs + 32:cur.offset + cur.i];
|
|
699
|
-
}
|
|
700
|
-
|
|
701
|
-
/// @notice Consume a dynamic block with a 64-byte fixed head followed by a variable-length tail.
|
|
702
|
-
/// @param cur Cursor; advanced past the block.
|
|
703
|
-
/// @param key Expected dynamic block key.
|
|
704
|
-
/// @return a First fixed head word.
|
|
705
|
-
/// @return b Second fixed head word.
|
|
706
|
-
/// @return tail Variable-length payload bytes after the fixed head.
|
|
707
|
-
function unpackHead64(
|
|
708
|
-
Cur memory cur,
|
|
709
|
-
bytes4 key
|
|
710
|
-
) internal pure returns (bytes32 a, bytes32 b, bytes calldata tail) {
|
|
711
|
-
uint abs = consume(cur, key, 64, 0);
|
|
712
|
-
a = bytes32(msg.data[abs:abs + 32]);
|
|
713
|
-
b = bytes32(msg.data[abs + 32:abs + 64]);
|
|
714
|
-
tail = msg.data[abs + 64:cur.offset + cur.i];
|
|
715
|
-
}
|
|
716
|
-
|
|
717
|
-
/// @notice Consume a dynamic block with a 96-byte fixed head followed by a variable-length tail.
|
|
718
|
-
/// @param cur Cursor; advanced past the block.
|
|
719
|
-
/// @param key Expected dynamic block key.
|
|
720
|
-
/// @return a First fixed head word.
|
|
721
|
-
/// @return b Second fixed head word.
|
|
722
|
-
/// @return c Third fixed head word.
|
|
723
|
-
/// @return tail Variable-length payload bytes after the fixed head.
|
|
724
|
-
function unpackHead96(
|
|
725
|
-
Cur memory cur,
|
|
726
|
-
bytes4 key
|
|
727
|
-
) internal pure returns (bytes32 a, bytes32 b, bytes32 c, bytes calldata tail) {
|
|
728
|
-
uint abs = consume(cur, key, 96, 0);
|
|
729
|
-
a = bytes32(msg.data[abs:abs + 32]);
|
|
730
|
-
b = bytes32(msg.data[abs + 32:abs + 64]);
|
|
731
|
-
c = bytes32(msg.data[abs + 64:abs + 96]);
|
|
732
|
-
tail = msg.data[abs + 96:cur.offset + cur.i];
|
|
733
|
-
}
|
|
734
|
-
|
|
735
|
-
/// @notice Consume a dynamic block with a 128-byte fixed head followed by a variable-length tail.
|
|
736
|
-
/// @param cur Cursor; advanced past the block.
|
|
737
|
-
/// @param key Expected dynamic block key.
|
|
738
|
-
/// @return a First fixed head word.
|
|
739
|
-
/// @return b Second fixed head word.
|
|
740
|
-
/// @return c Third fixed head word.
|
|
741
|
-
/// @return d Fourth fixed head word.
|
|
742
|
-
/// @return tail Variable-length payload bytes after the fixed head.
|
|
743
|
-
function unpackHead128(
|
|
744
|
-
Cur memory cur,
|
|
745
|
-
bytes4 key
|
|
746
|
-
) internal pure returns (bytes32 a, bytes32 b, bytes32 c, bytes32 d, bytes calldata tail) {
|
|
747
|
-
uint abs = consume(cur, key, 128, 0);
|
|
748
|
-
a = bytes32(msg.data[abs:abs + 32]);
|
|
749
|
-
b = bytes32(msg.data[abs + 32:abs + 64]);
|
|
750
|
-
c = bytes32(msg.data[abs + 64:abs + 96]);
|
|
751
|
-
d = bytes32(msg.data[abs + 96:abs + 128]);
|
|
752
|
-
tail = msg.data[abs + 128:cur.offset + cur.i];
|
|
753
|
-
}
|
|
754
|
-
|
|
755
723
|
// Generic typed-shape decoders
|
|
756
724
|
|
|
757
725
|
/// @notice Consume a fixed-size asset amount block and return asset, meta, and amount.
|
|
@@ -764,7 +732,7 @@ library Cursors {
|
|
|
764
732
|
Cur memory cur,
|
|
765
733
|
bytes4 key
|
|
766
734
|
) internal pure returns (bytes32 asset, bytes32 meta, uint amount) {
|
|
767
|
-
uint abs = consume(cur, key, 96, 96);
|
|
735
|
+
uint abs = consume(cur, 0, key, 96, 96);
|
|
768
736
|
asset = bytes32(msg.data[abs:abs + 32]);
|
|
769
737
|
meta = bytes32(msg.data[abs + 32:abs + 64]);
|
|
770
738
|
amount = uint(bytes32(msg.data[abs + 64:abs + 96]));
|
|
@@ -781,7 +749,7 @@ library Cursors {
|
|
|
781
749
|
Cur memory cur,
|
|
782
750
|
bytes4 key
|
|
783
751
|
) internal pure returns (bytes32 account, bytes32 asset, bytes32 meta, uint amount) {
|
|
784
|
-
uint abs = consume(cur, key, 128, 128);
|
|
752
|
+
uint abs = consume(cur, 0, key, 128, 128);
|
|
785
753
|
account = bytes32(msg.data[abs:abs + 32]);
|
|
786
754
|
asset = bytes32(msg.data[abs + 32:abs + 64]);
|
|
787
755
|
meta = bytes32(msg.data[abs + 64:abs + 96]);
|
|
@@ -799,7 +767,7 @@ library Cursors {
|
|
|
799
767
|
Cur memory cur,
|
|
800
768
|
bytes4 key
|
|
801
769
|
) internal pure returns (uint host, bytes32 asset, bytes32 meta, uint amount) {
|
|
802
|
-
uint abs = consume(cur, key, 128, 128);
|
|
770
|
+
uint abs = consume(cur, 0, key, 128, 128);
|
|
803
771
|
host = uint(bytes32(msg.data[abs:abs + 32]));
|
|
804
772
|
asset = bytes32(msg.data[abs + 32:abs + 64]);
|
|
805
773
|
meta = bytes32(msg.data[abs + 64:abs + 96]);
|
|
@@ -817,7 +785,7 @@ library Cursors {
|
|
|
817
785
|
Cur memory cur,
|
|
818
786
|
bytes4 key
|
|
819
787
|
) internal pure returns (uint host, bytes32 account, bytes32 asset, bytes32 meta) {
|
|
820
|
-
uint abs = consume(cur, key, 128, 128);
|
|
788
|
+
uint abs = consume(cur, 0, key, 128, 128);
|
|
821
789
|
host = uint(bytes32(msg.data[abs:abs + 32]));
|
|
822
790
|
account = bytes32(msg.data[abs + 32:abs + 64]);
|
|
823
791
|
asset = bytes32(msg.data[abs + 64:abs + 96]);
|
|
@@ -836,7 +804,7 @@ library Cursors {
|
|
|
836
804
|
Cur memory cur,
|
|
837
805
|
bytes4 key
|
|
838
806
|
) internal pure returns (bytes32 from, bytes32 to, bytes32 asset, bytes32 meta, uint amount) {
|
|
839
|
-
uint abs = consume(cur, key, 160, 160);
|
|
807
|
+
uint abs = consume(cur, 0, key, 160, 160);
|
|
840
808
|
from = bytes32(msg.data[abs:abs + 32]);
|
|
841
809
|
to = bytes32(msg.data[abs + 32:abs + 64]);
|
|
842
810
|
asset = bytes32(msg.data[abs + 64:abs + 96]);
|
|
@@ -860,20 +828,6 @@ library Cursors {
|
|
|
860
828
|
node = uint(unpack32(cur, Keys.Node));
|
|
861
829
|
}
|
|
862
830
|
|
|
863
|
-
/// @notice Consume a RATE block and return the value.
|
|
864
|
-
/// @param cur Cursor; advanced past the block.
|
|
865
|
-
/// @return value Encoded ratio or rate.
|
|
866
|
-
function unpackRate(Cur memory cur) internal pure returns (uint value) {
|
|
867
|
-
value = uint(unpack32(cur, Keys.Rate));
|
|
868
|
-
}
|
|
869
|
-
|
|
870
|
-
/// @notice Consume a QUANTITY block and return the amount.
|
|
871
|
-
/// @param cur Cursor; advanced past the block.
|
|
872
|
-
/// @return amount Scalar quantity value.
|
|
873
|
-
function unpackQuantity(Cur memory cur) internal pure returns (uint amount) {
|
|
874
|
-
amount = uint(unpack32(cur, Keys.Quantity));
|
|
875
|
-
}
|
|
876
|
-
|
|
877
831
|
/// @notice Consume a FEE block and return the amount.
|
|
878
832
|
/// @param cur Cursor; advanced past the block.
|
|
879
833
|
/// @return amount Fee amount.
|
|
@@ -895,7 +849,7 @@ library Cursors {
|
|
|
895
849
|
/// @return asset Asset identifier.
|
|
896
850
|
/// @return meta Asset metadata slot.
|
|
897
851
|
function unpackAccountAsset(Cur memory cur) internal pure returns (bytes32 account, bytes32 asset, bytes32 meta) {
|
|
898
|
-
uint abs = consume(cur, Keys.AccountAsset, 96, 96);
|
|
852
|
+
uint abs = consume(cur, 0, Keys.AccountAsset, 96, 96);
|
|
899
853
|
account = bytes32(msg.data[abs:abs + 32]);
|
|
900
854
|
asset = bytes32(msg.data[abs + 32:abs + 64]);
|
|
901
855
|
meta = bytes32(msg.data[abs + 64:abs + 96]);
|
|
@@ -918,18 +872,6 @@ library Cursors {
|
|
|
918
872
|
relayer = y;
|
|
919
873
|
}
|
|
920
874
|
|
|
921
|
-
/// @notice Consume a BOUNDS block and return the signed min and max values.
|
|
922
|
-
/// @param cur Cursor; advanced past the block.
|
|
923
|
-
/// @return min Lower signed bound.
|
|
924
|
-
/// @return max Upper signed bound.
|
|
925
|
-
function unpackBounds(Cur memory cur) internal pure returns (int min, int max) {
|
|
926
|
-
uint abs = consume(cur, Keys.Bounds, 64, 64);
|
|
927
|
-
assembly ("memory-safe") {
|
|
928
|
-
min := calldataload(abs)
|
|
929
|
-
max := calldataload(add(abs, 0x20))
|
|
930
|
-
}
|
|
931
|
-
}
|
|
932
|
-
|
|
933
875
|
/// @notice Consume an AMOUNT block and return its fields as separate values.
|
|
934
876
|
/// @param cur Cursor; advanced past the block.
|
|
935
877
|
/// @return asset Asset identifier.
|
|
@@ -1095,9 +1037,7 @@ library Cursors {
|
|
|
1095
1037
|
/// @return asset Asset identifier.
|
|
1096
1038
|
/// @return meta Asset metadata slot.
|
|
1097
1039
|
/// @return amount Token amount.
|
|
1098
|
-
function unpackCustody(
|
|
1099
|
-
Cur memory cur
|
|
1100
|
-
) internal pure returns (uint host, bytes32 asset, bytes32 meta, uint amount) {
|
|
1040
|
+
function unpackCustody(Cur memory cur) internal pure returns (uint host, bytes32 asset, bytes32 meta, uint amount) {
|
|
1101
1041
|
return unpackHostAmount(cur, Keys.Custody);
|
|
1102
1042
|
}
|
|
1103
1043
|
|
|
@@ -1131,25 +1071,62 @@ library Cursors {
|
|
|
1131
1071
|
// Type-specific dynamic decoders
|
|
1132
1072
|
|
|
1133
1073
|
/// @notice Consume a STEP block and return its sub-command invocation fields.
|
|
1134
|
-
/// The `req` slice
|
|
1074
|
+
/// The `req` slice is the raw payload of the block's required BYTES child.
|
|
1135
1075
|
/// @param cur Cursor; advanced past the block.
|
|
1136
1076
|
/// @return target Destination node ID for the sub-command.
|
|
1137
1077
|
/// @return value Native value to forward with the call.
|
|
1138
1078
|
/// @return req Embedded request bytes for the sub-command.
|
|
1139
1079
|
function unpackStep(Cur memory cur) internal pure returns (uint target, uint value, bytes calldata req) {
|
|
1140
|
-
|
|
1141
|
-
|
|
1080
|
+
uint end = cur.enter(Keys.Step, 64 + Sizes.Header, 0);
|
|
1081
|
+
target = uint(cur.read32());
|
|
1082
|
+
value = uint(cur.read32());
|
|
1083
|
+
req = cur.unpackBytes();
|
|
1084
|
+
cur.exit(end);
|
|
1142
1085
|
}
|
|
1143
1086
|
|
|
1144
1087
|
/// @notice Consume a CALL block and return its target invocation fields.
|
|
1145
|
-
/// The `data` slice
|
|
1088
|
+
/// The `data` slice is the raw payload of the block's required BYTES child.
|
|
1146
1089
|
/// @param cur Cursor; advanced past the block.
|
|
1147
1090
|
/// @return target Target node ID to call.
|
|
1148
1091
|
/// @return value Native value to forward with the call.
|
|
1149
1092
|
/// @return data Raw calldata payload for the target.
|
|
1150
1093
|
function unpackCall(Cur memory cur) internal pure returns (uint target, uint value, bytes calldata data) {
|
|
1151
|
-
|
|
1152
|
-
|
|
1094
|
+
uint end = cur.enter(Keys.Call, 64 + Sizes.Header, 0);
|
|
1095
|
+
target = uint(cur.read32());
|
|
1096
|
+
value = uint(cur.read32());
|
|
1097
|
+
data = cur.unpackBytes();
|
|
1098
|
+
cur.exit(end);
|
|
1099
|
+
}
|
|
1100
|
+
|
|
1101
|
+
/// @notice Consume a CONTEXT block and return its command context fields.
|
|
1102
|
+
/// The `state` and `request` slices are the raw payloads of the required BYTES children.
|
|
1103
|
+
/// @param cur Cursor; advanced past the block.
|
|
1104
|
+
/// @return account Command account identifier.
|
|
1105
|
+
/// @return state Embedded state block stream.
|
|
1106
|
+
/// @return request Embedded request block stream.
|
|
1107
|
+
function unpackContext(Cur memory cur) internal pure returns (bytes32 account, bytes calldata state, bytes calldata request) {
|
|
1108
|
+
uint end = cur.enter(Keys.Context, 32 + 2 * Sizes.Header, 0);
|
|
1109
|
+
account = cur.read32();
|
|
1110
|
+
state = cur.unpackBytes();
|
|
1111
|
+
request = cur.unpackBytes();
|
|
1112
|
+
cur.exit(end);
|
|
1113
|
+
}
|
|
1114
|
+
|
|
1115
|
+
/// @notice Consume a RELAY block and return its target, value, and context fields.
|
|
1116
|
+
/// @param cur Cursor; advanced past the block.
|
|
1117
|
+
/// @return target Destination command/node ID.
|
|
1118
|
+
/// @return value Native value assigned to the relay.
|
|
1119
|
+
/// @return account Command account identifier.
|
|
1120
|
+
/// @return state Embedded state block stream.
|
|
1121
|
+
/// @return request Embedded request block stream.
|
|
1122
|
+
function unpackRelay(
|
|
1123
|
+
Cur memory cur
|
|
1124
|
+
) internal pure returns (uint target, uint value, bytes32 account, bytes calldata state, bytes calldata request) {
|
|
1125
|
+
uint end = cur.enter(Keys.Relay, 64 + Sizes.Header + 32 + 2 * Sizes.Header, 0);
|
|
1126
|
+
target = uint(cur.read32());
|
|
1127
|
+
value = uint(cur.read32());
|
|
1128
|
+
(account, state, request) = cur.unpackContext();
|
|
1129
|
+
cur.exit(end);
|
|
1153
1130
|
}
|
|
1154
1131
|
|
|
1155
1132
|
// Type-specific validators
|
|
@@ -1162,10 +1139,12 @@ library Cursors {
|
|
|
1162
1139
|
/// @return deadline Expiry timestamp.
|
|
1163
1140
|
/// @return proof Raw proof bytes (layout: `[bytes20 signer][bytes65 sig]`).
|
|
1164
1141
|
function expectAuth(Cur memory cur, uint i, uint cid) internal pure returns (uint deadline, bytes calldata proof) {
|
|
1165
|
-
(uint abs, uint next) = expect(cur, i, Keys.Auth,
|
|
1142
|
+
(uint abs, uint next) = expect(cur, i, 0, Keys.Auth, 64 + Sizes.Header + Sizes.Proof, 0);
|
|
1166
1143
|
if (uint(bytes32(msg.data[abs:abs + 32])) != cid) revert UnexpectedValue();
|
|
1167
1144
|
deadline = uint(bytes32(msg.data[abs + 32:abs + 64]));
|
|
1168
|
-
|
|
1145
|
+
|
|
1146
|
+
(abs, ) = expect(cur, i + Sizes.Header + 64, next, Keys.Bytes, Sizes.Proof, Sizes.Proof);
|
|
1147
|
+
proof = msg.data[abs:abs + Sizes.Proof];
|
|
1169
1148
|
}
|
|
1170
1149
|
|
|
1171
1150
|
// -------------------------------------------------------------------------
|
|
@@ -1183,7 +1162,7 @@ library Cursors {
|
|
|
1183
1162
|
bytes4 key,
|
|
1184
1163
|
bytes32 asset
|
|
1185
1164
|
) internal pure returns (bytes32 meta, uint amount) {
|
|
1186
|
-
uint abs = consume(cur, key, 96, 96);
|
|
1165
|
+
uint abs = consume(cur, 0, key, 96, 96);
|
|
1187
1166
|
if (bytes32(msg.data[abs:abs + 32]) != asset) revert UnexpectedValue();
|
|
1188
1167
|
meta = bytes32(msg.data[abs + 32:abs + 64]);
|
|
1189
1168
|
amount = uint(bytes32(msg.data[abs + 64:abs + 96]));
|
|
@@ -1201,7 +1180,7 @@ library Cursors {
|
|
|
1201
1180
|
bytes32 asset,
|
|
1202
1181
|
bytes32 meta
|
|
1203
1182
|
) internal pure returns (uint amount) {
|
|
1204
|
-
uint abs = consume(cur, key, 96, 96);
|
|
1183
|
+
uint abs = consume(cur, 0, key, 96, 96);
|
|
1205
1184
|
if (bytes32(msg.data[abs:abs + 32]) != asset) revert UnexpectedValue();
|
|
1206
1185
|
if (bytes32(msg.data[abs + 32:abs + 64]) != meta) revert UnexpectedValue();
|
|
1207
1186
|
amount = uint(bytes32(msg.data[abs + 64:abs + 96]));
|
|
@@ -1213,7 +1192,7 @@ library Cursors {
|
|
|
1213
1192
|
/// @param asset Expected asset identifier.
|
|
1214
1193
|
/// @return meta Metadata slot from the block.
|
|
1215
1194
|
function requireUnitAssetAmount(Cur memory cur, bytes4 key, bytes32 asset) internal pure returns (bytes32 meta) {
|
|
1216
|
-
uint abs = consume(cur, key, 96, 96);
|
|
1195
|
+
uint abs = consume(cur, 0, key, 96, 96);
|
|
1217
1196
|
if (bytes32(msg.data[abs:abs + 32]) != asset) revert UnexpectedValue();
|
|
1218
1197
|
meta = bytes32(msg.data[abs + 32:abs + 64]);
|
|
1219
1198
|
if (uint(bytes32(msg.data[abs + 64:abs + 96])) != 1) revert UnexpectedValue();
|
|
@@ -1240,7 +1219,7 @@ library Cursors {
|
|
|
1240
1219
|
bytes4 key,
|
|
1241
1220
|
uint host
|
|
1242
1221
|
) internal pure returns (bytes32 asset, bytes32 meta, uint amount) {
|
|
1243
|
-
uint abs = consume(cur, key, 128, 128);
|
|
1222
|
+
uint abs = consume(cur, 0, key, 128, 128);
|
|
1244
1223
|
if (uint(bytes32(msg.data[abs:abs + 32])) != host) revert UnexpectedValue();
|
|
1245
1224
|
asset = bytes32(msg.data[abs + 32:abs + 64]);
|
|
1246
1225
|
meta = bytes32(msg.data[abs + 64:abs + 96]);
|
|
@@ -1260,7 +1239,7 @@ library Cursors {
|
|
|
1260
1239
|
uint host,
|
|
1261
1240
|
bytes32 asset
|
|
1262
1241
|
) internal pure returns (bytes32 meta, uint amount) {
|
|
1263
|
-
uint abs = consume(cur, key, 128, 128);
|
|
1242
|
+
uint abs = consume(cur, 0, key, 128, 128);
|
|
1264
1243
|
if (uint(bytes32(msg.data[abs:abs + 32])) != host) revert UnexpectedValue();
|
|
1265
1244
|
if (bytes32(msg.data[abs + 32:abs + 64]) != asset) revert UnexpectedValue();
|
|
1266
1245
|
meta = bytes32(msg.data[abs + 64:abs + 96]);
|
|
@@ -1279,7 +1258,7 @@ library Cursors {
|
|
|
1279
1258
|
uint host,
|
|
1280
1259
|
bytes32 asset
|
|
1281
1260
|
) internal pure returns (bytes32 meta) {
|
|
1282
|
-
uint abs = consume(cur, key, 128, 128);
|
|
1261
|
+
uint abs = consume(cur, 0, key, 128, 128);
|
|
1283
1262
|
if (uint(bytes32(msg.data[abs:abs + 32])) != host) revert UnexpectedValue();
|
|
1284
1263
|
if (bytes32(msg.data[abs + 32:abs + 64]) != asset) revert UnexpectedValue();
|
|
1285
1264
|
meta = bytes32(msg.data[abs + 64:abs + 96]);
|
|
@@ -1299,7 +1278,7 @@ library Cursors {
|
|
|
1299
1278
|
uint host,
|
|
1300
1279
|
bytes32 account
|
|
1301
1280
|
) internal pure returns (bytes32 asset, bytes32 meta) {
|
|
1302
|
-
uint abs = consume(cur, key, 128, 128);
|
|
1281
|
+
uint abs = consume(cur, 0, key, 128, 128);
|
|
1303
1282
|
if (uint(bytes32(msg.data[abs:abs + 32])) != host) revert UnexpectedValue();
|
|
1304
1283
|
if (bytes32(msg.data[abs + 32:abs + 64]) != account) revert UnexpectedValue();
|
|
1305
1284
|
asset = bytes32(msg.data[abs + 64:abs + 96]);
|
|
@@ -1318,7 +1297,7 @@ library Cursors {
|
|
|
1318
1297
|
bytes4 key,
|
|
1319
1298
|
uint host
|
|
1320
1299
|
) internal pure returns (bytes32 account, bytes32 asset, bytes32 meta) {
|
|
1321
|
-
uint abs = consume(cur, key, 128, 128);
|
|
1300
|
+
uint abs = consume(cur, 0, key, 128, 128);
|
|
1322
1301
|
if (uint(bytes32(msg.data[abs:abs + 32])) != host) revert UnexpectedValue();
|
|
1323
1302
|
account = bytes32(msg.data[abs + 32:abs + 64]);
|
|
1324
1303
|
asset = bytes32(msg.data[abs + 64:abs + 96]);
|
|
@@ -1345,7 +1324,7 @@ library Cursors {
|
|
|
1345
1324
|
/// @return proof Raw proof bytes.
|
|
1346
1325
|
function requireAuth(Cur memory cur, uint cid) internal pure returns (uint deadline, bytes calldata proof) {
|
|
1347
1326
|
(deadline, proof) = expectAuth(cur, cur.i, cid);
|
|
1348
|
-
cur.i += Sizes.
|
|
1327
|
+
cur.i += Sizes.Auth;
|
|
1349
1328
|
}
|
|
1350
1329
|
|
|
1351
1330
|
// -------------------------------------------------------------------------
|
|
@@ -1362,7 +1341,7 @@ library Cursors {
|
|
|
1362
1341
|
uint i = find(cur, 0, Keys.Node);
|
|
1363
1342
|
if (i == cur.len) return backup;
|
|
1364
1343
|
|
|
1365
|
-
(uint abs, ) = expect(cur, i, Keys.Node, 32, 32);
|
|
1344
|
+
(uint abs, ) = expect(cur, i, 0, Keys.Node, 32, 32);
|
|
1366
1345
|
return uint(bytes32(msg.data[abs:abs + 32]));
|
|
1367
1346
|
}
|
|
1368
1347
|
|
|
@@ -1386,7 +1365,7 @@ library Cursors {
|
|
|
1386
1365
|
uint i = find(cur, 0, Keys.Account);
|
|
1387
1366
|
if (i == cur.len) return backup;
|
|
1388
1367
|
|
|
1389
|
-
(uint abs, ) = expect(cur, i, Keys.Account, 32, 32);
|
|
1368
|
+
(uint abs, ) = expect(cur, i, 0, Keys.Account, 32, 32);
|
|
1390
1369
|
return bytes32(msg.data[abs:abs + 32]);
|
|
1391
1370
|
}
|
|
1392
1371
|
|
|
@@ -1399,7 +1378,7 @@ library Cursors {
|
|
|
1399
1378
|
uint i = find(cur, cur.bound, Keys.Node);
|
|
1400
1379
|
if (i == cur.len) return backup;
|
|
1401
1380
|
|
|
1402
|
-
(uint abs, ) = expect(cur, i, Keys.Node, 32, 32);
|
|
1381
|
+
(uint abs, ) = expect(cur, i, 0, Keys.Node, 32, 32);
|
|
1403
1382
|
return uint(bytes32(msg.data[abs:abs + 32]));
|
|
1404
1383
|
}
|
|
1405
1384
|
|
|
@@ -1412,7 +1391,7 @@ library Cursors {
|
|
|
1412
1391
|
uint i = find(cur, cur.bound, Keys.Account);
|
|
1413
1392
|
if (i == cur.len) return backup;
|
|
1414
1393
|
|
|
1415
|
-
(uint abs, ) = expect(cur, i, Keys.Account, 32, 32);
|
|
1394
|
+
(uint abs, ) = expect(cur, i, 0, Keys.Account, 32, 32);
|
|
1416
1395
|
return bytes32(msg.data[abs:abs + 32]);
|
|
1417
1396
|
}
|
|
1418
1397
|
|
|
@@ -1422,19 +1401,19 @@ library Cursors {
|
|
|
1422
1401
|
/// The signed slice covers from `cur.i` up to (but not including) the AUTH proof bytes.
|
|
1423
1402
|
/// @param cur Source cursor; `bound` marks the end of the primary data region.
|
|
1424
1403
|
/// @param cid Command ID that the signature must be bound to.
|
|
1425
|
-
/// @return
|
|
1404
|
+
/// @return digest keccak256 of the signed message slice.
|
|
1426
1405
|
/// @return deadline Expiry timestamp from the AUTH block.
|
|
1427
1406
|
/// @return proof Raw proof bytes (layout: `[bytes20 signer][bytes65 sig]`).
|
|
1428
1407
|
function authLast(
|
|
1429
1408
|
Cur memory cur,
|
|
1430
1409
|
uint cid
|
|
1431
|
-
) internal pure returns (bytes32
|
|
1410
|
+
) internal pure returns (bytes32 digest, uint deadline, bytes calldata proof) {
|
|
1432
1411
|
if (cur.len - cur.i < Sizes.Auth) revert MalformedBlocks();
|
|
1433
1412
|
|
|
1434
1413
|
uint i = cur.len - Sizes.Auth;
|
|
1435
1414
|
if (i < cur.bound) revert MalformedBlocks();
|
|
1436
1415
|
|
|
1437
1416
|
(deadline, proof) = expectAuth(cur, i, cid);
|
|
1438
|
-
|
|
1417
|
+
digest = cur.hash(cur.i, cur.len - Sizes.Proof);
|
|
1439
1418
|
}
|
|
1440
1419
|
}
|