@rootzero/contracts 0.9.3 → 0.9.4

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.
@@ -12,11 +12,23 @@ struct Writer {
12
12
  uint i;
13
13
  /// @dev Logical buffer capacity in bytes; writers should not advance past this limit.
14
14
  uint end;
15
+ /// @dev Whether append helpers may expand the backing buffer when more capacity is needed.
16
+ bool growable;
15
17
  /// @dev Destination buffer. Physical capacity may be padded up to a full 32-byte word;
16
18
  /// final length is set to `i` by `finish`.
17
19
  bytes dst;
18
20
  }
19
21
 
22
+ /// @title Hints
23
+ /// @notice Initial per-block capacity estimates for growable writers.
24
+ library Hints {
25
+ uint constant Any = 128;
26
+ uint constant Bytes = 128;
27
+ uint constant Step = 256;
28
+ uint constant Call = 256;
29
+ uint constant Context = 512;
30
+ }
31
+
20
32
  /// @title Writers
21
33
  /// @notice Response block stream builder for the rootzero protocol.
22
34
  /// Allocates a fixed-size memory buffer up front and writes binary-encoded
@@ -47,7 +59,15 @@ library Writers {
47
59
  // Extra 32 bytes ensure mstore in write/append32 never reaches past allocated memory,
48
60
  // even when a sub-word packed write starts within the last 31 bytes of the logical region.
49
61
  uint padded = ((len + 31) & ~uint(31)) + 32;
50
- writer = Writer({i: 0, end: len, dst: new bytes(padded)});
62
+ writer = Writer({i: 0, end: len, growable: false, dst: new bytes(padded)});
63
+ }
64
+
65
+ /// @notice Allocate a growable writer with an initial logical byte capacity.
66
+ /// @param hint Initial logical byte capacity to allocate.
67
+ /// @return writer Freshly allocated growable writer positioned at index 0.
68
+ function dynamic(uint hint) internal pure returns (Writer memory writer) {
69
+ writer = alloc(hint);
70
+ writer.growable = true;
51
71
  }
52
72
 
53
73
  /// @notice Core allocation routine used by all counted `alloc*` helpers.
@@ -60,6 +80,16 @@ library Writers {
60
80
  writer = alloc(count * blockLen);
61
81
  }
62
82
 
83
+ /// @notice Core allocation routine used by counted growable `alloc*` helpers.
84
+ /// Computes `count * hint` and allocates an expandable writer with that initial capacity.
85
+ /// @param count Number of output blocks.
86
+ /// @param hint Initial logical byte capacity per output block.
87
+ /// @return writer Allocated growable writer.
88
+ function allocFromHint(uint count, uint hint) internal pure returns (Writer memory writer) {
89
+ if (count == 0) revert EmptyRequest();
90
+ writer = dynamic(count * hint);
91
+ }
92
+
63
93
  /// @notice Allocate a writer sized for exactly `count` dynamic blocks with a shared payload length.
64
94
  /// Each block reserves `Sizes.Header + payloadLen` bytes.
65
95
  /// @param count Number of blocks to allocate space for.
@@ -69,6 +99,22 @@ library Writers {
69
99
  return allocFromCount(count, Sizes.Header + payloadLen);
70
100
  }
71
101
 
102
+ /// @notice Allocate a writer for `count` variable-sized blocks using a per-block capacity hint.
103
+ /// @dev The backing buffer expands automatically if encoded blocks exceed the initial hint.
104
+ /// @param count Number of blocks to allocate space for.
105
+ /// @return writer Allocated growable writer.
106
+ function allocAny(uint count) internal pure returns (Writer memory writer) {
107
+ return allocFromHint(count, Hints.Any);
108
+ }
109
+
110
+ /// @notice Allocate a writer for `count` BYTES blocks using a per-block capacity hint.
111
+ /// @dev The backing buffer expands automatically if encoded bytes blocks exceed the initial hint.
112
+ /// @param count Number of bytes blocks to allocate space for.
113
+ /// @return writer Allocated growable writer.
114
+ function allocBytes(uint count) internal pure returns (Writer memory writer) {
115
+ return allocFromHint(count, Hints.Bytes);
116
+ }
117
+
72
118
  /// @notice Allocate a writer sized for exactly `count` 32-byte-payload blocks.
73
119
  /// @param count Number of blocks to allocate space for.
74
120
  /// @return writer Allocated writer.
