@rootzero/contracts 1.18.0 → 1.20.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 +96 -0
- package/Endpoints.sol +39 -44
- package/Events.sol +1 -0
- package/README.md +2 -2
- package/Utils.sol +0 -1
- package/annotations/Label.sol +1 -5
- package/codec/Blocks.sol +359 -74
- package/codec/Buffers.sol +14 -0
- package/codec/Decoders.sol +59 -0
- package/codec/Writers.sol +102 -0
- package/commands/Base.sol +1 -2
- package/commands/Credit.sol +2 -2
- package/commands/Debit.sol +2 -2
- package/commands/Relay.sol +18 -13
- package/commands/Settle.sol +2 -2
- package/core/Settlement.sol +1 -1
- package/docs/Schema.md +5 -0
- package/events/Relay.sol +20 -0
- package/execution/Execution.sol +150 -0
- package/guards/Base.sol +1 -2
- package/package.json +1 -1
- package/ports/AllowAssets.sol +2 -2
- package/ports/Allowance.sol +2 -2
- package/ports/Base.sol +1 -2
- package/ports/Credit.sol +2 -2
- package/ports/Debit.sol +2 -2
- package/ports/DenyAssets.sol +2 -2
- package/ports/Dispatch.sol +18 -7
- package/ports/Pipe.sol +2 -2
- package/ports/Post.sol +2 -2
- package/ports/Redeem.sol +2 -2
- package/queries/Base.sol +1 -2
- package/utils/Cursors.sol +10 -3
- package/utils/Nodes.sol +21 -16
- package/utils/Selectors.sol +0 -49
package/codec/Writers.sol
CHANGED
|
@@ -22,6 +22,7 @@ struct Writer {
|
|
|
22
22
|
/// then lazily allocates and writes binary-encoded blocks sequentially.
|
|
23
23
|
/// Physical allocation is rounded up to whole 32-byte words for scratch space,
|
|
24
24
|
/// while the writer cursor length tracks logical capacity. Call `finish` to trim the buffer.
|
|
25
|
+
/// `append*` helpers consume memory inputs; `copy*` helpers consume calldata inputs.
|
|
25
26
|
library Writers {
|
|
26
27
|
// -------------------------------------------------------------------------
|
|
27
28
|
// Initialization helpers
|
|
@@ -497,6 +498,107 @@ library Writers {
|
|
|
497
498
|
Blocks.writeSchema(writer.dst, i, spec, body, name);
|
|
498
499
|
}
|
|
499
500
|
|
|
501
|
+
// -------------------------------------------------------------------------
|
|
502
|
+
// Calldata copy helpers
|
|
503
|
+
// -------------------------------------------------------------------------
|
|
504
|
+
|
|
505
|
+
/// @notice Append arbitrary calldata bytes to the writer.
|
|
506
|
+
/// @param writer Destination writer; `i` is advanced by `data.length`.
|
|
507
|
+
/// @param data Calldata bytes to append.
|
|
508
|
+
function copy(Writer memory writer, bytes calldata data) internal pure {
|
|
509
|
+
uint i = reserve(writer, data.length, data.length);
|
|
510
|
+
Buffers.copy(writer.dst, i, data);
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
/// @notice Append a custom block by copying its payload from calldata.
|
|
514
|
+
function copyBlock(Writer memory writer, uint spec, bytes calldata data) internal pure {
|
|
515
|
+
Specs.validate(spec, data.length);
|
|
516
|
+
uint size = Sizes.Header + data.length;
|
|
517
|
+
uint i = reserve(writer, size);
|
|
518
|
+
Blocks.copy(writer.dst, i, Specs.key(spec), data);
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
/// @notice Append a LIST block by copying its payload from calldata.
|
|
522
|
+
function copyList(Writer memory writer, bytes calldata value) internal pure {
|
|
523
|
+
uint size = Sizes.Header + value.length;
|
|
524
|
+
uint i = reserve(writer, size);
|
|
525
|
+
Blocks.copyList(writer.dst, i, value);
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
/// @notice Append an EVM block by copying its payload from calldata.
|
|
529
|
+
function copyEvm(Writer memory writer, bytes calldata value) internal pure {
|
|
530
|
+
uint size = Sizes.Header + value.length;
|
|
531
|
+
uint i = reserve(writer, size);
|
|
532
|
+
Blocks.copyEvm(writer.dst, i, value);
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
/// @notice Append a BYTES block by copying its payload from calldata.
|
|
536
|
+
function copyBytes(Writer memory writer, bytes calldata value) internal pure {
|
|
537
|
+
uint size = Sizes.Header + value.length;
|
|
538
|
+
uint i = reserve(writer, size);
|
|
539
|
+
Blocks.copyBytes(writer.dst, i, value);
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
/// @notice Append a STRING block by copying its payload from calldata.
|
|
543
|
+
function copyString(Writer memory writer, string calldata value) internal pure {
|
|
544
|
+
uint size = Sizes.Header + bytes(value).length;
|
|
545
|
+
uint i = reserve(writer, size);
|
|
546
|
+
Blocks.copyString(writer.dst, i, value);
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
/// @notice Append a STEP block by copying its nested input from calldata.
|
|
550
|
+
function copyStep(Writer memory writer, uint cmd, uint resources, bytes calldata input) internal pure {
|
|
551
|
+
uint size = Sizes.B64 + Sizes.Header + input.length;
|
|
552
|
+
uint i = reserve(writer, size);
|
|
553
|
+
Blocks.copyStep(writer.dst, i, cmd, resources, input);
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
/// @notice Append a CALL block by copying its nested payload from calldata.
|
|
557
|
+
function copyCall(Writer memory writer, uint target, uint resources, bytes calldata payload) internal pure {
|
|
558
|
+
uint size = Sizes.B64 + Sizes.Header + payload.length;
|
|
559
|
+
uint i = reserve(writer, size);
|
|
560
|
+
Blocks.copyCall(writer.dst, i, target, resources, payload);
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
/// @notice Append a RELAY block by copying its nested input from calldata.
|
|
564
|
+
function copyRelay(Writer memory writer, uint portal, uint resources, bytes calldata input) internal pure {
|
|
565
|
+
uint size = Sizes.B64 + Sizes.Header + input.length;
|
|
566
|
+
uint i = reserve(writer, size);
|
|
567
|
+
Blocks.copyRelay(writer.dst, i, portal, resources, input);
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
/// @notice Append a DISPATCH block by copying its nested payload from calldata.
|
|
571
|
+
function copyDispatch(Writer memory writer, uint portal, uint resources, bytes calldata payload) internal pure {
|
|
572
|
+
uint size = Sizes.B64 + Sizes.Header + payload.length;
|
|
573
|
+
uint i = reserve(writer, size);
|
|
574
|
+
Blocks.copyDispatch(writer.dst, i, portal, resources, payload);
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
/// @notice Append a CONTEXT block by copying its nested streams from calldata.
|
|
578
|
+
function copyContext(
|
|
579
|
+
Writer memory writer,
|
|
580
|
+
bytes32 account,
|
|
581
|
+
bytes calldata state,
|
|
582
|
+
bytes calldata input
|
|
583
|
+
) internal pure {
|
|
584
|
+
uint size = Sizes.B32 + 2 * Sizes.Header + state.length + input.length;
|
|
585
|
+
uint i = reserve(writer, size);
|
|
586
|
+
Blocks.copyContext(writer.dst, i, account, state, input);
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
/// @notice Append a RECOVER block by copying its nested witness from calldata.
|
|
590
|
+
function copyRecover(
|
|
591
|
+
Writer memory writer,
|
|
592
|
+
uint handler,
|
|
593
|
+
uint resources,
|
|
594
|
+
bytes32 recoverykey,
|
|
595
|
+
bytes calldata witness
|
|
596
|
+
) internal pure {
|
|
597
|
+
uint size = Sizes.B96 + Sizes.Header + witness.length;
|
|
598
|
+
uint i = reserve(writer, size);
|
|
599
|
+
Blocks.copyRecover(writer.dst, i, handler, resources, recoverykey, witness);
|
|
600
|
+
}
|
|
601
|
+
|
|
500
602
|
// -------------------------------------------------------------------------
|
|
501
603
|
// Finalisation
|
|
502
604
|
// -------------------------------------------------------------------------
|
package/commands/Base.sol
CHANGED
|
@@ -11,7 +11,6 @@ import {ReceivedEvent} from "../events/Received.sol";
|
|
|
11
11
|
import {Actions} from "../utils/Actions.sol";
|
|
12
12
|
import {Descriptors} from "../codec/Descriptors.sol";
|
|
13
13
|
import {Nodes} from "../utils/Nodes.sol";
|
|
14
|
-
import {Selectors} from "../utils/Selectors.sol";
|
|
15
14
|
import {Cursors} from "../utils/Cursors.sol";
|
|
16
15
|
|
|
17
16
|
using Executions for Execution;
|
|
@@ -72,7 +71,7 @@ abstract contract CommandBase is CallerAccess, EndpointBase, ReceivedEvent {
|
|
|
72
71
|
/// @return id Command node ID.
|
|
73
72
|
/// @return published Published endpoint descriptor.
|
|
74
73
|
function command(string memory name, uint descriptor) internal returns (uint id, uint published) {
|
|
75
|
-
id = Nodes.toCommand(
|
|
74
|
+
id = Nodes.toCommand(name, address(this));
|
|
76
75
|
published = endpoint(id, name, descriptor);
|
|
77
76
|
}
|
|
78
77
|
|
package/commands/Credit.sol
CHANGED
|
@@ -45,11 +45,11 @@ abstract contract CreditAccount is CommandBase, CreditAccountHook {
|
|
|
45
45
|
}
|
|
46
46
|
}
|
|
47
47
|
|
|
48
|
-
/// @title
|
|
48
|
+
/// @title CreditAccountInternal
|
|
49
49
|
/// @notice Extends the advertised credit-account command with memory-state pipeline dispatch.
|
|
50
50
|
/// @dev This adapter is not a separate command. It uses the command ID and account hook
|
|
51
51
|
/// inherited from `CreditAccount` while accepting the state location used by `Pipeline`.
|
|
52
|
-
abstract contract
|
|
52
|
+
abstract contract CreditAccountInternal is CreditAccount {
|
|
53
53
|
/// @notice Execute the inherited credit-account command from an internal pipeline.
|
|
54
54
|
/// @param account Account credited by each balance.
|
|
55
55
|
/// @param state BALANCE block stream held in pipeline memory.
|
package/commands/Debit.sol
CHANGED
|
@@ -49,11 +49,11 @@ abstract contract DebitAccount is CommandBase, DebitAccountHook {
|
|
|
49
49
|
}
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
-
/// @title
|
|
52
|
+
/// @title DebitAccountInternal
|
|
53
53
|
/// @notice Extends the advertised debit-account command with memory-state pipeline dispatch.
|
|
54
54
|
/// @dev This adapter is not a separate command. It uses the command ID and account hook
|
|
55
55
|
/// inherited from `DebitAccount` while accepting the state location used by `Pipeline`.
|
|
56
|
-
abstract contract
|
|
56
|
+
abstract contract DebitAccountInternal is DebitAccount {
|
|
57
57
|
/// @notice Execute the inherited debit-account command from an internal pipeline.
|
|
58
58
|
/// @param account Account whose funds are debited.
|
|
59
59
|
/// @param state Empty pipeline state required by the command schema.
|
package/commands/Relay.sol
CHANGED
|
@@ -1,20 +1,29 @@
|
|
|
1
1
|
// SPDX-License-Identifier: GPL-3.0-only
|
|
2
2
|
pragma solidity ^0.8.33;
|
|
3
3
|
|
|
4
|
-
import {
|
|
4
|
+
import {Execution, Executions, CommandBase, Lanes, Specs} from "./Base.sol";
|
|
5
5
|
|
|
6
6
|
using Executions for Execution;
|
|
7
7
|
|
|
8
|
-
/// @notice Hook implemented by hosts that
|
|
8
|
+
/// @notice Hook implemented by hosts that relay command contexts.
|
|
9
9
|
abstract contract RelayPayableHook {
|
|
10
|
-
/// @notice Override to relay
|
|
10
|
+
/// @notice Override to relay a command context to `portal`.
|
|
11
11
|
/// @param portal Destination portal identifier, often the destination host ID.
|
|
12
12
|
/// @param resources Chain-specific destination resources. EVM adapters
|
|
13
13
|
/// may interpret this as packed execution gas and destination value.
|
|
14
|
-
/// @param
|
|
14
|
+
/// @param account Destination command account.
|
|
15
|
+
/// @param state State forwarded into the destination context.
|
|
16
|
+
/// @param input Input forwarded into the destination context.
|
|
15
17
|
/// @param funds Execution used for source value available for transport fees
|
|
16
18
|
/// and destination resource funding.
|
|
17
|
-
function
|
|
19
|
+
function relay(
|
|
20
|
+
uint portal,
|
|
21
|
+
uint resources,
|
|
22
|
+
bytes32 account,
|
|
23
|
+
bytes calldata state,
|
|
24
|
+
bytes calldata input,
|
|
25
|
+
Execution memory funds
|
|
26
|
+
) internal virtual;
|
|
18
27
|
}
|
|
19
28
|
|
|
20
29
|
/// @title RelayPayable
|
|
@@ -33,10 +42,8 @@ abstract contract RelayPayable is CommandBase, RelayPayableHook {
|
|
|
33
42
|
bytes calldata input
|
|
34
43
|
) external payable onlyCommand returns (bytes memory, bytes memory) {
|
|
35
44
|
Execution memory exec = openCommand(state, input, descriptor, 1);
|
|
36
|
-
(uint portal, uint resources, bytes calldata
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
relayTo(portal, resources, context, exec);
|
|
45
|
+
(uint portal, uint resources, bytes calldata relayInput) = exec.unpackRelay(Lanes.Input);
|
|
46
|
+
relay(portal, resources, account, state, relayInput, exec);
|
|
40
47
|
|
|
41
48
|
return close(exec, account);
|
|
42
49
|
}
|
|
@@ -65,10 +72,8 @@ abstract contract RelayBalancePayable is CommandBase, RelayPayableHook {
|
|
|
65
72
|
bytes calldata input
|
|
66
73
|
) external payable onlyCommand returns (bytes memory, bytes memory) {
|
|
67
74
|
Execution memory exec = openCommand(state, input, descriptor, 1);
|
|
68
|
-
(uint portal, uint resources, bytes calldata
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
relayTo(portal, resources, context, exec);
|
|
75
|
+
(uint portal, uint resources, bytes calldata relayInput) = exec.unpackRelay(Lanes.Input);
|
|
76
|
+
relay(portal, resources, account, state, relayInput, exec);
|
|
72
77
|
|
|
73
78
|
return close(exec, account);
|
|
74
79
|
}
|
package/commands/Settle.sol
CHANGED
|
@@ -97,11 +97,11 @@ abstract contract SettlePayable is CommandBase, SettlePayableHook, Action {
|
|
|
97
97
|
}
|
|
98
98
|
}
|
|
99
99
|
|
|
100
|
-
/// @title
|
|
100
|
+
/// @title SettleInternal
|
|
101
101
|
/// @notice Extends the advertised settle command with memory-state pipeline dispatch.
|
|
102
102
|
/// @dev This adapter is not a separate command. It uses the command ID and settlement hook
|
|
103
103
|
/// inherited from `Settle` while accepting the state location used by `Pipeline`.
|
|
104
|
-
abstract contract
|
|
104
|
+
abstract contract SettleInternal is Settle {
|
|
105
105
|
/// @notice Execute the inherited settle command from an internal pipeline.
|
|
106
106
|
/// @param account Account for which each position is settled.
|
|
107
107
|
/// @param state POSITION block stream held in pipeline memory.
|
package/core/Settlement.sol
CHANGED
|
@@ -69,7 +69,7 @@ abstract contract Settlement is PostHook, SettleHook, RepayHook, DebitAccountHoo
|
|
|
69
69
|
bytes32 liability,
|
|
70
70
|
uint debt
|
|
71
71
|
) internal virtual override {
|
|
72
|
+
repay(account, liability, debt);
|
|
72
73
|
if (amount != 0) creditAccount(account, asset, amount);
|
|
73
|
-
if (debt != 0) debitAccount(account, liability, debt);
|
|
74
74
|
}
|
|
75
75
|
}
|
package/docs/Schema.md
CHANGED
|
@@ -301,6 +301,11 @@ bytes1 through bytes32
|
|
|
301
301
|
`uint` means `uint256`; `int` means `int256`. Other integer widths, unsized
|
|
302
302
|
`bytes`, `string`, and array syntax are not part of the core schema DSL.
|
|
303
303
|
|
|
304
|
+
Restricting fixed bytes to the power-of-two widths `bytes1`, `bytes2`,
|
|
305
|
+
`bytes4`, `bytes8`, `bytes16`, and `bytes32` is under consideration, but has
|
|
306
|
+
not been decided. Until that decision is made, the schema DSL continues to
|
|
307
|
+
allow every `bytesN` width from 1 through 32.
|
|
308
|
+
|
|
304
309
|
Integers are encoded big-endian. Signed integers use two's-complement encoding
|
|
305
310
|
for their declared width. `bool` is one byte: `0x00` for false and `0x01` for
|
|
306
311
|
true. `bytesN` values are encoded as exactly `N` bytes with no padding.
|
package/events/Relay.sol
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
// SPDX-License-Identifier: GPL-3.0-only
|
|
2
|
+
pragma solidity ^0.8.33;
|
|
3
|
+
|
|
4
|
+
import {EventEmitter} from "./Emitter.sol";
|
|
5
|
+
|
|
6
|
+
/// @notice Emitted when an account records an outbound relay reference.
|
|
7
|
+
abstract contract RelayEvent is EventEmitter {
|
|
8
|
+
string private constant ABI = "event Relay(bytes32 indexed account, uint portal, uint resources, bytes32 key, bytes32 digest)";
|
|
9
|
+
|
|
10
|
+
/// @param account Account that owns the relayed context.
|
|
11
|
+
/// @param portal Destination portal identifier, often the destination host ID.
|
|
12
|
+
/// @param resources Chain-specific resources assigned to the relay.
|
|
13
|
+
/// @param key Relay correlation or recovery lookup key.
|
|
14
|
+
/// @param digest Digest of the relayed payload or canonical envelope.
|
|
15
|
+
event Relay(bytes32 indexed account, uint portal, uint resources, bytes32 key, bytes32 digest);
|
|
16
|
+
|
|
17
|
+
constructor() {
|
|
18
|
+
emit EventAbi(ABI);
|
|
19
|
+
}
|
|
20
|
+
}
|
package/execution/Execution.sol
CHANGED
|
@@ -24,6 +24,8 @@ struct Execution {
|
|
|
24
24
|
|
|
25
25
|
/// @title Executions
|
|
26
26
|
/// @notice Opening, decoding, output, transaction, and value helpers for executions.
|
|
27
|
+
/// @dev `output*` helpers consume memory inputs; `outputCopy*` helpers copy
|
|
28
|
+
/// calldata inputs directly to the output lane.
|
|
27
29
|
library Executions {
|
|
28
30
|
using Cursors for uint;
|
|
29
31
|
|
|
@@ -197,6 +199,21 @@ library Executions {
|
|
|
197
199
|
exec.decoders = cur.seekAbs(end);
|
|
198
200
|
}
|
|
199
201
|
|
|
202
|
+
/// @notice Validate and enter the payload of the next block in an execution decoder lane.
|
|
203
|
+
/// @dev The selected lane remains in its existing frame so callers can decode
|
|
204
|
+
/// child blocks in place. Callers should prove complete payload consumption
|
|
205
|
+
/// with `exec.expectAbs(end)` after decoding the children from the same lane.
|
|
206
|
+
/// @param exec Execution whose selected decoder cursor advances over the block header.
|
|
207
|
+
/// @param lane Execution decoder lane to select.
|
|
208
|
+
/// @param spec Expected parent block specification.
|
|
209
|
+
/// @return abs Absolute position of the first payload byte.
|
|
210
|
+
/// @return end Absolute position immediately after the payload.
|
|
211
|
+
function enter(Execution memory exec, uint8 lane, uint spec) internal pure returns (uint abs, uint end) {
|
|
212
|
+
uint cur = exec.decoders.select(lane);
|
|
213
|
+
(abs, end) = Blocks.expect(cur.absolute(), spec);
|
|
214
|
+
exec.decoders = cur.seekAbs(abs);
|
|
215
|
+
}
|
|
216
|
+
|
|
200
217
|
/// @notice Require the active execution decoder to be at absolute position `abs`.
|
|
201
218
|
/// @dev The most recent lane-aware decoder operation determines the active lane.
|
|
202
219
|
/// @param exec Execution whose active decoder position is validated.
|
|
@@ -218,6 +235,46 @@ library Executions {
|
|
|
218
235
|
// Fixed-width block decoding
|
|
219
236
|
// -------------------------------------------------------------------------
|
|
220
237
|
|
|
238
|
+
/// @dev Return the next raw calldata word from `lane` and advance by `size` bytes.
|
|
239
|
+
function next(Execution memory exec, uint8 lane, uint size) private pure returns (bytes32 value) {
|
|
240
|
+
uint abs;
|
|
241
|
+
(exec.decoders, abs) = exec.decoders.consume(lane, size);
|
|
242
|
+
value = Blocks.read32(abs);
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
/// @notice Return the next raw byte from a decoder lane and advance it by one byte.
|
|
246
|
+
function next1(Execution memory exec, uint8 lane) internal pure returns (bytes1 value) {
|
|
247
|
+
value = bytes1(next(exec, lane, 1));
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
/// @notice Return the next two raw bytes from a decoder lane and advance it by two bytes.
|
|
251
|
+
function next2(Execution memory exec, uint8 lane) internal pure returns (bytes2 value) {
|
|
252
|
+
value = bytes2(next(exec, lane, 2));
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
/// @notice Return the next four raw bytes from a decoder lane and advance it by four bytes.
|
|
256
|
+
function next4(Execution memory exec, uint8 lane) internal pure returns (bytes4 value) {
|
|
257
|
+
value = bytes4(next(exec, lane, 4));
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
/// @notice Return the next eight raw bytes from a decoder lane and advance it by eight bytes.
|
|
261
|
+
function next8(Execution memory exec, uint8 lane) internal pure returns (bytes8 value) {
|
|
262
|
+
value = bytes8(next(exec, lane, 8));
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
/// @notice Return the next sixteen raw bytes from a decoder lane and advance it by sixteen bytes.
|
|
266
|
+
function next16(Execution memory exec, uint8 lane) internal pure returns (bytes16 value) {
|
|
267
|
+
value = bytes16(next(exec, lane, 16));
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
/// @notice Return the next raw calldata word from a decoder lane and advance it.
|
|
271
|
+
/// @param exec Execution whose selected decoder cursor advances by one word.
|
|
272
|
+
/// @param lane Execution decoder lane to select.
|
|
273
|
+
/// @return value Raw word at the selected lane's previous position.
|
|
274
|
+
function next32(Execution memory exec, uint8 lane) internal pure returns (bytes32 value) {
|
|
275
|
+
value = next(exec, lane, Sizes.Word);
|
|
276
|
+
}
|
|
277
|
+
|
|
221
278
|
/// @notice Decode one fixed 32-byte payload from `lane`.
|
|
222
279
|
/// @param exec Execution whose decoder is advanced.
|
|
223
280
|
/// @param lane Decoder lane to consume.
|
|
@@ -1097,6 +1154,99 @@ library Executions {
|
|
|
1097
1154
|
Blocks.writeSchema(exec.output, i, spec, body, name);
|
|
1098
1155
|
}
|
|
1099
1156
|
|
|
1157
|
+
// -------------------------------------------------------------------------
|
|
1158
|
+
// Calldata output copy helpers
|
|
1159
|
+
// -------------------------------------------------------------------------
|
|
1160
|
+
|
|
1161
|
+
/// @notice Append a custom block to execution output by copying its payload from calldata.
|
|
1162
|
+
function outputCopyBlock(Execution memory exec, uint spec, bytes calldata data) internal pure {
|
|
1163
|
+
Specs.validate(spec, data.length);
|
|
1164
|
+
uint size = Sizes.Header + data.length;
|
|
1165
|
+
uint i = reserve(exec, size);
|
|
1166
|
+
Blocks.copy(exec.output, i, Specs.key(spec), data);
|
|
1167
|
+
}
|
|
1168
|
+
|
|
1169
|
+
/// @notice Append a LIST block to execution output by copying its payload from calldata.
|
|
1170
|
+
function outputCopyList(Execution memory exec, bytes calldata value) internal pure {
|
|
1171
|
+
uint size = Sizes.Header + value.length;
|
|
1172
|
+
uint i = reserve(exec, size);
|
|
1173
|
+
Blocks.copyList(exec.output, i, value);
|
|
1174
|
+
}
|
|
1175
|
+
|
|
1176
|
+
/// @notice Append an EVM block to execution output by copying its payload from calldata.
|
|
1177
|
+
function outputCopyEvm(Execution memory exec, bytes calldata value) internal pure {
|
|
1178
|
+
uint size = Sizes.Header + value.length;
|
|
1179
|
+
uint i = reserve(exec, size);
|
|
1180
|
+
Blocks.copyEvm(exec.output, i, value);
|
|
1181
|
+
}
|
|
1182
|
+
|
|
1183
|
+
/// @notice Append a BYTES block to execution output by copying its payload from calldata.
|
|
1184
|
+
function outputCopyBytes(Execution memory exec, bytes calldata value) internal pure {
|
|
1185
|
+
uint size = Sizes.Header + value.length;
|
|
1186
|
+
uint i = reserve(exec, size);
|
|
1187
|
+
Blocks.copyBytes(exec.output, i, value);
|
|
1188
|
+
}
|
|
1189
|
+
|
|
1190
|
+
/// @notice Append a STRING block to execution output by copying its payload from calldata.
|
|
1191
|
+
function outputCopyString(Execution memory exec, string calldata value) internal pure {
|
|
1192
|
+
uint size = Sizes.Header + bytes(value).length;
|
|
1193
|
+
uint i = reserve(exec, size);
|
|
1194
|
+
Blocks.copyString(exec.output, i, value);
|
|
1195
|
+
}
|
|
1196
|
+
|
|
1197
|
+
/// @notice Append a STEP block to execution output by copying its nested input from calldata.
|
|
1198
|
+
function outputCopyStep(Execution memory exec, uint cmd, uint resources, bytes calldata input) internal pure {
|
|
1199
|
+
uint size = Sizes.B64 + Sizes.Header + input.length;
|
|
1200
|
+
uint i = reserve(exec, size);
|
|
1201
|
+
Blocks.copyStep(exec.output, i, cmd, resources, input);
|
|
1202
|
+
}
|
|
1203
|
+
|
|
1204
|
+
/// @notice Append a CALL block to execution output by copying its nested payload from calldata.
|
|
1205
|
+
function outputCopyCall(Execution memory exec, uint target, uint resources, bytes calldata payload) internal pure {
|
|
1206
|
+
uint size = Sizes.B64 + Sizes.Header + payload.length;
|
|
1207
|
+
uint i = reserve(exec, size);
|
|
1208
|
+
Blocks.copyCall(exec.output, i, target, resources, payload);
|
|
1209
|
+
}
|
|
1210
|
+
|
|
1211
|
+
/// @notice Append a RELAY block to execution output by copying its nested input from calldata.
|
|
1212
|
+
function outputCopyRelay(Execution memory exec, uint portal, uint resources, bytes calldata input) internal pure {
|
|
1213
|
+
uint size = Sizes.B64 + Sizes.Header + input.length;
|
|
1214
|
+
uint i = reserve(exec, size);
|
|
1215
|
+
Blocks.copyRelay(exec.output, i, portal, resources, input);
|
|
1216
|
+
}
|
|
1217
|
+
|
|
1218
|
+
/// @notice Append a DISPATCH block to execution output by copying its nested payload from calldata.
|
|
1219
|
+
function outputCopyDispatch(Execution memory exec, uint portal, uint resources, bytes calldata payload) internal pure {
|
|
1220
|
+
uint size = Sizes.B64 + Sizes.Header + payload.length;
|
|
1221
|
+
uint i = reserve(exec, size);
|
|
1222
|
+
Blocks.copyDispatch(exec.output, i, portal, resources, payload);
|
|
1223
|
+
}
|
|
1224
|
+
|
|
1225
|
+
/// @notice Append a CONTEXT block to execution output by copying its nested streams from calldata.
|
|
1226
|
+
function outputCopyContext(
|
|
1227
|
+
Execution memory exec,
|
|
1228
|
+
bytes32 account,
|
|
1229
|
+
bytes calldata state,
|
|
1230
|
+
bytes calldata input
|
|
1231
|
+
) internal pure {
|
|
1232
|
+
uint size = Sizes.B32 + 2 * Sizes.Header + state.length + input.length;
|
|
1233
|
+
uint i = reserve(exec, size);
|
|
1234
|
+
Blocks.copyContext(exec.output, i, account, state, input);
|
|
1235
|
+
}
|
|
1236
|
+
|
|
1237
|
+
/// @notice Append a RECOVER block to execution output by copying its nested witness from calldata.
|
|
1238
|
+
function outputCopyRecover(
|
|
1239
|
+
Execution memory exec,
|
|
1240
|
+
uint handler,
|
|
1241
|
+
uint resources,
|
|
1242
|
+
bytes32 recoverykey,
|
|
1243
|
+
bytes calldata witness
|
|
1244
|
+
) internal pure {
|
|
1245
|
+
uint size = Sizes.B96 + Sizes.Header + witness.length;
|
|
1246
|
+
uint i = reserve(exec, size);
|
|
1247
|
+
Blocks.copyRecover(exec.output, i, handler, resources, recoverykey, witness);
|
|
1248
|
+
}
|
|
1249
|
+
|
|
1100
1250
|
// -------------------------------------------------------------------------
|
|
1101
1251
|
// Value and transaction writing
|
|
1102
1252
|
// -------------------------------------------------------------------------
|
package/guards/Base.sol
CHANGED
|
@@ -5,7 +5,6 @@ import {InputEndpointBase} from "../core/Endpoint.sol";
|
|
|
5
5
|
import {GuardianAccess} from "../core/Access.sol";
|
|
6
6
|
import {Specs} from "../codec/Specs.sol";
|
|
7
7
|
import {Nodes} from "../utils/Nodes.sol";
|
|
8
|
-
import {Selectors} from "../utils/Selectors.sol";
|
|
9
8
|
|
|
10
9
|
/// @title GuardBase
|
|
11
10
|
/// @notice Abstract base for guardian-only direct host actions.
|
|
@@ -27,7 +26,7 @@ abstract contract GuardBase is GuardianAccess, InputEndpointBase {
|
|
|
27
26
|
string memory name,
|
|
28
27
|
uint input
|
|
29
28
|
) internal returns (uint id, uint descriptor) {
|
|
30
|
-
id = Nodes.toGuard(
|
|
29
|
+
id = Nodes.toGuard(name, address(this));
|
|
31
30
|
descriptor = endpoint(id, name, Specs.Empty, input, Specs.Empty, 0, 0);
|
|
32
31
|
}
|
|
33
32
|
}
|
package/package.json
CHANGED
package/ports/AllowAssets.sol
CHANGED
|
@@ -8,10 +8,10 @@ import {Execution, Executions, Lanes} from "../execution/Execution.sol";
|
|
|
8
8
|
|
|
9
9
|
using Executions for Execution;
|
|
10
10
|
|
|
11
|
-
/// @title
|
|
11
|
+
/// @title AllowAssetsPort
|
|
12
12
|
/// @notice Port that permits a list of assets on behalf of a peer host.
|
|
13
13
|
/// Each ASSET block in the input calls `allowAsset`. Restricted to trusted peers.
|
|
14
|
-
abstract contract
|
|
14
|
+
abstract contract AllowAssetsPort is PortBase, AllowAssetsHook {
|
|
15
15
|
uint private immutable descriptor;
|
|
16
16
|
|
|
17
17
|
constructor() {
|
package/ports/Allowance.sol
CHANGED
|
@@ -8,11 +8,11 @@ import {Execution, Executions, Lanes} from "../execution/Execution.sol";
|
|
|
8
8
|
|
|
9
9
|
using Executions for Execution;
|
|
10
10
|
|
|
11
|
-
/// @title
|
|
11
|
+
/// @title AllowancePort
|
|
12
12
|
/// @notice Port that lets a trusted peer host input or refresh its own allowance.
|
|
13
13
|
/// Each AMOUNT block in the input is scoped to the peer host and passed to the
|
|
14
14
|
/// shared allowance hook as a host-scoped allowance. Restricted to trusted peers.
|
|
15
|
-
abstract contract
|
|
15
|
+
abstract contract AllowancePort is PortBase, AllowanceHook {
|
|
16
16
|
uint private immutable descriptor;
|
|
17
17
|
|
|
18
18
|
constructor() {
|
package/ports/Base.sol
CHANGED
|
@@ -6,7 +6,6 @@ import { NodeAccess } from "../core/Access.sol";
|
|
|
6
6
|
import { Specs } from "../codec/Specs.sol";
|
|
7
7
|
import { InputEndpointBase } from "../core/Endpoint.sol";
|
|
8
8
|
import { Nodes } from "../utils/Nodes.sol";
|
|
9
|
-
import { Selectors } from "../utils/Selectors.sol";
|
|
10
9
|
import { Descriptors } from "../codec/Descriptors.sol";
|
|
11
10
|
|
|
12
11
|
/// @title PortBase
|
|
@@ -56,7 +55,7 @@ abstract contract PortBase is NodeCalls, NodeAccess, InputEndpointBase {
|
|
|
56
55
|
string memory name,
|
|
57
56
|
uint descriptor
|
|
58
57
|
) internal returns (uint id, uint published) {
|
|
59
|
-
id = Nodes.toPort(
|
|
58
|
+
id = Nodes.toPort(name, address(this));
|
|
60
59
|
published = endpoint(id, name, descriptor);
|
|
61
60
|
}
|
|
62
61
|
}
|
package/ports/Credit.sol
CHANGED
|
@@ -8,10 +8,10 @@ import {Execution, Executions, Lanes} from "../execution/Execution.sol";
|
|
|
8
8
|
|
|
9
9
|
using Executions for Execution;
|
|
10
10
|
|
|
11
|
-
/// @title
|
|
11
|
+
/// @title CreditAccountPort
|
|
12
12
|
/// @notice Port that lets a trusted peer credit supplied accounts directly.
|
|
13
13
|
/// Each ACCOUNT_AMOUNT block calls `creditAccount` for its account.
|
|
14
|
-
abstract contract
|
|
14
|
+
abstract contract CreditAccountPort is PortBase, CreditAccountHook {
|
|
15
15
|
uint private immutable descriptor;
|
|
16
16
|
|
|
17
17
|
constructor() {
|
package/ports/Debit.sol
CHANGED
|
@@ -8,10 +8,10 @@ import {Execution, Executions, Lanes} from "../execution/Execution.sol";
|
|
|
8
8
|
|
|
9
9
|
using Executions for Execution;
|
|
10
10
|
|
|
11
|
-
/// @title
|
|
11
|
+
/// @title DebitAccountPort
|
|
12
12
|
/// @notice Port that lets a trusted peer debit supplied accounts directly.
|
|
13
13
|
/// Each ACCOUNT_AMOUNT block calls `debitAccount` for its account.
|
|
14
|
-
abstract contract
|
|
14
|
+
abstract contract DebitAccountPort is PortBase, DebitAccountHook {
|
|
15
15
|
uint private immutable descriptor;
|
|
16
16
|
|
|
17
17
|
constructor() {
|
package/ports/DenyAssets.sol
CHANGED
|
@@ -8,10 +8,10 @@ import {Execution, Executions, Lanes} from "../execution/Execution.sol";
|
|
|
8
8
|
|
|
9
9
|
using Executions for Execution;
|
|
10
10
|
|
|
11
|
-
/// @title
|
|
11
|
+
/// @title DenyAssetsPort
|
|
12
12
|
/// @notice Port that blocks a list of assets on behalf of a peer host.
|
|
13
13
|
/// Each ASSET block in the input calls `denyAsset`. Restricted to trusted peers.
|
|
14
|
-
abstract contract
|
|
14
|
+
abstract contract DenyAssetsPort is PortBase, DenyAssetsHook {
|
|
15
15
|
uint private immutable descriptor;
|
|
16
16
|
|
|
17
17
|
constructor() {
|
package/ports/Dispatch.sol
CHANGED
|
@@ -2,23 +2,34 @@
|
|
|
2
2
|
pragma solidity ^0.8.33;
|
|
3
3
|
|
|
4
4
|
import {PortBase} from "./Base.sol";
|
|
5
|
-
import {RelayPayableHook} from "../commands/Relay.sol";
|
|
6
5
|
import {Specs} from "../Codec.sol";
|
|
7
6
|
import {Execution, Executions, Lanes} from "../execution/Execution.sol";
|
|
8
7
|
|
|
9
8
|
using Executions for Execution;
|
|
10
9
|
|
|
11
|
-
/// @
|
|
12
|
-
|
|
13
|
-
|
|
10
|
+
/// @notice Hook implemented by hosts that forward funded dispatch payloads.
|
|
11
|
+
abstract contract DispatchPayableHook {
|
|
12
|
+
/// @notice Override to dispatch an encoded payload to `portal`.
|
|
13
|
+
/// @param portal Destination portal identifier, often the destination host ID.
|
|
14
|
+
/// @param resources Chain-specific destination resources. EVM adapters
|
|
15
|
+
/// may interpret this as packed execution gas and destination value.
|
|
16
|
+
/// @param payload Encoded payload ready for the transport layer.
|
|
17
|
+
/// @param funds Execution used for source value available for transport fees
|
|
18
|
+
/// and destination resource funding.
|
|
19
|
+
function dispatchTo(uint portal, uint resources, bytes memory payload, Execution memory funds) internal virtual;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/// @title DispatchPayablePort
|
|
23
|
+
/// @notice Port endpoint that forwards DISPATCH blocks to a host-defined dispatch hook.
|
|
24
|
+
abstract contract DispatchPayablePort is PortBase, DispatchPayableHook {
|
|
14
25
|
uint private immutable descriptor;
|
|
15
26
|
|
|
16
27
|
constructor() {
|
|
17
28
|
(, descriptor) = port("portDispatchPayable", Specs.Dispatch, Specs.Empty, true);
|
|
18
29
|
}
|
|
19
30
|
|
|
20
|
-
/// @notice Forward peer-supplied dispatches to the host-defined
|
|
21
|
-
/// @dev
|
|
31
|
+
/// @notice Forward peer-supplied dispatches to the host-defined dispatch hook.
|
|
32
|
+
/// @dev Dispatch hooks receive the shared top-level source value
|
|
22
33
|
/// budget. Any `msg.value` not spent by the hook remains on this host.
|
|
23
34
|
/// @param data DISPATCH block stream supplied by the trusted peer.
|
|
24
35
|
/// @return Empty response bytes.
|
|
@@ -27,7 +38,7 @@ abstract contract PortDispatchPayable is PortBase, RelayPayableHook {
|
|
|
27
38
|
|
|
28
39
|
while (exec.more()) {
|
|
29
40
|
(uint portal, uint resources, bytes calldata payload) = exec.unpackDispatch(Lanes.Input);
|
|
30
|
-
|
|
41
|
+
dispatchTo(portal, resources, payload, exec);
|
|
31
42
|
}
|
|
32
43
|
|
|
33
44
|
return "";
|
package/ports/Pipe.sol
CHANGED
|
@@ -9,10 +9,10 @@ import {Budget} from "../execution/Budget.sol";
|
|
|
9
9
|
|
|
10
10
|
using Executions for Execution;
|
|
11
11
|
|
|
12
|
-
/// @title
|
|
12
|
+
/// @title PipePayablePort
|
|
13
13
|
/// @notice Port that consumes CONTEXT blocks and executes each input as a step stream.
|
|
14
14
|
/// Each context's input bytes are passed to the shared pipeline.
|
|
15
|
-
abstract contract
|
|
15
|
+
abstract contract PipePayablePort is PortBase, Pipeline {
|
|
16
16
|
uint private immutable descriptor;
|
|
17
17
|
|
|
18
18
|
constructor() {
|