@rootzero/contracts 1.8.0 → 1.10.0
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/CHANGELOG.md +39 -0
- package/Core.sol +2 -1
- package/Endpoints.sol +2 -2
- package/Events.sol +2 -1
- package/README.md +14 -13
- package/blocks/Cursors.sol +61 -61
- package/blocks/Keys.sol +4 -4
- package/blocks/Schema.sol +8 -7
- package/blocks/Writers.sol +2 -2
- package/commands/Burn.sol +1 -1
- package/commands/Credit.sol +1 -1
- package/commands/Debit.sol +1 -1
- package/commands/Deposit.sol +2 -2
- package/commands/Payout.sol +2 -2
- package/commands/Provision.sol +2 -2
- package/commands/Recover.sol +21 -20
- package/commands/Relay.sol +11 -11
- package/commands/Withdraw.sol +1 -1
- package/commands/admin/AllowAssets.sol +1 -1
- package/commands/admin/Allowance.sol +1 -1
- package/commands/admin/Appoint.sol +1 -1
- package/commands/admin/Authorize.sol +1 -1
- package/commands/admin/DenyAssets.sol +1 -1
- package/commands/admin/Destroy.sol +1 -0
- package/commands/admin/Dismiss.sol +1 -1
- package/commands/admin/Execute.sol +2 -2
- package/commands/admin/Init.sol +1 -0
- package/commands/admin/Label.sol +1 -1
- package/commands/admin/Unauthorize.sol +1 -1
- package/core/Access.sol +1 -0
- package/core/Calls.sol +12 -1
- package/core/Payable.sol +8 -1
- package/core/Pipeline.sol +1 -1
- package/core/Portal.sol +39 -0
- package/docs/Schema.md +15 -11
- package/events/Dispatch.sol +5 -5
- package/events/Recovered.sol +17 -0
- package/events/Route.sol +5 -5
- package/events/Undelivered.sol +18 -0
- package/guards/Revoke.sol +1 -1
- package/package.json +1 -1
- package/ports/AllowAssets.sol +1 -1
- package/ports/Allowance.sol +1 -1
- package/ports/Credit.sol +1 -1
- package/ports/Debit.sol +1 -1
- package/ports/DenyAssets.sol +1 -1
- package/ports/Dispatch.sol +8 -8
- package/ports/Pipe.sol +1 -1
- package/ports/Redeem.sol +1 -1
- package/ports/Settle.sol +1 -1
- package/queries/Assets.sol +1 -1
- package/queries/Balances.sol +1 -1
- package/queries/Positions.sol +2 -1
- package/core/Commitments.sol +0 -19
- package/events/Commitment.sol +0 -19
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,45 @@
|
|
|
3
3
|
Until the protocol reaches integration-stable status, minor versions may include
|
|
4
4
|
breaking API changes. Breaking changes are called out explicitly.
|
|
5
5
|
|
|
6
|
+
## Unreleased
|
|
7
|
+
|
|
8
|
+
## 1.10.0
|
|
9
|
+
|
|
10
|
+
### Breaking Changes
|
|
11
|
+
|
|
12
|
+
- Moved `RecoverHook` from `Portal.sol` to `commands/Recover.sol`.
|
|
13
|
+
- Moved `RoutePayableHook` from `Portal.sol` to `commands/Relay.sol`.
|
|
14
|
+
- Renamed Portal helpers to `forward` / `retry`; hosts now explicitly bridge
|
|
15
|
+
the `RecoverPayable` hook to Portal retry behavior.
|
|
16
|
+
- Renamed the generic `Resolved` event to `Recovered`.
|
|
17
|
+
- Portal no longer emits `Recovered` when retrying an undelivered witness.
|
|
18
|
+
- Renamed `Cursors.exit` to `ensureAt` and renamed its position argument to
|
|
19
|
+
`pos`.
|
|
20
|
+
- Removed the redundant `next` return value from both `Cursors.init` overloads;
|
|
21
|
+
callers should use the returned cursor's `len` as the run boundary.
|
|
22
|
+
- Changed `Cursors.list` to require the expected current cursor position as
|
|
23
|
+
`pos` before entering the LIST block.
|
|
24
|
+
|
|
25
|
+
## 1.9.0
|
|
26
|
+
|
|
27
|
+
### Breaking Changes
|
|
28
|
+
|
|
29
|
+
- Renamed relay and dispatch routing fields from `chain` to `portal` across
|
|
30
|
+
schemas, cursor helpers, dispatch hooks, and dispatch/route events.
|
|
31
|
+
- Replaced the context-specific `RecoverContextPayable` / `#contextRecovery`
|
|
32
|
+
surface with generic `RecoverPayable` / `#recover` using byte witnesses.
|
|
33
|
+
- Renamed the `Dispatch` event correlation field from `ref` to `key`.
|
|
34
|
+
- Replaced `DispatchPayableHook.dispatch` with `RoutePayableHook.route` in the
|
|
35
|
+
portal core layer.
|
|
36
|
+
- Added `status` to `Route(uint indexed host, uint portal, uint status)`
|
|
37
|
+
so routes can be removed by emitting zero status.
|
|
38
|
+
- Added `Undelivered(uint indexed host, bytes32 key, bytes32 digest)` for portal
|
|
39
|
+
messages that could not be delivered to their handler port.
|
|
40
|
+
- Added `Recovered(uint indexed host, bytes32 key)` as the
|
|
41
|
+
matching event for resolved undelivered digests.
|
|
42
|
+
- Removed the generic `Commitments` core mixin and `Commitment` event in favor
|
|
43
|
+
of domain-specific events such as `Undelivered` and `Recovered`.
|
|
44
|
+
|
|
6
45
|
## 1.8.0
|
|
7
46
|
|
|
8
47
|
### Breaking Changes
|
package/Core.sol
CHANGED
|
@@ -6,13 +6,14 @@ pragma solidity ^0.8.33;
|
|
|
6
6
|
|
|
7
7
|
import { AccessControl } from "./core/Access.sol";
|
|
8
8
|
import { Balances, InsufficientFunds } from "./core/Balances.sol";
|
|
9
|
-
import { Commitments } from "./core/Commitments.sol";
|
|
10
9
|
import { Escrows, InsufficientEscrow } from "./core/Escrows.sol";
|
|
11
10
|
import { NativeAsset, Runtime } from "./core/Runtime.sol";
|
|
12
11
|
import { Host, IHostIntroduction } from "./core/Host.sol";
|
|
13
12
|
import { CommandCalls, FailedCall, NodeCalls, PortCalls } from "./core/Calls.sol";
|
|
14
13
|
import { Payable } from "./core/Payable.sol";
|
|
15
14
|
import { Pipeline } from "./core/Pipeline.sol";
|
|
15
|
+
import { Portal } from "./core/Portal.sol";
|
|
16
|
+
import { RecoverHook } from "./commands/Recover.sol";
|
|
16
17
|
import { AssetAmount, AccountAsset, AccountAmount, HostAmount, HostAccountAsset, HostAccountAmount, Tx } from "./core/Types.sol";
|
|
17
18
|
import { Validator } from "./core/Validator.sol";
|
|
18
19
|
|
package/Endpoints.sol
CHANGED
|
@@ -16,8 +16,8 @@ import { DebitAccount, DebitAccountHook } from "./commands/Debit.sol";
|
|
|
16
16
|
import { Deposit, DepositHook, DepositPayable, DepositPayableHook } from "./commands/Deposit.sol";
|
|
17
17
|
import { Payout, PayoutHook } from "./commands/Payout.sol";
|
|
18
18
|
import { Provision, ProvisionHook, ProvisionPayable, ProvisionPayableHook } from "./commands/Provision.sol";
|
|
19
|
-
import {
|
|
20
|
-
import { RelayPayable,
|
|
19
|
+
import { RecoverHook, RecoverPayable } from "./commands/Recover.sol";
|
|
20
|
+
import { RelayPayable, RoutePayableHook } from "./commands/Relay.sol";
|
|
21
21
|
import { Withdraw, WithdrawHook } from "./commands/Withdraw.sol";
|
|
22
22
|
|
|
23
23
|
// Admin commands
|
package/Events.sol
CHANGED
|
@@ -10,10 +10,10 @@ import { Actions } from "./utils/Actions.sol";
|
|
|
10
10
|
import { BalanceEvent } from "./events/Balance.sol";
|
|
11
11
|
import { CommanderEvent } from "./events/Commander.sol";
|
|
12
12
|
import { CommandEvent } from "./events/Command.sol";
|
|
13
|
-
import { CommitmentEvent } from "./events/Commitment.sol";
|
|
14
13
|
import { DispatchEvent } from "./events/Dispatch.sol";
|
|
15
14
|
import { PositionEvent } from "./events/Position.sol";
|
|
16
15
|
import { ReceivedEvent } from "./events/Received.sol";
|
|
16
|
+
import { RecoveredEvent } from "./events/Recovered.sol";
|
|
17
17
|
import { EventEmitter } from "./events/Emitter.sol";
|
|
18
18
|
import { GuardEvent } from "./events/Guard.sol";
|
|
19
19
|
import { GuardianEvent } from "./events/Guardian.sol";
|
|
@@ -26,6 +26,7 @@ import { QueryEvent } from "./events/Query.sol";
|
|
|
26
26
|
import { RootedEvent } from "./events/Rooted.sol";
|
|
27
27
|
import { RouteEvent } from "./events/Route.sol";
|
|
28
28
|
import { SpentEvent } from "./events/Spent.sol";
|
|
29
|
+
import { UndeliveredEvent } from "./events/Undelivered.sol";
|
|
29
30
|
import { UnlockedEvent } from "./events/Unlocked.sol";
|
|
30
31
|
|
|
31
32
|
|
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
rootzero is a protocol for building **hosts**: contracts that expose a uniform
|
|
4
4
|
set of endpoints over accounts and assets — commands that change state,
|
|
5
|
-
queries that read it, and
|
|
5
|
+
queries that read it, and port links that connect hosts to each other, on the
|
|
6
6
|
same chain or across chains.
|
|
7
7
|
|
|
8
8
|
This repository is `@rootzero/contracts`, the Solidity library for the EVM port
|
|
@@ -160,7 +160,7 @@ structured ID announces what it is (an account, an asset, a node) and which
|
|
|
160
160
|
chain it lives on, and the payload usually embeds the underlying address. User
|
|
161
161
|
accounts are chain-agnostic; admin and guardian accounts are chain-local.
|
|
162
162
|
Assets are unique IDs in the same single-word form as accounts and nodes.
|
|
163
|
-
Nodes are hosts, commands,
|
|
163
|
+
Nodes are hosts, commands, ports, queries, and guards.
|
|
164
164
|
|
|
165
165
|
Opaque asset declarations use `Asset(host, asset, preimage)`. The preimage
|
|
166
166
|
starts with a one-byte format/hash tag, letting offchain indexers or witnesses
|
|
@@ -220,7 +220,7 @@ the batch, call the hook, write the output run:
|
|
|
220
220
|
|
|
221
221
|
```solidity
|
|
222
222
|
function deposit(CommandContext calldata c) external onlyCommand returns (bytes memory) {
|
|
223
|
-
(Cur memory request, uint groups
|
|
223
|
+
(Cur memory request, uint groups) = Cursors.init(c.request, 1);
|
|
224
224
|
Writer memory writer = Writers.allocBalances(groups);
|
|
225
225
|
|
|
226
226
|
while (request.i < request.len) {
|
|
@@ -258,7 +258,7 @@ The standard commands cover the common ledger movements: `deposit` and
|
|
|
258
258
|
`depositPayable` (external funds in), `withdraw` and `burn` (funds out),
|
|
259
259
|
`debitAccount` and `creditAccount` (internal movements), `payout` (deliver
|
|
260
260
|
state to other accounts), `provision` (allocate custody on another host), and
|
|
261
|
-
`relayPayable` (hand a pipeline to another
|
|
261
|
+
`relayPayable` (hand a pipeline to another portal).
|
|
262
262
|
|
|
263
263
|
## Pipelines
|
|
264
264
|
|
|
@@ -285,9 +285,9 @@ if (state.length != 0) revert UnexpectedState();
|
|
|
285
285
|
A transfer, for instance, is a two-step pipeline: `debitAccount` turns an
|
|
286
286
|
`#amount` request into `#balance` state, and `payout` consumes that state
|
|
287
287
|
toward a recipient. Because a pipeline is just blocks, it is also the unit of
|
|
288
|
-
command batching — and `resources` is a chain-
|
|
289
|
-
bits are native value in wei, drawn from a
|
|
290
|
-
bytes are meaningful to every port.
|
|
288
|
+
command batching — and `resources` is a chain-specific word interpreted by the
|
|
289
|
+
portal adapter (on EVM, the low 128 bits are native value in wei, drawn from a
|
|
290
|
+
shared budget), so the same pipeline bytes are meaningful to every port.
|
|
291
291
|
|
|
292
292
|
## Queries
|
|
293
293
|
|
|
@@ -314,10 +314,11 @@ central ones are batches all the way down:
|
|
|
314
314
|
block — how two hosts record settlement between their ledgers.
|
|
315
315
|
- `portPipePayable` consumes `#context` blocks, each carrying an account, an
|
|
316
316
|
initial state, and a run of steps — a complete pipeline delivered by another
|
|
317
|
-
host, executed locally against the
|
|
317
|
+
host, executed locally against the port call's shared value budget.
|
|
318
318
|
|
|
319
|
-
This is also the cross-
|
|
320
|
-
wraps a pipe and addresses it to a
|
|
319
|
+
This is also the cross-portal mechanism. `relayPayable` (or `portDispatchPayable`)
|
|
320
|
+
wraps a pipe and addresses it to a portal, commonly the destination host ID;
|
|
321
|
+
a bridge adapter moves the **raw
|
|
321
322
|
bytes**; the destination host parses them with the same cursor rules and runs
|
|
322
323
|
the same pipeline loop. Nothing in the payload is EVM-specific — step targets
|
|
323
324
|
are destination-local node IDs, and only the adapter boundary (native
|
|
@@ -350,8 +351,8 @@ names, access sets, balances — from logs alone, with no artifact files.
|
|
|
350
351
|
Import from the package entry points rather than deep paths:
|
|
351
352
|
|
|
352
353
|
- `@rootzero/contracts/Core.sol` — `Host`, access control, `Balances`,
|
|
353
|
-
`Pipeline`, validator
|
|
354
|
-
- `@rootzero/contracts/Endpoints.sol` — command, admin,
|
|
354
|
+
`Pipeline`, `Portal`, validator
|
|
355
|
+
- `@rootzero/contracts/Endpoints.sol` — command, admin, port, guard, and query
|
|
355
356
|
mixins and their hooks
|
|
356
357
|
- `@rootzero/contracts/Cursors.sol` — `Cur` cursor reader, `Writers`, `Schemas`,
|
|
357
358
|
`Keys`
|
|
@@ -363,7 +364,7 @@ Repo layout:
|
|
|
363
364
|
|
|
364
365
|
- `contracts/core` — host, access control, balances, pipeline, validation
|
|
365
366
|
- `contracts/commands` — standard commands and admin commands
|
|
366
|
-
- `contracts/ports` —
|
|
367
|
+
- `contracts/ports` — port surfaces for inter-host and cross-portal flows
|
|
367
368
|
- `contracts/guards` — guardian direct actions
|
|
368
369
|
- `contracts/queries` — read-only query endpoints
|
|
369
370
|
- `contracts/blocks` — block schema, cursor parsing, writers
|
package/blocks/Cursors.sol
CHANGED
|
@@ -76,16 +76,14 @@ library Cursors {
|
|
|
76
76
|
/// @param group Expected block group size (e.g. 1 for single, 2 for paired).
|
|
77
77
|
/// @return cur Cursor with `len` truncated to the end of the first run in `source`.
|
|
78
78
|
/// @return groups Number of block groups in the run (`block count / group`).
|
|
79
|
-
/// @return next Byte offset immediately after the run, relative to `source`.
|
|
80
79
|
function init(
|
|
81
80
|
bytes calldata source,
|
|
82
81
|
uint group
|
|
83
|
-
) internal pure returns (Cur memory cur, uint groups
|
|
82
|
+
) internal pure returns (Cur memory cur, uint groups) {
|
|
84
83
|
cur = open(source);
|
|
85
84
|
if (cur.i == cur.len) revert ZeroCursor();
|
|
86
85
|
(bytes4 key, ) = cur.peek(cur.i);
|
|
87
86
|
groups = cur.run(key, group);
|
|
88
|
-
next = cur.len;
|
|
89
87
|
}
|
|
90
88
|
|
|
91
89
|
/// @notice Create a cursor over `source`, restrict it to its first grouped run, and require an exact group count.
|
|
@@ -93,14 +91,13 @@ library Cursors {
|
|
|
93
91
|
/// @param group Expected block group size (e.g. 1 for single, 2 for paired).
|
|
94
92
|
/// @param expectedGroups Required number of groups in the run.
|
|
95
93
|
/// @return cur Cursor with `len` truncated to the end of the first run in `source`.
|
|
96
|
-
/// @return next Byte offset immediately after the run, relative to `source`.
|
|
97
94
|
function init(
|
|
98
95
|
bytes calldata source,
|
|
99
96
|
uint group,
|
|
100
97
|
uint expectedGroups
|
|
101
|
-
) internal pure returns (Cur memory cur
|
|
98
|
+
) internal pure returns (Cur memory cur) {
|
|
102
99
|
uint groups;
|
|
103
|
-
(cur, groups
|
|
100
|
+
(cur, groups) = init(source, group);
|
|
104
101
|
if (groups != expectedGroups) revert BadRatio();
|
|
105
102
|
}
|
|
106
103
|
|
|
@@ -333,13 +330,16 @@ library Cursors {
|
|
|
333
330
|
return find(cur, cur.i, key);
|
|
334
331
|
}
|
|
335
332
|
|
|
336
|
-
/// @notice Enter a
|
|
333
|
+
/// @notice Enter a LIST block at the expected current position and return its next offset.
|
|
334
|
+
/// Reverts with `IncompleteCursor` if `cur.i` is not exactly `pos`.
|
|
337
335
|
/// Advances `cur.i` past the list header so the list members can be parsed
|
|
338
336
|
/// directly from the same cursor. The returned `next` is the byte offset
|
|
339
337
|
/// immediately after the list payload, relative to the current cursor region.
|
|
340
|
-
/// @param cur Cursor positioned at a list block; advanced past the 8-byte header.
|
|
338
|
+
/// @param cur Cursor expected to be positioned at a list block; advanced past the 8-byte header.
|
|
339
|
+
/// @param pos Expected current cursor position, relative to the cursor region.
|
|
341
340
|
/// @return next Byte offset immediately after the list payload.
|
|
342
|
-
function list(Cur memory cur) internal pure returns (uint next) {
|
|
341
|
+
function list(Cur memory cur, uint pos) internal pure returns (uint next) {
|
|
342
|
+
cur.ensureAt(pos);
|
|
343
343
|
next = enter(cur, Keys.List, 0, 0);
|
|
344
344
|
}
|
|
345
345
|
|
|
@@ -387,13 +387,13 @@ library Cursors {
|
|
|
387
387
|
return maybeTake(cur, Keys.Data);
|
|
388
388
|
}
|
|
389
389
|
|
|
390
|
-
/// @notice
|
|
391
|
-
/// Reverts with `IncompleteCursor` if `
|
|
392
|
-
/// or `cur.i !=
|
|
390
|
+
/// @notice Ensure the cursor is at an exact position.
|
|
391
|
+
/// Reverts with `IncompleteCursor` if `pos` exceeds the cursor region length
|
|
392
|
+
/// or `cur.i != pos`.
|
|
393
393
|
/// @param cur Cursor to check.
|
|
394
|
-
/// @param
|
|
395
|
-
function
|
|
396
|
-
if (
|
|
394
|
+
/// @param pos Relative byte offset the cursor must be positioned at.
|
|
395
|
+
function ensureAt(Cur memory cur, uint pos) internal pure {
|
|
396
|
+
if (pos > cur.len || cur.i != pos) revert IncompleteCursor();
|
|
397
397
|
}
|
|
398
398
|
|
|
399
399
|
/// @notice Assert that the cursor has consumed its entire source region.
|
|
@@ -519,7 +519,7 @@ library Cursors {
|
|
|
519
519
|
|
|
520
520
|
/// @notice Encode a STEP block.
|
|
521
521
|
/// @param target Command target identifier.
|
|
522
|
-
/// @param resources
|
|
522
|
+
/// @param resources Packed resources assigned to the step.
|
|
523
523
|
/// @param request Raw nested request payload.
|
|
524
524
|
/// @return Encoded STEP block bytes.
|
|
525
525
|
function toStepBlock(uint target, uint resources, bytes memory request) internal pure returns (bytes memory) {
|
|
@@ -528,7 +528,7 @@ library Cursors {
|
|
|
528
528
|
|
|
529
529
|
/// @notice Encode a CALL block.
|
|
530
530
|
/// @param target Target node identifier.
|
|
531
|
-
/// @param resources
|
|
531
|
+
/// @param resources Packed resources assigned to the call.
|
|
532
532
|
/// @param data Raw calldata payload for the target.
|
|
533
533
|
/// @return Encoded CALL block bytes.
|
|
534
534
|
function toCallBlock(uint target, uint resources, bytes memory data) internal pure returns (bytes memory) {
|
|
@@ -549,21 +549,21 @@ library Cursors {
|
|
|
549
549
|
}
|
|
550
550
|
|
|
551
551
|
/// @notice Encode a RELAY block.
|
|
552
|
-
/// @param
|
|
553
|
-
/// @param resources Chain-
|
|
552
|
+
/// @param portal Destination portal identifier, often the destination host ID.
|
|
553
|
+
/// @param resources Chain-specific resources for the destination context.
|
|
554
554
|
/// @param request Nested request block stream.
|
|
555
555
|
/// @return Encoded RELAY block bytes.
|
|
556
|
-
function toRelayBlock(uint
|
|
557
|
-
return createBlock(Keys.Relay, bytes.concat(bytes32(
|
|
556
|
+
function toRelayBlock(uint portal, uint resources, bytes memory request) internal pure returns (bytes memory) {
|
|
557
|
+
return createBlock(Keys.Relay, bytes.concat(bytes32(portal), bytes32(resources), toBytesBlock(request)));
|
|
558
558
|
}
|
|
559
559
|
|
|
560
560
|
/// @notice Encode a DISPATCH block.
|
|
561
|
-
/// @param
|
|
562
|
-
/// @param resources Chain-
|
|
563
|
-
/// @param payload Encoded
|
|
561
|
+
/// @param portal Destination portal identifier, often the destination host ID.
|
|
562
|
+
/// @param resources Chain-specific resources for the destination dispatch.
|
|
563
|
+
/// @param payload Encoded payload.
|
|
564
564
|
/// @return Encoded DISPATCH block bytes.
|
|
565
|
-
function toDispatchBlock(uint
|
|
566
|
-
return createBlock(Keys.Dispatch, bytes.concat(bytes32(
|
|
565
|
+
function toDispatchBlock(uint portal, uint resources, bytes memory payload) internal pure returns (bytes memory) {
|
|
566
|
+
return createBlock(Keys.Dispatch, bytes.concat(bytes32(portal), bytes32(resources), toBytesBlock(payload)));
|
|
567
567
|
}
|
|
568
568
|
|
|
569
569
|
// -------------------------------------------------------------------------
|
|
@@ -747,7 +747,7 @@ library Cursors {
|
|
|
747
747
|
id = cur.readUint();
|
|
748
748
|
namespace = cur.read32();
|
|
749
749
|
name = cur.unpackString();
|
|
750
|
-
cur.
|
|
750
|
+
cur.ensureAt(end);
|
|
751
751
|
}
|
|
752
752
|
|
|
753
753
|
/// @notice Consume a dynamic block with a single bytes32 payload.
|
|
@@ -1100,28 +1100,28 @@ library Cursors {
|
|
|
1100
1100
|
/// The `req` slice is the raw payload of the block's required BYTES child.
|
|
1101
1101
|
/// @param cur Cursor; advanced past the block.
|
|
1102
1102
|
/// @return target Destination node ID for the sub-command.
|
|
1103
|
-
/// @return resources
|
|
1103
|
+
/// @return resources Packed resources assigned to the step.
|
|
1104
1104
|
/// @return req Embedded request bytes for the sub-command.
|
|
1105
1105
|
function unpackStep(Cur memory cur) internal pure returns (uint target, uint resources, bytes calldata req) {
|
|
1106
1106
|
uint end = cur.enter(Keys.Step, 64 + Sizes.Header, 0);
|
|
1107
1107
|
target = uint(cur.read32());
|
|
1108
1108
|
resources = uint(cur.read32());
|
|
1109
1109
|
req = cur.unpackBytes();
|
|
1110
|
-
cur.
|
|
1110
|
+
cur.ensureAt(end);
|
|
1111
1111
|
}
|
|
1112
1112
|
|
|
1113
1113
|
/// @notice Consume a CALL block and return its target invocation fields.
|
|
1114
1114
|
/// The `data` slice is the raw payload of the block's required BYTES child.
|
|
1115
1115
|
/// @param cur Cursor; advanced past the block.
|
|
1116
1116
|
/// @return target Target node ID to call.
|
|
1117
|
-
/// @return resources
|
|
1117
|
+
/// @return resources Packed resources assigned to the call.
|
|
1118
1118
|
/// @return data Raw calldata payload for the target.
|
|
1119
1119
|
function unpackCall(Cur memory cur) internal pure returns (uint target, uint resources, bytes calldata data) {
|
|
1120
1120
|
uint end = cur.enter(Keys.Call, 64 + Sizes.Header, 0);
|
|
1121
1121
|
target = uint(cur.read32());
|
|
1122
1122
|
resources = uint(cur.read32());
|
|
1123
1123
|
data = cur.unpackBytes();
|
|
1124
|
-
cur.
|
|
1124
|
+
cur.ensureAt(end);
|
|
1125
1125
|
}
|
|
1126
1126
|
|
|
1127
1127
|
/// @notice Consume a CONTEXT block and return its command context fields.
|
|
@@ -1137,54 +1137,54 @@ library Cursors {
|
|
|
1137
1137
|
account = cur.read32();
|
|
1138
1138
|
state = cur.unpackBytes();
|
|
1139
1139
|
request = cur.unpackBytes();
|
|
1140
|
-
cur.
|
|
1140
|
+
cur.ensureAt(end);
|
|
1141
1141
|
}
|
|
1142
1142
|
|
|
1143
|
-
/// @notice Consume a RELAY block and return its destination
|
|
1143
|
+
/// @notice Consume a RELAY block and return its destination portal, resources, and request stream.
|
|
1144
1144
|
/// @param cur Cursor; advanced past the block.
|
|
1145
|
-
/// @return
|
|
1146
|
-
/// @return resources Chain-
|
|
1145
|
+
/// @return portal Destination portal identifier, often the destination host ID.
|
|
1146
|
+
/// @return resources Chain-specific resources for the destination context.
|
|
1147
1147
|
/// @return request Embedded request block stream.
|
|
1148
1148
|
function unpackRelay(
|
|
1149
1149
|
Cur memory cur
|
|
1150
|
-
) internal pure returns (uint
|
|
1150
|
+
) internal pure returns (uint portal, uint resources, bytes calldata request) {
|
|
1151
1151
|
uint end = cur.enter(Keys.Relay, 64 + Sizes.Header, 0);
|
|
1152
|
-
|
|
1152
|
+
portal = cur.readUint();
|
|
1153
1153
|
resources = cur.readUint();
|
|
1154
1154
|
request = cur.unpackBytes();
|
|
1155
|
-
cur.
|
|
1155
|
+
cur.ensureAt(end);
|
|
1156
1156
|
}
|
|
1157
1157
|
|
|
1158
|
-
/// @notice Consume a DISPATCH block and return its destination
|
|
1158
|
+
/// @notice Consume a DISPATCH block and return its destination portal, resources, and payload.
|
|
1159
1159
|
/// @param cur Cursor; advanced past the block.
|
|
1160
|
-
/// @return
|
|
1161
|
-
/// @return resources Chain-
|
|
1162
|
-
/// @return payload Encoded
|
|
1160
|
+
/// @return portal Destination portal identifier, often the destination host ID.
|
|
1161
|
+
/// @return resources Chain-specific resources for the destination dispatch.
|
|
1162
|
+
/// @return payload Encoded payload.
|
|
1163
1163
|
function unpackDispatch(
|
|
1164
1164
|
Cur memory cur
|
|
1165
|
-
) internal pure returns (uint
|
|
1165
|
+
) internal pure returns (uint portal, uint resources, bytes calldata payload) {
|
|
1166
1166
|
uint end = cur.enter(Keys.Dispatch, 64 + Sizes.Header, 0);
|
|
1167
|
-
|
|
1167
|
+
portal = cur.readUint();
|
|
1168
1168
|
resources = cur.readUint();
|
|
1169
1169
|
payload = cur.unpackBytes();
|
|
1170
|
-
cur.
|
|
1170
|
+
cur.ensureAt(end);
|
|
1171
1171
|
}
|
|
1172
1172
|
|
|
1173
|
-
/// @notice Consume a
|
|
1173
|
+
/// @notice Consume a RECOVER block and return its handler, resources, key, and witness bytes.
|
|
1174
1174
|
/// @param cur Cursor; advanced past the block.
|
|
1175
|
-
/// @return
|
|
1176
|
-
/// @return
|
|
1177
|
-
/// @return
|
|
1178
|
-
/// @return
|
|
1179
|
-
function
|
|
1175
|
+
/// @return handler Recovery handler port node ID.
|
|
1176
|
+
/// @return resources Packed resources assigned to the recovery attempt.
|
|
1177
|
+
/// @return key Recovery lookup key.
|
|
1178
|
+
/// @return witness Witness bytes used by the recovery handler.
|
|
1179
|
+
function unpackRecover(
|
|
1180
1180
|
Cur memory cur
|
|
1181
|
-
) internal pure returns (uint
|
|
1182
|
-
uint end = cur.enter(Keys.
|
|
1183
|
-
|
|
1184
|
-
key = cur.read32();
|
|
1181
|
+
) internal pure returns (uint handler, uint resources, bytes32 key, bytes calldata witness) {
|
|
1182
|
+
uint end = cur.enter(Keys.Recover, 96 + Sizes.Header, 0);
|
|
1183
|
+
handler = cur.readUint();
|
|
1185
1184
|
resources = cur.readUint();
|
|
1186
|
-
|
|
1187
|
-
cur.
|
|
1185
|
+
key = cur.read32();
|
|
1186
|
+
witness = cur.unpackBytes();
|
|
1187
|
+
cur.ensureAt(end);
|
|
1188
1188
|
}
|
|
1189
1189
|
|
|
1190
1190
|
// Type-specific validators
|
|
@@ -1379,16 +1379,16 @@ library Cursors {
|
|
|
1379
1379
|
/// @param cur Cursor; advanced past the RELAY block.
|
|
1380
1380
|
/// @param account Account identifier to embed in the destination context.
|
|
1381
1381
|
/// @param state State block stream to embed in the destination context.
|
|
1382
|
-
/// @return
|
|
1383
|
-
/// @return resources Chain resources assigned to the destination context.
|
|
1382
|
+
/// @return portal Destination portal identifier, often the destination host ID.
|
|
1383
|
+
/// @return resources Chain-specific resources assigned to the destination context.
|
|
1384
1384
|
/// @return context Encoded CONTEXT block containing `account`, `state`, and relay request.
|
|
1385
1385
|
function relayToContext(
|
|
1386
1386
|
Cur memory cur,
|
|
1387
1387
|
bytes32 account,
|
|
1388
1388
|
bytes calldata state
|
|
1389
|
-
) internal pure returns (uint
|
|
1389
|
+
) internal pure returns (uint portal, uint resources, bytes memory context) {
|
|
1390
1390
|
bytes calldata request;
|
|
1391
|
-
(
|
|
1391
|
+
(portal, resources, request) = cur.unpackRelay();
|
|
1392
1392
|
context = toContextBlock(account, bytes(state), bytes(request));
|
|
1393
1393
|
}
|
|
1394
1394
|
|
package/blocks/Keys.sol
CHANGED
|
@@ -41,13 +41,13 @@ library Keys {
|
|
|
41
41
|
bytes4 constant Transaction = bytes4(keccak256("#transaction"));
|
|
42
42
|
/// @dev Sub-command invocation - (uint target, uint resources, #bytes as request)
|
|
43
43
|
bytes4 constant Step = bytes4(keccak256("#step"));
|
|
44
|
-
/// @dev
|
|
44
|
+
/// @dev Portal relay request - (uint portal, uint resources, #bytes as request)
|
|
45
45
|
bytes4 constant Relay = bytes4(keccak256("#relay"));
|
|
46
46
|
/// @dev Command context transport - (bytes32 account, #bytes as state, #bytes as request)
|
|
47
47
|
bytes4 constant Context = bytes4(keccak256("#context"));
|
|
48
|
-
/// @dev Recoverable
|
|
49
|
-
bytes4 constant
|
|
50
|
-
/// @dev
|
|
48
|
+
/// @dev Recoverable witness - (uint handler, uint resources, bytes32 key, #bytes as witness)
|
|
49
|
+
bytes4 constant Recover = bytes4(keccak256("#recover"));
|
|
50
|
+
/// @dev Portal encoded payload dispatch - (uint portal, uint resources, #bytes as payload)
|
|
51
51
|
bytes4 constant Dispatch = bytes4(keccak256("#dispatch"));
|
|
52
52
|
/// @dev Raw external call - (uint target, uint resources, #bytes as payload)
|
|
53
53
|
bytes4 constant Call = bytes4(keccak256("#call"));
|
package/blocks/Schema.sol
CHANGED
|
@@ -16,10 +16,11 @@ pragma solidity ^0.8.33;
|
|
|
16
16
|
// - run items may repeat at top level for batching
|
|
17
17
|
// - `maybe #x { ... }` marks an optional block item
|
|
18
18
|
// - `many #x { ... }` emits one generic list block containing repeated `#x` items
|
|
19
|
-
// - `
|
|
20
|
-
//
|
|
21
|
-
//
|
|
22
|
-
//
|
|
19
|
+
// - `portal` fields are routing identifiers, often destination host IDs
|
|
20
|
+
// - `resources` fields are chain-specific resource words. A portal adapter
|
|
21
|
+
// interprets them for the destination runtime. EVM resources use the low
|
|
22
|
+
// 128 bits as native value.
|
|
23
|
+
// - dotted field names and aliases, e.g. `dst.portal` or `#bytes as dst.payload`,
|
|
23
24
|
// are offchain projection metadata only and do not change runtime encoding
|
|
24
25
|
// - a child block without an inline body, e.g. `#context as witness`, may resolve
|
|
25
26
|
// to a known schema in the active schema context; unresolved aliases are invalid
|
|
@@ -71,11 +72,11 @@ library Schemas {
|
|
|
71
72
|
string constant Allowance = "#allowance { uint host, bytes32 asset, uint amount }";
|
|
72
73
|
string constant Transaction = "#transaction { bytes32 from, bytes32 to, bytes32 asset, uint amount }";
|
|
73
74
|
string constant Context = "#context { bytes32 account, #bytes as state, #bytes as request }";
|
|
74
|
-
string constant
|
|
75
|
+
string constant Recover = "#recover { uint handler, uint resources, bytes32 key, #bytes as witness }";
|
|
75
76
|
string constant Call = "#call { uint target, uint resources, #bytes as payload }";
|
|
76
77
|
string constant Step = "#step { uint target, uint resources, #bytes as request }";
|
|
77
|
-
string constant Relay = "#relay { uint
|
|
78
|
-
string constant Dispatch = "#dispatch { uint
|
|
78
|
+
string constant Relay = "#relay { uint portal, uint resources, #bytes as request }";
|
|
79
|
+
string constant Dispatch = "#dispatch { uint portal, uint resources, #bytes as payload }";
|
|
79
80
|
string constant Bounty = "#bounty { uint amount, bytes32 relayer }";
|
|
80
81
|
string constant Fee = "#fee { uint amount }";
|
|
81
82
|
string constant Auth = "#auth { uint cid, uint deadline, #bytes as proof }";
|
package/blocks/Writers.sol
CHANGED
|
@@ -872,7 +872,7 @@ library Writers {
|
|
|
872
872
|
/// @notice Append a STEP block with a nested request BYTES payload.
|
|
873
873
|
/// @param writer Destination writer; `i` is advanced by the encoded STEP block length.
|
|
874
874
|
/// @param target Command target identifier.
|
|
875
|
-
/// @param resources
|
|
875
|
+
/// @param resources Packed resources assigned to the step.
|
|
876
876
|
/// @param request Raw nested request payload.
|
|
877
877
|
function appendStep(Writer memory writer, uint target, uint resources, bytes memory request) internal pure {
|
|
878
878
|
appendBlock64Bytes(writer, Keys.Step, bytes32(target), bytes32(resources), request);
|
|
@@ -881,7 +881,7 @@ library Writers {
|
|
|
881
881
|
/// @notice Append a CALL block with a nested payload BYTES block.
|
|
882
882
|
/// @param writer Destination writer; `i` is advanced by the encoded CALL block length.
|
|
883
883
|
/// @param target Call target identifier.
|
|
884
|
-
/// @param resources
|
|
884
|
+
/// @param resources Packed resources assigned to the call.
|
|
885
885
|
/// @param data Raw nested call payload.
|
|
886
886
|
function appendCall(Writer memory writer, uint target, uint resources, bytes memory data) internal pure {
|
|
887
887
|
appendBlock64Bytes(writer, Keys.Call, bytes32(target), bytes32(resources), data);
|
package/commands/Burn.sol
CHANGED
|
@@ -30,7 +30,7 @@ abstract contract Burn is CommandBase, BurnHook {
|
|
|
30
30
|
/// @param c Command context; `c.state` must contain BALANCE blocks.
|
|
31
31
|
/// @return Empty output state.
|
|
32
32
|
function burn(CommandContext calldata c) external onlyCommand returns (bytes memory) {
|
|
33
|
-
(Cur memory state,
|
|
33
|
+
(Cur memory state, ) = Cursors.init(c.state, 1);
|
|
34
34
|
|
|
35
35
|
while (state.i < state.len) {
|
|
36
36
|
(bytes32 asset, uint amount) = state.unpackBalance();
|
package/commands/Credit.sol
CHANGED
|
@@ -32,7 +32,7 @@ abstract contract CreditAccount is CommandBase, CreditAccountHook {
|
|
|
32
32
|
function creditAccount(
|
|
33
33
|
CommandContext calldata c
|
|
34
34
|
) external onlyCommand returns (bytes memory) {
|
|
35
|
-
(Cur memory state,
|
|
35
|
+
(Cur memory state, ) = Cursors.init(c.state, 1);
|
|
36
36
|
|
|
37
37
|
while (state.i < state.len) {
|
|
38
38
|
(bytes32 asset, uint amount) = state.unpackBalance();
|
package/commands/Debit.sol
CHANGED
|
@@ -32,7 +32,7 @@ abstract contract DebitAccount is CommandBase, DebitAccountHook {
|
|
|
32
32
|
/// The default implementation iterates AMOUNT blocks, calls
|
|
33
33
|
/// `debitAccount`, and emits matching BALANCE blocks.
|
|
34
34
|
function debitAccount(bytes32 account, bytes calldata request) internal virtual returns (bytes memory) {
|
|
35
|
-
(Cur memory input, uint groups
|
|
35
|
+
(Cur memory input, uint groups) = Cursors.init(request, 1);
|
|
36
36
|
Writer memory writer = Writers.allocBalances(groups);
|
|
37
37
|
|
|
38
38
|
while (input.i < input.len) {
|
package/commands/Deposit.sol
CHANGED
|
@@ -48,7 +48,7 @@ abstract contract Deposit is CommandBase, DepositHook {
|
|
|
48
48
|
function deposit(
|
|
49
49
|
CommandContext calldata c
|
|
50
50
|
) external onlyCommand returns (bytes memory) {
|
|
51
|
-
(Cur memory request, uint groups
|
|
51
|
+
(Cur memory request, uint groups) = Cursors.init(c.request, 1);
|
|
52
52
|
Writer memory writer = Writers.allocBalances(groups);
|
|
53
53
|
|
|
54
54
|
while (request.i < request.len) {
|
|
@@ -79,7 +79,7 @@ abstract contract DepositPayable is CommandBase, Payable, DepositPayableHook {
|
|
|
79
79
|
function depositPayable(
|
|
80
80
|
CommandContext calldata c
|
|
81
81
|
) external payable onlyCommand returns (bytes memory) {
|
|
82
|
-
(Cur memory request, uint groups
|
|
82
|
+
(Cur memory request, uint groups) = Cursors.init(c.request, 1);
|
|
83
83
|
Writer memory writer = Writers.allocBalances(groups);
|
|
84
84
|
Budget memory budget = openValue();
|
|
85
85
|
|
package/commands/Payout.sol
CHANGED
|
@@ -31,8 +31,8 @@ abstract contract Payout is CommandBase, PayoutHook {
|
|
|
31
31
|
/// @param c Command context; `c.state` must contain BALANCE blocks and `c.request` matching ACCOUNT blocks.
|
|
32
32
|
/// @return Empty output state.
|
|
33
33
|
function payout(CommandContext calldata c) external onlyCommand returns (bytes memory) {
|
|
34
|
-
(Cur memory state, uint groups
|
|
35
|
-
|
|
34
|
+
(Cur memory state, uint groups) = Cursors.init(c.state, 1);
|
|
35
|
+
Cur memory request = Cursors.init(c.request, 1, groups);
|
|
36
36
|
|
|
37
37
|
while (state.i < state.len) {
|
|
38
38
|
(bytes32 asset, uint amount) = state.unpackBalance();
|
package/commands/Provision.sol
CHANGED
|
@@ -44,7 +44,7 @@ abstract contract Provision is CommandBase, ProvisionHook {
|
|
|
44
44
|
/// @param c Command context; `c.request` must contain ALLOCATION blocks.
|
|
45
45
|
/// @return CUSTODY block stream matching the provisioned allocations.
|
|
46
46
|
function provision(CommandContext calldata c) external onlyCommand returns (bytes memory) {
|
|
47
|
-
(Cur memory request, uint groups
|
|
47
|
+
(Cur memory request, uint groups) = Cursors.init(c.request, 1);
|
|
48
48
|
Writer memory writer = Writers.allocCustodies(groups);
|
|
49
49
|
|
|
50
50
|
while (request.i < request.len) {
|
|
@@ -76,7 +76,7 @@ abstract contract ProvisionPayable is CommandBase, Payable, ProvisionPayableHook
|
|
|
76
76
|
function provisionPayable(
|
|
77
77
|
CommandContext calldata c
|
|
78
78
|
) external payable onlyCommand returns (bytes memory) {
|
|
79
|
-
(Cur memory request, uint groups
|
|
79
|
+
(Cur memory request, uint groups) = Cursors.init(c.request, 1);
|
|
80
80
|
Writer memory writer = Writers.allocCustodies(groups);
|
|
81
81
|
Budget memory budget = openValue();
|
|
82
82
|
|