@rootzero/contracts 1.0.1 → 1.2.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.
Files changed (56) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/Endpoints.sol +2 -1
  3. package/Events.sol +1 -0
  4. package/blocks/Cursors.sol +176 -116
  5. package/blocks/Keys.sol +11 -7
  6. package/blocks/Schema.sol +11 -5
  7. package/blocks/Writers.sol +25 -9
  8. package/commands/Base.sol +10 -9
  9. package/commands/Burn.sol +3 -4
  10. package/commands/Credit.sol +3 -4
  11. package/commands/Debit.sol +3 -4
  12. package/commands/Deposit.sol +6 -8
  13. package/commands/Payout.sol +3 -4
  14. package/commands/Provision.sol +6 -8
  15. package/commands/Relay.sol +24 -32
  16. package/commands/Withdraw.sol +3 -4
  17. package/commands/admin/AllowAssets.sol +3 -4
  18. package/commands/admin/Allowance.sol +3 -3
  19. package/commands/admin/Appoint.sol +3 -4
  20. package/commands/admin/Authorize.sol +3 -4
  21. package/commands/admin/DenyAssets.sol +3 -4
  22. package/commands/admin/Destroy.sol +3 -4
  23. package/commands/admin/Dismiss.sol +3 -4
  24. package/commands/admin/Execute.sol +6 -7
  25. package/commands/admin/Init.sol +3 -4
  26. package/commands/admin/Label.sol +35 -0
  27. package/commands/admin/Unauthorize.sol +3 -4
  28. package/core/Calls.sol +3 -3
  29. package/core/Host.sol +7 -11
  30. package/core/Payable.sol +12 -10
  31. package/core/Pipeline.sol +4 -4
  32. package/docs/Schema.md +13 -6
  33. package/events/Admin.sol +2 -4
  34. package/events/Chain.sol +2 -3
  35. package/events/Command.sol +2 -4
  36. package/events/Guard.sol +2 -3
  37. package/events/Introduction.sol +2 -4
  38. package/events/Labeled.sol +18 -0
  39. package/events/Peer.sol +2 -11
  40. package/events/Query.sol +2 -3
  41. package/guards/Base.sol +7 -6
  42. package/guards/Revoke.sol +3 -4
  43. package/package.json +2 -1
  44. package/peer/AllowAssets.sol +3 -3
  45. package/peer/Allowance.sol +3 -3
  46. package/peer/BalancePull.sol +3 -3
  47. package/peer/Base.sol +7 -6
  48. package/peer/DenyAssets.sol +3 -3
  49. package/peer/Dispatch.sol +13 -23
  50. package/peer/Pipe.sol +7 -7
  51. package/peer/Settle.sol +3 -3
  52. package/queries/Assets.sol +3 -3
  53. package/queries/Balances.sol +3 -3
  54. package/queries/Base.sol +9 -8
  55. package/queries/Positions.sol +3 -4
  56. package/utils/Value.sol +5 -4
package/CHANGELOG.md ADDED
@@ -0,0 +1,24 @@
1
+ # Changelog
2
+
3
+ Until the protocol reaches integration-stable status, minor versions may include
4
+ breaking API changes. Breaking changes are called out explicitly.
5
+
6
+ ## 1.2.0
7
+
8
+ ### Breaking Changes
9
+
10
+ - Removed human-readable names from Command, Admin, Peer, Query, Guard, and Chain discovery events.
11
+ - Added the Labeled event and default labels for commands, admin commands, peers, queries, guards, and examples.
12
+ - Added LABEL and STRING block schemas, plus cursor helpers for decoding labels supplied by callers.
13
+ - Added the admin label command for publishing mutable namespaced labels.
14
+ - Removed version and namespace fields from host Introduction events and host constructor introductions.
15
+
16
+ ## 1.1.0
17
+
18
+ ### Breaking Changes
19
+
20
+ - Renamed local execution fields from `value` to `resources` in PIPE, CALL, and STEP schemas.
21
+ - Interprets EVM value as the low 128 bits of packed `resources`.
22
+ - Changed native value APIs and dispatch hooks to use `uint128` for actual EVM value.
23
+ - Replaced the relay-specific hook with shared `DispatchPayableHook`.
24
+ - `RelayPayable` now dispatches an encoded PIPE payload and settles leftover user command value.
package/Endpoints.sol CHANGED
@@ -16,7 +16,7 @@ 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 { RelayPayable, RelayPayableHook } from "./commands/Relay.sol";
19
+ import { RelayPayable, DispatchPayableHook } from "./commands/Relay.sol";
20
20
  import { Withdraw, WithdrawHook } from "./commands/Withdraw.sol";
21
21
 
22
22
  // Admin commands