@@ -108,7 +154,7 @@ library Writers {
108
154
  /// @param count Number of blocks to allocate space for.
109
155
  /// @return writer Allocated writer.
110
156
  function allocStatuses(uint count) internal pure returns (Writer memory writer) {
111
- return alloc32s(count);
157
+ return allocFromCount(count, Sizes.Status);
112
158
  }
113
159
 
114
160
  /// @notice Allocate a writer sized for exactly `count` ASSET blocks.
@@ -153,6 +199,30 @@ library Writers {
153
199
  return alloc160s(count);
154
200
  }
155
201
 
202
+ /// @notice Allocate a writer for `count` STEP blocks using a per-block capacity hint.
203
+ /// @dev The backing buffer expands automatically if encoded steps exceed the initial hint.
204
+ /// @param count Number of step blocks to allocate space for.
205
+ /// @return writer Allocated growable writer.
206
+ function allocSteps(uint count) internal pure returns (Writer memory writer) {
207
+ return allocFromHint(count, Hints.Step);
208
+ }
209
+
210
+ /// @notice Allocate a writer for `count` CALL blocks using a per-block capacity hint.
211
+ /// @dev The backing buffer expands automatically if encoded calls exceed the initial hint.
212
+ /// @param count Number of call blocks to allocate space for.
213
+ /// @return writer Allocated growable writer.
214
+ function allocCalls(uint count) internal pure returns (Writer memory writer) {
215
+ return allocFromHint(count, Hints.Call);
216
+ }
217
+
218
+ /// @notice Allocate a writer for `count` CONTEXT blocks using a per-block capacity hint.
219
+ /// @dev The backing buffer expands automatically if encoded contexts exceed the initial hint.
220
+ /// @param count Number of context blocks to allocate space for.
221
+ /// @return writer Allocated growable writer.
222
+ function allocContexts(uint count) internal pure returns (Writer memory writer) {
223
+ return allocFromHint(count, Hints.Context);
224
+ }
225
+
156
226
  // -------------------------------------------------------------------------
157
227
  // Fixed-width write helpers
158
228
  // -------------------------------------------------------------------------
@@ -172,14 +242,6 @@ library Writers {
172
242
  }
173
243
  }
174
244
 
175
- /// @notice Commit a logical writer advance after a low-level write.
176
- /// @dev Low-level write helpers validate the padded backing buffer. This
177
- /// enforces the caller-requested logical capacity recorded in `end`.
178
- function commit(Writer memory writer, uint next) private pure {
179
- if (next > writer.end) revert WriterOverflow();
180
- writer.i = next;
181
- }
182
-
183
245
  /// @notice Write raw bytes directly into `dst` at byte offset `i` without a block header.
184
246
  /// @param dst Destination buffer.
185
247
  /// @param i Write offset within `dst`.
@@ -431,57 +493,160 @@ library Writers {
431
493
  }
432
494
  }
433
495
 
434
- /// @notice Write a dynamic block with a fixed 32-byte head word.
435
- /// @param dst Destination buffer; must have at least `i + Sizes.B32 + tail.length` bytes.
496
+ /// @notice Write a block with a 32-byte head and two nested BYTES payloads.
497
+ /// @param dst Destination buffer; must have at least `i + Sizes.B32 + 2 * Sizes.Header + b.length + c.length` bytes.
436
498
  /// @param i Write offset within `dst`.
437
- /// @param key Block type key.
499
+ /// @param key Block key.
438
500
  /// @param a Fixed head word.
439
- /// @param tail Dynamic payload bytes appended after the head.
501
+ /// @param b First raw nested payload.
502
+ /// @param c Second raw nested payload.
440
503
  /// @return next Byte offset immediately after the written block.