@@ -29,6 +29,7 @@ import { DenyAssets, DenyAssetsHook } from "./commands/admin/DenyAssets.sol";
29
29
  import { Dismiss } from "./commands/admin/Dismiss.sol";
30
30
  import { ExecutePayable } from "./commands/admin/Execute.sol";
31
31
  import { Init, InitHook } from "./commands/admin/Init.sol";
32
+ import { Label } from "./commands/admin/Label.sol";
32
33
  import { Unauthorize } from "./commands/admin/Unauthorize.sol";
33
34
 
34
35
  // Peer endpoints
package/Events.sol CHANGED
@@ -16,6 +16,7 @@ import { EventEmitter } from "./events/Emitter.sol";
16
16
  import { GuardEvent } from "./events/Guard.sol";
17
17
  import { GuardianEvent } from "./events/Guardian.sol";
18
18
  import { IntroductionEvent } from "./events/Introduction.sol";
19
+ import { LabeledEvent } from "./events/Labeled.sol";
19
20
  import { LockedEvent } from "./events/Locked.sol";
20
21
  import { NodeEvent } from "./events/Node.sol";
21
22
  import { PeerEvent } from "./events/Peer.sol";
@@ -489,6 +489,13 @@ library Cursors {
489
489
  return createBlock(Keys.Bytes, data);
490
490
  }
491
491
 
492
+ /// @notice Encode a STRING block with a UTF-8 payload.
493
+ /// @param data String payload.
494
+ /// @return Encoded STRING block bytes.
495
+ function toStringBlock(string memory data) internal pure returns (bytes memory) {
496
+ return createBlock(Keys.String, bytes(data));
497
+ }
498
+
492
499
  /// @notice Encode a BOUNTY block.
493
500
  /// @param bounty Relayer reward amount.
494
501
  /// @param relayer Relayer account identifier.
@@ -518,20 +525,20 @@ library Cursors {
518
525
 
519
526
  /// @notice Encode a STEP block.
520
527
  /// @param target Command target identifier.
521
- /// @param value Native value forwarded with the step.
528
+ /// @param resources Chain resources assigned to the step.
522
529
  /// @param request Raw nested request payload.
523
530
  /// @return Encoded STEP block bytes.
524
- function toStepBlock(uint target, uint value, bytes memory request) internal pure returns (bytes memory) {
525
- return createBlock(Keys.Step, bytes.concat(bytes32(target), bytes32(value), toBytesBlock(request)));
531
+ function toStepBlock(uint target, uint resources, bytes memory request) internal pure returns (bytes memory) {
532
+ return createBlock(Keys.Step, bytes.concat(bytes32(target), bytes32(resources), toBytesBlock(request)));
526
533
  }
527
534
 
528
535
  /// @notice Encode a CALL block.
529
536
  /// @param target Target node identifier.
530
- /// @param value Native value forwarded with the call.
537
+ /// @param resources Chain resources assigned to the call.
531
538
  /// @param data Raw calldata payload for the target.
532
539
  /// @return Encoded CALL block bytes.
533
- function toCallBlock(uint target, uint value, bytes memory data) internal pure returns (bytes memory) {
534
- return createBlock(Keys.Call, bytes.concat(bytes32(target), bytes32(value), toBytesBlock(data)));
540
+ function toCallBlock(uint target, uint resources, bytes memory data) internal pure returns (bytes memory) {
541
+ return createBlock(Keys.Call, bytes.concat(bytes32(target), bytes32(resources), toBytesBlock(data)));
535
542
  }
536
543
 
537
544
  /// @notice Encode a CONTEXT block.
@@ -548,37 +555,37 @@ library Cursors {
548
555
  }
549
556
 
550
557
  /// @notice Encode a PIPE block.
551
- /// @param value Native value assigned to the pipe.
558
+ /// @param resources Chain resources assigned to the pipe.
552
559
  /// @param account Command account identifier.
553
560
  /// @param state Embedded state block stream.
554
561
  /// @param steps Embedded step block stream.
555
562
  /// @return Encoded PIPE block bytes.
556
563
  function toPipeBlock(
557
- uint value,
564
+ uint resources,
558
565
  bytes32 account,
559
566
  bytes memory state,
560
567
  bytes memory steps
561
568
  ) internal pure returns (bytes memory) {
562
- return createBlock(Keys.Pipe, bytes.concat(bytes32(value), toContextBlock(account, state, steps)));
563
- }
564
-
565
- /// @notice Encode a RELAY block.
566
- /// @param chain Destination chain node ID.
567
- /// @param resources Chain-adapter-specific resources for the destination pipe.
568
- /// @param steps Nested step block stream.
569
- /// @return Encoded RELAY block bytes.
570
- function toRelayBlock(uint chain, uint resources, bytes memory steps) internal pure returns (bytes memory) {
571
- return createBlock(Keys.Relay, bytes.concat(bytes32(chain), bytes32(resources), toBytesBlock(steps)));
572
- }
573
-
574
- /// @notice Encode a DISPATCH block.
575
- /// @param chain Destination chain node ID.
576
- /// @param resources Chain-adapter-specific resources for the destination dispatch.
577
- /// @param payload Encoded cross-chain payload.
578
- /// @return Encoded DISPATCH block bytes.
579
- function toDispatchBlock(uint chain, uint resources, bytes memory payload) internal pure returns (bytes memory) {
580
- return createBlock(Keys.Dispatch, bytes.concat(bytes32(chain), bytes32(resources), toBytesBlock(payload)));
581
- }
569
+ return createBlock(Keys.Pipe, bytes.concat(bytes32(resources), toContextBlock(account, state, steps)));
570
+ }
571
+
572
+ /// @notice Encode a RELAY block.
573
+ /// @param chain Destination chain node ID.
574
+ /// @param resources Chain-adapter-specific resources for the destination pipe.
575
+ /// @param steps Nested step block stream.
576
+ /// @return Encoded RELAY block bytes.
577
+ function toRelayBlock(uint chain, uint resources, bytes memory steps) internal pure returns (bytes memory) {
578
+ return createBlock(Keys.Relay, bytes.concat(bytes32(chain), bytes32(resources), toBytesBlock(steps)));
579
+ }
580
+
581
+ /// @notice Encode a DISPATCH block.
582
+ /// @param chain Destination chain node ID.
583
+ /// @param resources Chain-adapter-specific resources for the destination dispatch.
584
+ /// @param payload Encoded cross-chain payload.
585
+ /// @return Encoded DISPATCH block bytes.
586
+ function toDispatchBlock(uint chain, uint resources, bytes memory payload) internal pure returns (bytes memory) {
587
+ return createBlock(Keys.Dispatch, bytes.concat(bytes32(chain), bytes32(resources), toBytesBlock(payload)));
588
+ }
582
589
 
583
590
  // -------------------------------------------------------------------------
584
591
  // Raw calldata loaders
@@ -590,31 +597,43 @@ library Cursors {
590
597
  /// @param cur Cursor whose current position is advanced by `n` bytes.
591
598
  /// @param n Number of bytes to advance.
592
599
  /// @return value Loaded word.
593
- function read(Cur memory cur, uint n) internal pure returns (bytes32 value) {
594
- uint abs = cur.offset + cur.i;
595
- assembly ("memory-safe") {
596
- value := calldataload(abs)
597
- }
598
- cur.i += n;
599
- }
600
-
601
- /// @notice Read the next 4 bytes from the cursor and advance by 4 bytes.
602
- /// @dev Performs no bounds, key, length, or cursor checks.
603
- /// @param cur Cursor whose current position is advanced by 4 bytes.
604
- /// @return value Loaded bytes4 value.
605
- function read4(Cur memory cur) internal pure returns (bytes4 value) {
606
- uint abs = cur.offset + cur.i;
607
- assembly ("memory-safe") {
608
- value := calldataload(abs)
609
- }
610
- cur.i += 4;
611
- }
612
-
613
- /// @notice Read the next 16 bytes from the cursor and advance by 16 bytes.
614
- /// @dev Performs no bounds, key, length, or cursor checks.
615
- /// @param cur Cursor whose current position is advanced by 16 bytes.
616
- /// @return value Loaded bytes16 value.
617
- function read16(Cur memory cur) internal pure returns (bytes16 value) {
600
+ function read(Cur memory cur, uint n) internal pure returns (bytes32 value) {
601
+ uint abs = cur.offset + cur.i;
602
+ assembly ("memory-safe") {
603
+ value := calldataload(abs)
604
+ }
605
+ cur.i += n;
606
+ }
607
+
608
+ /// @notice Read the next 4 bytes from the cursor and advance by 4 bytes.
609
+ /// @dev Performs no bounds, key, length, or cursor checks.
610
+ /// @param cur Cursor whose current position is advanced by 4 bytes.
611
+ /// @return value Loaded bytes4 value.
612
+ function read4(Cur memory cur) internal pure returns (bytes4 value) {
613
+ uint abs = cur.offset + cur.i;
614
+ assembly ("memory-safe") {
615
+ value := calldataload(abs)
616
+ }
617
+ cur.i += 4;
618
+ }
619
+
620
+ /// @notice Read the next 8 bytes from the cursor and advance by 8 bytes.
621
+ /// @dev Performs no bounds, key, length, or cursor checks.
622
+ /// @param cur Cursor whose current position is advanced by 8 bytes.
623
+ /// @return value Loaded bytes8 value.
624
+ function read8(Cur memory cur) internal pure returns (bytes8 value) {
625
+ uint abs = cur.offset + cur.i;
626
+ assembly ("memory-safe") {
627
+ value := calldataload(abs)
628
+ }
629
+ cur.i += 8;
630
+ }
631
+
632
+ /// @notice Read the next 16 bytes from the cursor and advance by 16 bytes.
633
+ /// @dev Performs no bounds, key, length, or cursor checks.
634
+ /// @param cur Cursor whose current position is advanced by 16 bytes.
635
+ /// @return value Loaded bytes16 value.
636
+ function read16(Cur memory cur) internal pure returns (bytes16 value) {
618
637
  uint abs = cur.offset + cur.i;
619
638
  assembly ("memory-safe") {
620
639
  value := calldataload(abs)
@@ -626,30 +645,30 @@ library Cursors {
626
645
  /// @dev Performs no bounds, key, length, or cursor checks.
627
646
  /// @param cur Cursor whose current position is advanced by 32 bytes.
628
647
  /// @return value Loaded word.
629
- function read32(Cur memory cur) internal pure returns (bytes32 value) {
630
- uint abs = cur.offset + cur.i;
631
- assembly ("memory-safe") {
632
- value := calldataload(abs)
633
- }
634
- cur.i += 32;
635
- }
636
-
637
- /// @notice Read the next uint from the cursor and advance by one word.
638
- /// @dev Performs no bounds, key, length, or cursor checks.
639
- /// @param cur Cursor whose current position is advanced by 32 bytes.
640
- /// @return value Loaded uint value.
641
- function readUint(Cur memory cur) internal pure returns (uint value) {
642
- uint abs = cur.offset + cur.i;
643
- assembly ("memory-safe") {
644
- value := calldataload(abs)
645
- }
646
- cur.i += 32;
647
- }
648
-
649
- /// @notice Read the next two 32-byte words from the cursor and advance by 64 bytes.
650
- /// @dev Performs no bounds, key, length, or cursor checks.
651
- /// @param cur Cursor whose current position is advanced by 64 bytes.
652
- /// @return a First loaded word.
648
+ function read32(Cur memory cur) internal pure returns (bytes32 value) {
649
+ uint abs = cur.offset + cur.i;
650
+ assembly ("memory-safe") {
651
+ value := calldataload(abs)
652
+ }
653
+ cur.i += 32;
654
+ }
655
+
656
+ /// @notice Read the next uint from the cursor and advance by one word.
657
+ /// @dev Performs no bounds, key, length, or cursor checks.
658
+ /// @param cur Cursor whose current position is advanced by 32 bytes.
659
+ /// @return value Loaded uint value.
660
+ function readUint(Cur memory cur) internal pure returns (uint value) {
661
+ uint abs = cur.offset + cur.i;
662
+ assembly ("memory-safe") {
663
+ value := calldataload(abs)
664
+ }
665
+ cur.i += 32;
666
+ }
667
+
668
+ /// @notice Read the next two 32-byte words from the cursor and advance by 64 bytes.
669
+ /// @dev Performs no bounds, key, length, or cursor checks.
670
+ /// @param cur Cursor whose current position is advanced by 64 bytes.
671
+ /// @return a First loaded word.
653
672
  /// @return b Second loaded word.
654
673
  function read64(Cur memory cur) internal pure returns (bytes32 a, bytes32 b) {
655
674
  uint abs = cur.offset + cur.i;
@@ -708,6 +727,26 @@ library Cursors {
708
727
  return unpackRaw(cur, Keys.Bytes);
709
728
  }
710
729
 
730
+ /// @notice Consume a reserved STRING block and return its UTF-8 payload.
731
+ /// @param cur Cursor; advanced past the STRING block.
732
+ /// @return data Decoded STRING payload.
733
+ function unpackString(Cur memory cur) internal pure returns (string memory data) {
734
+ return string(unpackRaw(cur, Keys.String));
735
+ }
736
+
737
+ /// @notice Consume a LABEL block and return its fields.
738
+ /// @param cur Cursor; advanced past the LABEL block.
739
+ /// @return id Node ID being labelled.
740
+ /// @return namespace Label namespace.
741
+ /// @return name Label value.
742
+ function unpackLabel(Cur memory cur) internal pure returns (uint id, bytes32 namespace, string memory name) {
743
+ uint end = cur.enter(Keys.Label, 64 + Sizes.Header, 0);
744
+ id = cur.readUint();
745
+ namespace = cur.read32();
746
+ name = cur.unpackString();
747
+ cur.exit(end);
748
+ }
749
+
711
750
  /// @notice Consume a dynamic block with a single bytes32 payload.
712
751
  /// @param cur Cursor; advanced past the block.
713
752
  /// @param key Expected dynamic block key.
@@ -1079,12 +1118,12 @@ library Cursors {
1079
1118
  /// The `req` slice is the raw payload of the block's required BYTES child.
1080
1119
  /// @param cur Cursor; advanced past the block.
1081
1120
  /// @return target Destination node ID for the sub-command.
1082
- /// @return value Native value to forward with the call.
1121
+ /// @return resources Chain resources assigned to the step.
1083
1122
  /// @return req Embedded request bytes for the sub-command.
1084
- function unpackStep(Cur memory cur) internal pure returns (uint target, uint value, bytes calldata req) {
1123
+ function unpackStep(Cur memory cur) internal pure returns (uint target, uint resources, bytes calldata req) {
1085
1124
  uint end = cur.enter(Keys.Step, 64 + Sizes.Header, 0);
1086
1125
  target = uint(cur.read32());
1087
- value = uint(cur.read32());
1126
+ resources = uint(cur.read32());
1088
1127
  req = cur.unpackBytes();
1089
1128
  cur.exit(end);
1090
1129
  }
@@ -1093,12 +1132,12 @@ library Cursors {
1093
1132
  /// The `data` slice is the raw payload of the block's required BYTES child.
1094
1133
  /// @param cur Cursor; advanced past the block.
1095
1134
  /// @return target Target node ID to call.
1096
- /// @return value Native value to forward with the call.
1135
+ /// @return resources Chain resources assigned to the call.
1097
1136
  /// @return data Raw calldata payload for the target.
1098
- function unpackCall(Cur memory cur) internal pure returns (uint target, uint value, bytes calldata data) {
1137
+ function unpackCall(Cur memory cur) internal pure returns (uint target, uint resources, bytes calldata data) {
1099
1138
  uint end = cur.enter(Keys.Call, 64 + Sizes.Header, 0);
1100
1139
  target = uint(cur.read32());
1101
- value = uint(cur.read32());
1140
+ resources = uint(cur.read32());
1102
1141
  data = cur.unpackBytes();
1103
1142
  cur.exit(end);
1104
1143
  }
@@ -1119,50 +1158,50 @@ library Cursors {
1119
1158
  cur.exit(end);
1120
1159
  }
1121
1160
 
1122
- /// @notice Consume a PIPE block and return its value and context fields.
1161
+ /// @notice Consume a PIPE block and return its resources and context fields.
1123
1162
  /// @param cur Cursor; advanced past the block.
1124
- /// @return value Native value assigned to the pipe.
1163
+ /// @return resources Chain resources assigned to the pipe.
1125
1164
  /// @return account Command account identifier.
1126
1165
  /// @return state Embedded state block stream.
1127
1166
  /// @return steps Embedded step block stream.
1128
1167
  function unpackPipe(
1129
1168
  Cur memory cur
1130
- ) internal pure returns (uint value, bytes32 account, bytes calldata state, bytes calldata steps) {
1169
+ ) internal pure returns (uint resources, bytes32 account, bytes calldata state, bytes calldata steps) {
1131
1170
  uint end = cur.enter(Keys.Pipe, 32 + Sizes.Header + 32 + 2 * Sizes.Header, 0);
1132
- value = uint(cur.read32());
1171
+ resources = uint(cur.read32());
1133
1172
  (account, state, steps) = cur.unpackContext();
1134
1173
  cur.exit(end);
1135
1174
  }
1136
1175
 
1137
- /// @notice Consume a RELAY block and return its destination chain, resources, and step stream.
1138
- /// @param cur Cursor; advanced past the block.
1139
- /// @return chain Destination chain node ID.
1140
- /// @return resources Chain-adapter-specific resources for the destination pipe.
1141
- /// @return steps Embedded step block stream.
1142
- function unpackRelay(
1143
- Cur memory cur
1144
- ) internal pure returns (uint chain, uint resources, bytes calldata steps) {
1145
- uint end = cur.enter(Keys.Relay, 64 + Sizes.Header, 0);
1146
- chain = cur.readUint();
1147
- resources = cur.readUint();
1148
- steps = cur.unpackBytes();
1149
- cur.exit(end);
1150
- }
1151
-
1152
- /// @notice Consume a DISPATCH block and return its destination chain, resources, and payload.
1153
- /// @param cur Cursor; advanced past the block.
1154
- /// @return chain Destination chain node ID.
1155
- /// @return resources Chain-adapter-specific resources for the destination dispatch.
1156
- /// @return payload Encoded cross-chain payload.
1157
- function unpackDispatch(
1158
- Cur memory cur
1159
- ) internal pure returns (uint chain, uint resources, bytes calldata payload) {
1160
- uint end = cur.enter(Keys.Dispatch, 64 + Sizes.Header, 0);
1161
- chain = cur.readUint();
1162
- resources = cur.readUint();
1163
- payload = cur.unpackBytes();
1164
- cur.exit(end);
1165
- }
1176
+ /// @notice Consume a RELAY block and return its destination chain, resources, and step stream.
1177
+ /// @param cur Cursor; advanced past the block.
1178
+ /// @return chain Destination chain node ID.
1179
+ /// @return resources Chain-adapter-specific resources for the destination pipe.
1180
+ /// @return steps Embedded step block stream.
1181
+ function unpackRelay(
1182
+ Cur memory cur
1183
+ ) internal pure returns (uint chain, uint resources, bytes calldata steps) {
1184
+ uint end = cur.enter(Keys.Relay, 64 + Sizes.Header, 0);
1185
+ chain = cur.readUint();
1186
+ resources = cur.readUint();
1187
+ steps = cur.unpackBytes();
1188
+ cur.exit(end);
1189
+ }
1190
+
1191
+ /// @notice Consume a DISPATCH block and return its destination chain, resources, and payload.
1192
+ /// @param cur Cursor; advanced past the block.
1193
+ /// @return chain Destination chain node ID.
1194
+ /// @return resources Chain-adapter-specific resources for the destination dispatch.
1195
+ /// @return payload Encoded cross-chain payload.
1196
+ function unpackDispatch(
1197
+ Cur memory cur
1198
+ ) internal pure returns (uint chain, uint resources, bytes calldata payload) {
1199
+ uint end = cur.enter(Keys.Dispatch, 64 + Sizes.Header, 0);
1200
+ chain = cur.readUint();
1201
+ resources = cur.readUint();
1202
+ payload = cur.unpackBytes();
1203
+ cur.exit(end);
1204
+ }
1166
1205
 
1167
1206
  // Type-specific validators
1168
1207
 
@@ -1385,6 +1424,27 @@ library Cursors {
1385
1424
  if (uint(bytes32(msg.data[abs + 128:abs + 160])) < amount) revert UnexpectedValue();
1386
1425
  }
1387
1426
 
1427
+ // -------------------------------------------------------------------------
1428
+ // Transform helpers
1429
+ // -------------------------------------------------------------------------
1430
+
1431
+ /// @notice Consume a RELAY block and encode its destination pipe payload.
1432
+ /// @param cur Cursor; advanced past the RELAY block.
1433
+ /// @param account Account identifier to embed in the destination pipe context.
1434
+ /// @param state State block stream to embed in the destination pipe context.
1435
+ /// @return chain Destination chain node ID.
1436
+ /// @return resources Chain resources assigned to the destination pipe.
1437
+ /// @return pipe Encoded PIPE block containing `account`, `state`, and relay steps.
1438
+ function relayToPipe(
1439
+ Cur memory cur,
1440
+ bytes32 account,
1441
+ bytes calldata state
1442
+ ) internal pure returns (uint chain, uint resources, bytes memory pipe) {
1443
+ bytes calldata steps;
1444
+ (chain, resources, steps) = cur.unpackRelay();
1445
+ pipe = toPipeBlock(resources, account, bytes(state), bytes(steps));
1446
+ }
1447
+
1388
1448
  // -------------------------------------------------------------------------
1389
1449
  // Search helpers
1390
1450
  // -------------------------------------------------------------------------
package/blocks/Keys.sol CHANGED
@@ -33,21 +33,23 @@ library Keys {
33
33
  bytes4 constant Evm = bytes4(keccak256("#evm"));
34
34
  /// @dev Reserved raw bytes child block.
35
35
  bytes4 constant Bytes = bytes4(keccak256("#bytes"));
36
+ /// @dev Reserved UTF-8 string child block.
37
+ bytes4 constant String = bytes4(keccak256("#string"));
36
38
  /// @dev Account identifier - (bytes32 account)
37
39
  bytes4 constant Account = bytes4(keccak256("#account"));
38
40
  /// @dev Transfer record passed through the pipeline - (bytes32 from, bytes32 to, bytes32 asset, bytes32 meta, uint amount)
39
41
  bytes4 constant Transaction = bytes4(keccak256("#transaction"));
40
- /// @dev Sub-command invocation - (uint target, uint value, #bytes as request)
42
+ /// @dev Sub-command invocation - (uint target, uint resources, #bytes as request)
41
43
  bytes4 constant Step = bytes4(keccak256("#step"));
42
- /// @dev Cross-chain pipe relay - (uint chain, uint resources, #bytes as steps)
43
- bytes4 constant Relay = bytes4(keccak256("#relay"));
44
- /// @dev Cross-chain encoded payload dispatch - (uint chain, uint resources, #bytes as payload)
45
- bytes4 constant Dispatch = bytes4(keccak256("#dispatch"));
46
- /// @dev Raw external call - (uint target, uint value, #bytes as payload)
44
+ /// @dev Cross-chain pipe relay - (uint chain, uint resources, #bytes as steps)
45
+ bytes4 constant Relay = bytes4(keccak256("#relay"));
46
+ /// @dev Cross-chain encoded payload dispatch - (uint chain, uint resources, #bytes as payload)
47
+ bytes4 constant Dispatch = bytes4(keccak256("#dispatch"));
48
+ /// @dev Raw external call - (uint target, uint resources, #bytes as payload)
47
49
  bytes4 constant Call = bytes4(keccak256("#call"));
48
50
  /// @dev Command context transport - (bytes32 account, #bytes as state, #bytes as request)
49
51
  bytes4 constant Context = bytes4(keccak256("#context"));
50
- /// @dev Pipeline invocation - (uint value, #context)
52
+ /// @dev Pipeline invocation - (uint resources, #context)
51
53
  bytes4 constant Pipe = bytes4(keccak256("#pipe"));
52
54
  /// @dev Authentication proof - (uint cid, uint deadline, #bytes as proof); must appear last in its segment
53
55
  bytes4 constant Auth = bytes4(keccak256("#auth"));
@@ -57,6 +59,8 @@ library Keys {
57
59
  bytes4 constant Node = bytes4(keccak256("#node"));
58
60
  /// @dev Relayer bounty - (uint amount, bytes32 relayer)
59
61
  bytes4 constant Bounty = bytes4(keccak256("#bounty"));
62
+ /// @dev Mutable node label - (uint id, bytes32 namespace, #string as name)
63
+ bytes4 constant Label = bytes4(keccak256("#label"));
60
64
 
61
65
  /// @dev Structural status form - (uint code)
62
66
  bytes4 constant Status = bytes4(keccak256("#status"));
package/blocks/Schema.sol CHANGED
@@ -18,10 +18,14 @@ pragma solidity ^0.8.33;
18
18
  // - run items may repeat at top level for batching
19
19
  // - `maybe #x { ... }` marks an optional block item
20
20
  // - `many #x { ... }` emits one generic list block containing repeated `#x` items
21
+ // - `resources` fields are chain-specific resource words; one chain type may
22
+ // pack them differently from another, but a given chain type must use one
23
+ // stable format everywhere. EVM resources use the low 128 bits as native value.
21
24
  // - fixed fields are packed in declaration order
22
25
  // - blocks have fixed fields followed by a dynamic child-block tail
23
26
  // - child block tails are embedded directly, without an extra stream wrapper
24
27
  // - `#bytes` is a reserved child block that stores raw bytes and has no body
28
+ // - `#string` is a reserved child block that stores UTF-8 string bytes and has no body
25
29
  // - generic `#data` uses the stable key derived from `#data`
26
30
  // - generic lists use the stable key derived from `#list`
27
31
  // - keys are derived from block names, e.g. bytes4(keccak256("#amount"))
@@ -62,15 +66,17 @@ library Schemas {
62
66
  string constant Allowance = "#allowance { uint host, bytes32 asset, bytes32 meta, uint amount }";
63
67
  string constant Transaction = "#transaction { bytes32 from, bytes32 to, bytes32 asset, bytes32 meta, uint amount }";
64
68
  string constant Context = "#context { bytes32 account, #bytes as state, #bytes as request }";
65
- string constant Pipe = "#pipe { uint value, #context { bytes32 account, #bytes as state, #bytes as steps } }";
66
- string constant Call = "#call { uint target, uint value, #bytes as payload }";
67
- string constant Step = "#step { uint target, uint value, #bytes as request }";
68
- string constant Relay = "#relay { uint chain, uint resources, #bytes as steps }";
69
- string constant Dispatch = "#dispatch { uint chain, uint resources, #bytes as payload }";
69
+ string constant Pipe = "#pipe { uint resources, #context { bytes32 account, #bytes as state, #bytes as steps } }";
70
+ string constant Call = "#call { uint target, uint resources, #bytes as payload }";
71
+ string constant Step = "#step { uint target, uint resources, #bytes as request }";
72
+ string constant Relay = "#relay { uint chain, uint resources, #bytes as steps }";
73
+ string constant Dispatch = "#dispatch { uint chain, uint resources, #bytes as payload }";
70
74
  string constant Bounty = "#bounty { uint amount, bytes32 relayer }";
71
75
  string constant Fee = "#fee { uint amount }";
72
76
  string constant Auth = "#auth { uint cid, uint deadline, #bytes as proof }";
77
+ string constant Label = "#label { uint id, bytes32 namespace, #string as name }";
73
78
  string constant Bytes = "#bytes";
79
+ string constant String = "#string";
74
80
  string constant Data = "#data";
75
81
  string constant List = "#list";
76
82
  string constant Evm = "#evm";
@@ -24,6 +24,7 @@ struct Writer {
24
24
  library Hints {
25
25
  uint constant Any = 128;
26
26
  uint constant Bytes = 128;
27
+ uint constant String = 128;
27
28
  uint constant Step = 256;
28
29
  uint constant Call = 256;
29
30
  uint constant Context = 512;
@@ -116,6 +117,14 @@ library Writers {
116
117
  return allocFromHint(count, Hints.Bytes);
117
118
  }
118
119
 
120
+ /// @notice Allocate a writer for `count` STRING blocks using a per-block capacity hint.
121
+ /// @dev The backing buffer expands automatically if encoded string blocks exceed the initial hint.
122
+ /// @param count Number of string blocks to allocate space for.
123
+ /// @return writer Allocated growable writer.
124
+ function allocStrings(uint count) internal pure returns (Writer memory writer) {
125
+ return allocFromHint(count, Hints.String);
126
+ }
127
+
119
128
  /// @notice Allocate a writer sized for exactly `count` 32-byte-payload blocks.
120
129
  /// @param count Number of blocks to allocate space for.
121
130
  /// @return writer Allocated writer.
@@ -862,22 +871,29 @@ library Writers {
862
871
  appendBlock(writer, Keys.Bytes, data);
863
872
  }
864
873
 
874
+ /// @notice Append a STRING block.
875
+ /// @param writer Destination writer; `i` is advanced by the encoded STRING block length.
876
+ /// @param data String payload.
877
+ function appendString(Writer memory writer, string memory data) internal pure {
878
+ appendBlock(writer, Keys.String, bytes(data));
879
+ }
880
+
865
881
  /// @notice Append a STEP block with a nested request BYTES payload.
866
882
  /// @param writer Destination writer; `i` is advanced by the encoded STEP block length.
867
883
  /// @param target Command target identifier.
868
- /// @param value Native value forwarded with the step.
884
+ /// @param resources Chain resources assigned to the step.
869
885
  /// @param request Raw nested request payload.
870
- function appendStep(Writer memory writer, uint target, uint value, bytes memory request) internal pure {
871
- appendBlock64Bytes(writer, Keys.Step, bytes32(target), bytes32(value), request);
886
+ function appendStep(Writer memory writer, uint target, uint resources, bytes memory request) internal pure {
887
+ appendBlock64Bytes(writer, Keys.Step, bytes32(target), bytes32(resources), request);
872
888
  }
873
889
 
874
890
  /// @notice Append a CALL block with a nested payload BYTES block.
875
891
  /// @param writer Destination writer; `i` is advanced by the encoded CALL block length.
876
892
  /// @param target Call target identifier.
877
- /// @param value Native value forwarded with the call.
893
+ /// @param resources Chain resources assigned to the call.
878
894
  /// @param data Raw nested call payload.
879
- function appendCall(Writer memory writer, uint target, uint value, bytes memory data) internal pure {
880
- appendBlock64Bytes(writer, Keys.Call, bytes32(target), bytes32(value), data);
895
+ function appendCall(Writer memory writer, uint target, uint resources, bytes memory data) internal pure {
896
+ appendBlock64Bytes(writer, Keys.Call, bytes32(target), bytes32(resources), data);
881
897
  }
882
898
 
883
899
  /// @notice Append a CONTEXT block with nested state/request BYTES payloads.
@@ -891,13 +907,13 @@ library Writers {
891
907
 
892
908
  /// @notice Append a PIPE block with a nested CONTEXT block.
893
909
  /// @param writer Destination writer; `i` is advanced by the encoded PIPE block length.
894
- /// @param value Native value assigned to the pipe.
910
+ /// @param resources Chain resources assigned to the pipe.
895
911
  /// @param account Command account identifier.
896
912
  /// @param state Raw nested state payload.
897
913
  /// @param steps Raw nested step payload.
898
914
  function appendPipe(
899
915
  Writer memory writer,
900
- uint value,
916
+ uint resources,
901
917
  bytes32 account,
902
918
  bytes memory state,
903
919
  bytes memory steps
@@ -909,7 +925,7 @@ library Writers {
909
925
 
910
926
  uint p = writeHeader(writer.dst, i, Keys.Pipe, uint32(max32(len)));
911
927
  assembly ("memory-safe") {
912
- mstore(add(p, 0x08), value)
928
+ mstore(add(p, 0x08), resources)
913
929
  }
914
930
 
915
931
  writeBlock32BytesBytes(writer.dst, i + Sizes.Header + 32, Keys.Context, account, state, steps);