441
- function writeBlockHead32(
504
+ function writeBlock32BytesBytes(
442
505
  bytes memory dst,
443
506
  uint i,
444
507
  bytes4 key,
445
508
  bytes32 a,
446
- bytes memory tail
509
+ bytes memory b,
510
+ bytes memory c
447
511
  ) internal pure returns (uint next) {
448
- uint len = 32 + tail.length;
512
+ uint bLen = b.length;
513
+ uint len = 32 + 2 * Sizes.Header + bLen + c.length;
449
514
  next = i + Sizes.Header + len;
450
- if (i + Sizes.B32 + tail.length > dst.length) revert WriterOverflow();
451
- uint p = writeHeader(dst, i, key, uint32(max32(len)));
452
- assembly ("memory-safe") {
453
- mstore(add(p, 0x08), a)
454
- mcopy(add(p, 0x28), add(tail, 0x20), mload(tail))
515
+ if (next > dst.length) revert WriterOverflow();
516
+
517
+ {
518
+ uint p = writeHeader(dst, i, key, uint32(max32(len)));
519
+ assembly ("memory-safe") {
520
+ mstore(add(p, 0x08), a)
521
+ }
522
+ }
523
+
524
+ {
525
+ uint q = writeHeader(dst, i + Sizes.Header + 32, Keys.Bytes, uint32(max32(bLen)));
526
+ assembly ("memory-safe") {
527
+ mcopy(add(q, 0x08), add(b, 0x20), mload(b))
528
+ }
529
+ }
530
+
531
+ {
532
+ uint r = writeHeader(dst, i + Sizes.Header + 32 + Sizes.Header + bLen, Keys.Bytes, uint32(max32(c.length)));
533
+ assembly ("memory-safe") {
534
+ mcopy(add(r, 0x08), add(c, 0x20), mload(c))
535
+ }
455
536
  }
456
537
  }
457
538
 
458
- /// @notice Write a dynamic block with a fixed 64-byte head.
459
- /// @param dst Destination buffer; must have at least `i + Sizes.B64 + tail.length` bytes.
539
+ /// @notice Write a block with a 64-byte head and two nested BYTES payloads.
540
+ /// @param dst Destination buffer; must have at least `i + Sizes.B64 + 2 * Sizes.Header + c.length + d.length` bytes.
460
541
  /// @param i Write offset within `dst`.
461
- /// @param key Block type key.
462
- /// @param a First fixed head word.
463
- /// @param b Second fixed head word.
464
- /// @param tail Dynamic payload bytes appended after the head.
542
+ /// @param key Block key.
543
+ /// @param a First head word.
544
+ /// @param b Second head word.
545
+ /// @param c First raw nested payload.
546
+ /// @param d Second raw nested payload.
465
547
  /// @return next Byte offset immediately after the written block.
466
- function writeBlockHead64(
548
+ function writeBlock64BytesBytes(
467
549
  bytes memory dst,
468
550
  uint i,
469
551
  bytes4 key,
470
552
  bytes32 a,
471
553
  bytes32 b,
472
- bytes memory tail
554
+ bytes memory c,
555
+ bytes memory d
473
556
  ) internal pure returns (uint next) {
474
- uint len = 64 + tail.length;
557
+ uint cLen = c.length;
558
+ uint len = 64 + 2 * Sizes.Header + cLen + d.length;
475
559
  next = i + Sizes.Header + len;
476
- if (i + Sizes.B64 + tail.length > dst.length) revert WriterOverflow();
477
- uint p = writeHeader(dst, i, key, uint32(max32(len)));
478
- assembly ("memory-safe") {
479
- mstore(add(p, 0x08), a)
480
- mstore(add(p, 0x28), b)
481
- mcopy(add(p, 0x48), add(tail, 0x20), mload(tail))
560
+ if (next > dst.length) revert WriterOverflow();
561
+
562
+ {
563
+ uint p = writeHeader(dst, i, key, uint32(max32(len)));
564
+ assembly ("memory-safe") {
565
+ mstore(add(p, 0x08), a)
566
+ mstore(add(p, 0x28), b)
567
+ }
568
+ }
569
+
570
+ {
571
+ uint q = writeHeader(dst, i + Sizes.Header + 64, Keys.Bytes, uint32(max32(cLen)));
572
+ assembly ("memory-safe") {
573
+ mcopy(add(q, 0x08), add(c, 0x20), mload(c))
574
+ }
575
+ }
576
+
577
+ {
578
+ uint r = writeHeader(dst, i + Sizes.Header + 64 + Sizes.Header + cLen, Keys.Bytes, uint32(max32(d.length)));
579
+ assembly ("memory-safe") {
580
+ mcopy(add(r, 0x08), add(d, 0x20), mload(d))
581
+ }
482
582
  }
483
583
  }
484
584
 
585
+ /// @notice Write a block with a 64-byte head and nested BYTES payload.
586
+ /// @param dst Destination buffer; must have at least `i + Sizes.B64 + Sizes.Header + c.length` bytes.
587
+ /// @param i Write offset within `dst`.
588
+ /// @param key Block key.
589
+ /// @param a First head word.
590
+ /// @param b Second head word.
591
+ /// @param c Raw nested payload.
592
+ /// @return next Byte offset immediately after the written block.
593
+ function writeBlock64Bytes(
594
+ bytes memory dst,
595
+ uint i,
596
+ bytes4 key,
597
+ bytes32 a,
598
+ bytes32 b,
599
+ bytes memory c
600
+ ) internal pure returns (uint next) {
601
+ uint cLen = c.length;
602
+ uint len = 64 + Sizes.Header + cLen;
603
+ next = i + Sizes.Header + len;
604
+ if (next > dst.length) revert WriterOverflow();
605
+
606
+ {
607
+ uint p = writeHeader(dst, i, key, uint32(max32(len)));
608
+ assembly ("memory-safe") {
609
+ mstore(add(p, 0x08), a)
610
+ mstore(add(p, 0x28), b)
611
+ }
612
+ }
613
+
614
+ {
615
+ uint q = writeHeader(dst, i + Sizes.Header + 64, Keys.Bytes, uint32(max32(cLen)));
616
+ assembly ("memory-safe") {
617
+ mcopy(add(q, 0x08), add(c, 0x20), mload(c))
618
+ }
619
+ }
620
+ }
621
+
622
+ /// @notice Reserve physical write space and advance the logical writer position.
623
+ /// Fixed writers may use padded backing space but cannot advance past logical capacity;
624
+ /// growable writers expand when `touch` exceeds current capacity.
625
+ /// @return i Original write offset.
626
+ function reserve(Writer memory writer, uint next, uint touch) private pure returns (uint i) {
627
+ i = writer.i;
628
+ if (writer.growable) {
629
+ if (touch > writer.end) {
630
+ uint end = writer.end == 0 ? 64 : writer.end * 2;
631
+ while (end < touch) {
632
+ end *= 2;
633
+ }
634
+
635
+ uint padded = ((end + 31) & ~uint(31)) + 32;
636
+ bytes memory src = writer.dst;
637
+ bytes memory dst = new bytes(padded);
638
+ assembly ("memory-safe") {
639
+ mcopy(add(dst, 0x20), add(src, 0x20), i)
640
+ }
641
+ writer.end = end;
642
+ writer.dst = dst;
643
+ }
644
+ } else if (touch > writer.dst.length) revert WriterOverflow();
645
+
646
+ if (next > writer.end) revert WriterOverflow();
647
+ writer.i = next;
648
+ }
649
+
485
650
  // -------------------------------------------------------------------------
486
651
  // Append helpers
487
652
  // -------------------------------------------------------------------------
@@ -490,7 +655,9 @@ library Writers {
490
655
  /// @param writer Destination writer; `i` is advanced by `data.length`.
491
656
  /// @param data Bytes to append.
492
657
  function append(Writer memory writer, bytes memory data) internal pure {
493
- commit(writer, write(writer.dst, writer.i, data));
658
+ uint next = writer.i + data.length;
659
+ uint i = reserve(writer, next, next);
660
+ write(writer.dst, i, data);
494
661
  }
495
662
 
496
663
  /// @notice Append a raw 32-byte word without a block header.
@@ -498,7 +665,10 @@ library Writers {
498
665
  /// @param value Word to append.
499
666
  /// @param keep Number of bytes to keep from the word (1..32).
500
667
  function append32(Writer memory writer, bytes32 value, uint keep) internal pure {
501
- commit(writer, write32(writer.dst, writer.i, value, keep));
668
+ uint i = writer.i;
669
+ uint next = i + keep;
670
+ i = reserve(writer, next, i + 32);
671
+ write32(writer.dst, i, value, keep);
502
672
  }
503
673
 
504
674
  /// @notice Append two raw 32-byte words without a block header.
@@ -507,7 +677,10 @@ library Writers {
507
677
  /// @param b Second word to append.
508
678
  /// @param keep Number of bytes to keep from the final word (1..32).
509
679
  function append64(Writer memory writer, bytes32 a, bytes32 b, uint keep) internal pure {
510
- commit(writer, write64(writer.dst, writer.i, a, b, keep));
680
+ uint i = writer.i;
681
+ uint next = i + 32 + keep;
682
+ i = reserve(writer, next, i + 64);
683
+ write64(writer.dst, i, a, b, keep);
511
684
  }
512
685
 
513
686
  /// @notice Append three raw 32-byte words without a block header.
@@ -517,7 +690,10 @@ library Writers {
517
690
  /// @param c Third word to append.
518
691
  /// @param keep Number of bytes to keep from the final word (1..32).
519
692
  function append96(Writer memory writer, bytes32 a, bytes32 b, bytes32 c, uint keep) internal pure {
520
- commit(writer, write96(writer.dst, writer.i, a, b, c, keep));
693
+ uint i = writer.i;
694
+ uint next = i + 64 + keep;
695
+ i = reserve(writer, next, i + 96);
696
+ write96(writer.dst, i, a, b, c, keep);
521
697
  }
522
698
 
523
699
  /// @notice Append a dynamic block.
@@ -525,7 +701,9 @@ library Writers {
525
701
  /// @param key Block type key.
526
702
  /// @param data Dynamic payload bytes.
527
703
  function appendBlock(Writer memory writer, bytes4 key, bytes memory data) internal pure {
528
- commit(writer, writeBlock(writer.dst, writer.i, key, data));
704
+ uint next = writer.i + Sizes.Header + data.length;
705
+ uint i = reserve(writer, next, next);
706
+ writeBlock(writer.dst, i, key, data);
529
707
  }
530
708
 
531
709
  /// @notice Append a fixed-width 32-byte-payload block.
@@ -534,7 +712,10 @@ library Writers {
534
712
  /// @param a First payload word.
535
713
  /// @param keep Number of bytes to keep from the final payload word (1..32).
536
714
  function appendBlock32(Writer memory writer, bytes4 key, bytes32 a, uint keep) internal pure {
537
- commit(writer, writeBlock32(writer.dst, writer.i, key, a, keep));
715
+ uint i = writer.i;
716
+ uint next = i + Sizes.Header + keep;
717
+ i = reserve(writer, next, i + Sizes.B32);
718
+ writeBlock32(writer.dst, i, key, a, keep);
538
719
  }
539
720
 
540
721
  /// @notice Append a fixed-width 64-byte-payload block.
@@ -544,7 +725,10 @@ library Writers {
544
725
  /// @param b Second payload word.
545
726
  /// @param keep Number of bytes to keep from the final payload word (1..32).
546
727
  function appendBlock64(Writer memory writer, bytes4 key, bytes32 a, bytes32 b, uint keep) internal pure {
547
- commit(writer, writeBlock64(writer.dst, writer.i, key, a, b, keep));
728
+ uint i = writer.i;
729
+ uint next = i + Sizes.Header + 32 + keep;
730
+ i = reserve(writer, next, i + Sizes.B64);
731
+ writeBlock64(writer.dst, i, key, a, b, keep);
548
732
  }
549
733
 
550
734
  /// @notice Append a fixed-width 96-byte-payload block.
@@ -555,7 +739,10 @@ library Writers {
555
739
  /// @param c Third payload word.
556
740
  /// @param keep Number of bytes to keep from the final payload word (1..32).
557
741
  function appendBlock96(Writer memory writer, bytes4 key, bytes32 a, bytes32 b, bytes32 c, uint keep) internal pure {
558
- commit(writer, writeBlock96(writer.dst, writer.i, key, a, b, c, keep));
742
+ uint i = writer.i;
743
+ uint next = i + Sizes.Header + 64 + keep;
744
+ i = reserve(writer, next, i + Sizes.B96);
745
+ writeBlock96(writer.dst, i, key, a, b, c, keep);
559
746
  }
560
747
 
561
748
  /// @notice Append a fixed-width 128-byte-payload block.
@@ -575,7 +762,10 @@ library Writers {
575
762
  bytes32 d,
576
763
  uint keep
577
764
  ) internal pure {
578
- commit(writer, writeBlock128(writer.dst, writer.i, key, a, b, c, d, keep));
765
+ uint i = writer.i;
766
+ uint next = i + Sizes.Header + 96 + keep;
767
+ i = reserve(writer, next, i + Sizes.B128);
768
+ writeBlock128(writer.dst, i, key, a, b, c, d, keep);
579
769
  }
580
770
 
581
771
  /// @notice Append a fixed-width 160-byte-payload block.
@@ -597,39 +787,111 @@ library Writers {
597
787
  bytes32 e,
598
788
  uint keep
599
789
  ) internal pure {
600
- commit(writer, writeBlock160(writer.dst, writer.i, key, a, b, c, d, e, keep));
790
+ uint i = writer.i;
791
+ uint next = i + Sizes.Header + 128 + keep;
792
+ i = reserve(writer, next, i + Sizes.B160);
793
+ writeBlock160(writer.dst, i, key, a, b, c, d, e, keep);
601
794
  }
602
795
 
603
- /// @notice Append a dynamic block with a fixed 32-byte head word.
604
- /// @param writer Destination writer; `i` is advanced by `Sizes.B32 + tail.length`.
605
- /// @param key Block type key.
796
+ /// @notice Append a block with a 32-byte head and two nested BYTES payloads.
797
+ /// @param writer Destination writer; `i` is advanced by the encoded block length.
798
+ /// @param key Block key.
606
799
  /// @param a Fixed head word.
607
- /// @param tail Dynamic payload bytes appended after the head.
608
- function appendBlockHead32(Writer memory writer, bytes4 key, bytes32 a, bytes memory tail) internal pure {
609
- commit(writer, writeBlockHead32(writer.dst, writer.i, key, a, tail));
800
+ /// @param b First raw nested payload.
801
+ /// @param c Second raw nested payload.
802
+ function appendBlock32BytesBytes(
803
+ Writer memory writer,
804
+ bytes4 key,
805
+ bytes32 a,
806
+ bytes memory b,
807
+ bytes memory c
808
+ ) internal pure {
809
+ uint i = writer.i;
810
+ uint next = i + Sizes.B32 + 2 * Sizes.Header + b.length + c.length;
811
+ i = reserve(writer, next, next);
812
+ writeBlock32BytesBytes(writer.dst, i, key, a, b, c);
610
813
  }
611
814
 
612
- /// @notice Append a dynamic block with a fixed 64-byte head.
613
- /// @param writer Destination writer; `i` is advanced by `Sizes.B64 + tail.length`.
614
- /// @param key Block type key.
615
- /// @param a First fixed head word.
616
- /// @param b Second fixed head word.
617
- /// @param tail Dynamic payload bytes appended after the head.
618
- function appendBlockHead64(
815
+ /// @notice Append a block with a 64-byte head and two nested BYTES payloads.
816
+ /// @param writer Destination writer; `i` is advanced by the encoded block length.
817
+ /// @param key Block key.
818
+ /// @param a First head word.
819
+ /// @param b Second head word.
820
+ /// @param c First raw nested payload.
821
+ /// @param d Second raw nested payload.
822
+ function appendBlock64BytesBytes(
619
823
  Writer memory writer,
620
824
  bytes4 key,
621
825
  bytes32 a,
622
826
  bytes32 b,
623
- bytes memory tail
827
+ bytes memory c,
828
+ bytes memory d
829
+ ) internal pure {
830
+ uint i = writer.i;
831
+ uint next = i + Sizes.B64 + 2 * Sizes.Header + c.length + d.length;
832
+ i = reserve(writer, next, next);
833
+ writeBlock64BytesBytes(writer.dst, i, key, a, b, c, d);
834
+ }
835
+
836
+ /// @notice Append a block with a 64-byte head and nested BYTES payload.
837
+ /// @param writer Destination writer; `i` is advanced by the encoded block length.
838
+ /// @param key Block key.
839
+ /// @param a First head word.
840
+ /// @param b Second head word.
841
+ /// @param c Raw nested payload.
842
+ function appendBlock64Bytes(Writer memory writer, bytes4 key, bytes32 a, bytes32 b, bytes memory c) internal pure {
843
+ uint i = writer.i;
844
+ uint next = i + Sizes.B64 + Sizes.Header + c.length;
845
+ i = reserve(writer, next, next);
846
+ writeBlock64Bytes(writer.dst, i, key, a, b, c);
847
+ }
848
+
849
+ /// @notice Append a BYTES block.
850
+ /// @param writer Destination writer; `i` is advanced by the encoded BYTES block length.
851
+ /// @param data Raw bytes payload.
852
+ function appendBytes(Writer memory writer, bytes memory data) internal pure {
853
+ appendBlock(writer, Keys.Bytes, data);
854
+ }
855
+
856
+ /// @notice Append a STEP block with a nested request BYTES payload.
857
+ /// @param writer Destination writer; `i` is advanced by the encoded STEP block length.
858
+ /// @param target Command target identifier.
859
+ /// @param value Native value forwarded with the step.
860
+ /// @param request Raw nested request payload.
861
+ function appendStep(Writer memory writer, uint target, uint value, bytes memory request) internal pure {
862
+ appendBlock64Bytes(writer, Keys.Step, bytes32(target), bytes32(value), request);
863
+ }
864
+
865
+ /// @notice Append a CALL block with a nested payload BYTES block.
866
+ /// @param writer Destination writer; `i` is advanced by the encoded CALL block length.
867
+ /// @param target Call target identifier.
868
+ /// @param value Native value forwarded with the call.
869
+ /// @param data Raw nested call payload.
870
+ function appendCall(Writer memory writer, uint target, uint value, bytes memory data) internal pure {
871
+ appendBlock64Bytes(writer, Keys.Call, bytes32(target), bytes32(value), data);
872
+ }
873
+
874
+ /// @notice Append a CONTEXT block with a value budget and nested state/request BYTES payloads.
875
+ /// @param writer Destination writer; `i` is advanced by the encoded CONTEXT block length.
876
+ /// @param account Command account identifier.
877
+ /// @param value Native value budget assigned to the context.
878
+ /// @param state Raw nested state payload.
879
+ /// @param request Raw nested request payload.
880
+ function appendContext(
881
+ Writer memory writer,
882
+ bytes32 account,
883
+ uint value,
884
+ bytes memory state,
885
+ bytes memory request
624
886
  ) internal pure {
625
- commit(writer, writeBlockHead64(writer.dst, writer.i, key, a, b, tail));
887
+ appendBlock64BytesBytes(writer, Keys.Context, account, bytes32(value), state, request);
626
888
  }
627
889
 
628
890
  /// @notice Append a STATUS form block.
629
- /// @param writer Destination writer; `i` is advanced by `Sizes.B32`.
891
+ /// @param writer Destination writer; `i` is advanced by `Sizes.Status`.
630
892
  /// @param ok Status value to encode.
631
893
  function appendStatus(Writer memory writer, bool ok) internal pure {
632
- commit(writer, writeBlock32(writer.dst, writer.i, Keys.Status, ok ? bytes32(uint(1)) : bytes32(0), 32));
894
+ appendBlock32(writer, Keys.Status, ok ? bytes32(uint(1) << 248) : bytes32(0), 1);
633
895
  }
634
896
 
635
897
  /// @notice Append a BALANCE block using separate field values.
@@ -638,17 +900,14 @@ library Writers {
638
900
  /// @param meta Asset metadata slot.
639
901
  /// @param amount Token amount.
640
902
  function appendBalance(Writer memory writer, bytes32 asset, bytes32 meta, uint amount) internal pure {
641
- commit(writer, writeBlock96(writer.dst, writer.i, Keys.Balance, asset, meta, bytes32(amount), 32));
903
+ appendBlock96(writer, Keys.Balance, asset, meta, bytes32(amount), 32);
642
904
  }
643
905
 
644
906
  /// @notice Append a BALANCE block from a struct.
645
907
  /// @param writer Destination writer; `i` is advanced by `Sizes.Balance`.
646
908
  /// @param value Balance fields to encode.
647
909
  function appendBalance(Writer memory writer, AssetAmount memory value) internal pure {
648
- commit(
649
- writer,
650
- writeBlock96(writer.dst, writer.i, Keys.Balance, value.asset, value.meta, bytes32(value.amount), 32)
651
- );
910
+ appendBalance(writer, value.asset, value.meta, value.amount);
652
911
  }
653
912
 
654
913
  /// @notice Append an AMOUNT block using separate field values.
@@ -657,17 +916,14 @@ library Writers {
657
916
  /// @param meta Asset metadata slot.
658
917
  /// @param amount Token amount.
659
918
  function appendAmount(Writer memory writer, bytes32 asset, bytes32 meta, uint amount) internal pure {
660
- commit(writer, writeBlock96(writer.dst, writer.i, Keys.Amount, asset, meta, bytes32(amount), 32));
919
+ appendBlock96(writer, Keys.Amount, asset, meta, bytes32(amount), 32);
661
920
  }
662
921
 
663
922
  /// @notice Append an AMOUNT block from a struct.
664
923
  /// @param writer Destination writer; `i` is advanced by `Sizes.Balance`.
665
924
  /// @param value Amount fields to encode.
666
925
  function appendAmount(Writer memory writer, AssetAmount memory value) internal pure {
667
- commit(
668
- writer,
669
- writeBlock96(writer.dst, writer.i, Keys.Amount, value.asset, value.meta, bytes32(value.amount), 32)
670
- );
926
+ appendAmount(writer, value.asset, value.meta, value.amount);
671
927
  }
672
928
 
673
929
  /// @notice Append an ACCOUNT_AMOUNT form block using separate field values.
@@ -683,29 +939,14 @@ library Writers {
683
939
  bytes32 meta,
684
940
  uint amount
685
941
  ) internal pure {
686
- commit(
687
- writer,
688
- writeBlock128(writer.dst, writer.i, Keys.AccountAmount, account, asset, meta, bytes32(amount), 32)
689
- );
942
+ appendBlock128(writer, Keys.AccountAmount, account, asset, meta, bytes32(amount), 32);
690
943
  }
691
944
 
692
945
  /// @notice Append an ACCOUNT_AMOUNT form block from a struct.
693
946
  /// @param writer Destination writer; `i` is advanced by `Sizes.B128`.
694
947
  /// @param value Account amount fields to encode.
695
948
  function appendAccountAmount(Writer memory writer, AccountAmount memory value) internal pure {
696
- commit(
697
- writer,
698
- writeBlock128(
699
- writer.dst,
700
- writer.i,
701
- Keys.AccountAmount,
702
- value.account,
703
- value.asset,
704
- value.meta,
705
- bytes32(value.amount),
706
- 32
707
- )
708
- );
949
+ appendAccountAmount(writer, value.account, value.asset, value.meta, value.amount);
709
950
  }
710
951
 
711
952
  /// @notice Append an ASSET block.
@@ -713,7 +954,7 @@ library Writers {
713
954
  /// @param asset Asset identifier.
714
955
  /// @param meta Asset metadata slot.
715
956
  function appendAsset(Writer memory writer, bytes32 asset, bytes32 meta) internal pure {
716
- commit(writer, writeBlock64(writer.dst, writer.i, Keys.Asset, asset, meta, 32));
957
+ appendBlock64(writer, Keys.Asset, asset, meta, 32);
717
958
  }
718
959
 
719
960
  /// @notice Append a BOUNTY block to the writer.
@@ -721,7 +962,7 @@ library Writers {
721
962
  /// @param amount Relayer reward amount.
722
963
  /// @param relayer Relayer account identifier.
723
964
  function appendBounty(Writer memory writer, uint amount, bytes32 relayer) internal pure {
724
- commit(writer, writeBlock64(writer.dst, writer.i, Keys.Bounty, bytes32(amount), relayer, 32));
965
+ appendBlock64(writer, Keys.Bounty, bytes32(amount), relayer, 32);
725
966
  }
726
967
 
727
968
  /// @notice Append a CUSTODY block using separate field values.
@@ -731,10 +972,7 @@ library Writers {
731
972
  /// @param meta Asset metadata slot.
732
973
  /// @param amount Token amount.
733
974
  function appendCustody(Writer memory writer, uint host, bytes32 asset, bytes32 meta, uint amount) internal pure {
734
- commit(
735
- writer,
736
- writeBlock128(writer.dst, writer.i, Keys.Custody, bytes32(host), asset, meta, bytes32(amount), 32)
737
- );
975
+ appendBlock128(writer, Keys.Custody, bytes32(host), asset, meta, bytes32(amount), 32);
738
976
  }
739
977
 
740
978
  /// @notice Append a CUSTODY block from a host and asset amount.
@@ -742,57 +980,29 @@ library Writers {
742
980
  /// @param host Host node ID.
743
981
  /// @param value Custody fields to encode.
744
982
  function appendCustody(Writer memory writer, uint host, AssetAmount memory value) internal pure {
745
- commit(
746
- writer,
747
- writeBlock128(
748
- writer.dst,
749
- writer.i,
750
- Keys.Custody,
751
- bytes32(host),
752
- value.asset,
753
- value.meta,
754
- bytes32(value.amount),
755
- 32
756
- )
757
- );
983
+ appendCustody(writer, host, value.asset, value.meta, value.amount);
758
984
  }
759
985
 
760
986
  /// @notice Append a CUSTODY block from a host amount struct.
761
987
  /// @param writer Destination writer; `i` is advanced by `Sizes.HostAmount`.
762
988
  /// @param value Custody fields to encode.
763
989
  function appendCustody(Writer memory writer, HostAmount memory value) internal pure {
764
- commit(
765
- writer,
766
- writeBlock128(
767
- writer.dst,
768
- writer.i,
769
- Keys.Custody,
770
- bytes32(value.host),
771
- value.asset,
772
- value.meta,
773
- bytes32(value.amount),
774
- 32
775
- )
776
- );
990
+ appendCustody(writer, value.host, value.asset, value.meta, value.amount);
777
991
  }
778
992
 
779
993
  /// @notice Append a TRANSACTION block from a struct.
780
994
  /// @param writer Destination writer; `i` is advanced by `Sizes.Transaction`.
781
995
  /// @param value Transfer record fields to encode.
782
996
  function appendTransaction(Writer memory writer, Tx memory value) internal pure {
783
- commit(
997
+ appendBlock160(
784
998
  writer,
785
- writeBlock160(
786
- writer.dst,
787
- writer.i,
788
- Keys.Transaction,
789
- bytes32(value.from),
790
- bytes32(value.to),
791
- value.asset,
792
- value.meta,
793
- bytes32(value.amount),
794
- 32
795
- )
999
+ Keys.Transaction,
1000
+ bytes32(value.from),
1001
+ bytes32(value.to),
1002
+ value.asset,
1003
+ value.meta,
1004
+ bytes32(value.amount),
1005
+ 32
796
1006
  );
797
1007
  }
798
1008