@hazbase/simplicity 0.0.5 → 0.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 (61) hide show
  1. package/README.md +140 -1038
  2. package/dist/cli.js +3341 -269
  3. package/dist/client/SimplicityClient.d.ts +91 -290
  4. package/dist/client/SimplicityClient.js +93 -23
  5. package/dist/core/executor.js +67 -92
  6. package/dist/core/lineage.d.ts +18 -0
  7. package/dist/core/lineage.js +30 -0
  8. package/dist/core/outputBinding.d.ts +61 -0
  9. package/dist/core/outputBinding.js +552 -0
  10. package/dist/core/reporting.d.ts +22 -0
  11. package/dist/core/reporting.js +40 -0
  12. package/dist/core/schnorr.d.ts +5 -0
  13. package/dist/core/schnorr.js +46 -0
  14. package/dist/core/types.d.ts +799 -1
  15. package/dist/docs/definitions/bond-anchor.simf +19 -0
  16. package/dist/docs/definitions/bond-definition.json +10 -0
  17. package/dist/docs/definitions/bond-descriptor-bound-settlement-machine.simf +144 -0
  18. package/dist/docs/definitions/bond-issuance-anchor.simf +26 -0
  19. package/dist/docs/definitions/bond-issuance-state-partial-redemption.json +18 -0
  20. package/dist/docs/definitions/bond-issuance-state-redeemed.json +18 -0
  21. package/dist/docs/definitions/bond-issuance-state.json +12 -0
  22. package/dist/docs/definitions/bond-redemption-state-machine.simf +118 -0
  23. package/dist/docs/definitions/bond-redemption-transition.simf +41 -0
  24. package/dist/docs/definitions/bond-script-bound-settlement-machine.simf +142 -0
  25. package/dist/docs/definitions/fund-capital-call-open.simf +82 -0
  26. package/dist/docs/definitions/fund-capital-call-refund-only.simf +67 -0
  27. package/dist/docs/definitions/fund-capital-call-state.json +11 -0
  28. package/dist/docs/definitions/fund-definition.json +8 -0
  29. package/dist/docs/definitions/fund-distribution-claim.simf +57 -0
  30. package/dist/docs/definitions/receivable-definition.json +9 -0
  31. package/dist/docs/definitions/receivable-funding-claim.json +13 -0
  32. package/dist/docs/definitions/receivable-funding-claim.simf +58 -0
  33. package/dist/docs/definitions/receivable-repayment-claim.json +13 -0
  34. package/dist/docs/definitions/receivable-repayment-claim.simf +59 -0
  35. package/dist/docs/definitions/receivable-state-funded.json +20 -0
  36. package/dist/docs/definitions/receivable-state-originated.json +19 -0
  37. package/dist/docs/definitions/receivable-state-repaid.json +20 -0
  38. package/dist/docs/definitions/recursive-delay-direct-next.simf +60 -0
  39. package/dist/docs/definitions/recursive-delay-optional.simf +88 -0
  40. package/dist/docs/definitions/recursive-delay-required.simf +72 -0
  41. package/dist/docs/definitions/recursive-delay.simf +83 -0
  42. package/dist/docs/definitions/recursive-policy-transfer-machine.simf +65 -0
  43. package/dist/domain/bond.d.ts +8649 -720
  44. package/dist/domain/bond.js +1398 -8
  45. package/dist/domain/bondSettlementValidation.d.ts +2 -0
  46. package/dist/domain/bondSettlementValidation.js +28 -0
  47. package/dist/domain/bondValidation.d.ts +37 -1
  48. package/dist/domain/bondValidation.js +137 -11
  49. package/dist/domain/fund.d.ts +2452 -0
  50. package/dist/domain/fund.js +1756 -0
  51. package/dist/domain/fundValidation.d.ts +152 -0
  52. package/dist/domain/fundValidation.js +767 -0
  53. package/dist/domain/policies.d.ts +1064 -0
  54. package/dist/domain/policies.js +1625 -0
  55. package/dist/domain/receivable.d.ts +824 -0
  56. package/dist/domain/receivable.js +1375 -0
  57. package/dist/domain/receivableValidation.d.ts +147 -0
  58. package/dist/domain/receivableValidation.js +831 -0
  59. package/dist/index.d.ts +8 -2
  60. package/dist/index.js +137 -21
  61. package/package.json +20 -2
@@ -0,0 +1,67 @@
1
+ /*
2
+ * LP capital call refund-only contract.
3
+ *
4
+ * This artifact is reached only after the open capital call is explicitly
5
+ * rolled over post-cutoff. Once in this state, only the LP refund path remains.
6
+ */
7
+ fn not(bit: bool) -> bool {
8
+ <u1>::into(jet::complement_1(<bool>::into(bit)))
9
+ }
10
+
11
+ fn require_definition_anchor() {
12
+ let anchored_definition_hash: u256 = 0x{{DEFINITION_HASH}};
13
+ let zero_hash: u256 = 0x0000000000000000000000000000000000000000000000000000000000000000;
14
+ assert!(not(jet::eq_256(anchored_definition_hash, zero_hash)));
15
+ }
16
+
17
+ fn require_state_anchor() {
18
+ let anchored_state_hash: u256 = 0x{{STATE_HASH}};
19
+ let zero_hash: u256 = 0x0000000000000000000000000000000000000000000000000000000000000000;
20
+ assert!(not(jet::eq_256(anchored_state_hash, zero_hash)));
21
+ }
22
+
23
+ fn require_output_shape(expected_output_hash: u256, expected_output_script_hash: u256, binding_mode: u8) {
24
+ match jet::eq_8(binding_mode, 1) {
25
+ true => {
26
+ let actual_output_hash: u256 = match jet::output_hash(0) {
27
+ Some(output_hash : u256) => output_hash,
28
+ None => panic!(),
29
+ };
30
+ assert!(jet::eq_32(jet::num_outputs(), 2));
31
+ assert!(unwrap(jet::output_is_fee(1)));
32
+ assert!(jet::eq_256(actual_output_hash, expected_output_hash));
33
+ },
34
+ false => {
35
+ match jet::eq_8(binding_mode, 2) {
36
+ true => {
37
+ let actual_output_script_hash: u256 = unwrap(jet::output_script_hash(0));
38
+ assert!(jet::eq_32(jet::num_outputs(), 2));
39
+ assert!(unwrap(jet::output_is_fee(1)));
40
+ assert!(jet::eq_256(actual_output_script_hash, expected_output_script_hash));
41
+ },
42
+ false => {},
43
+ }
44
+ },
45
+ }
46
+ }
47
+
48
+ fn refund_path(
49
+ expected_output_hash: u256,
50
+ expected_output_script_hash: u256,
51
+ binding_mode: u8,
52
+ lp_signature: Signature
53
+ ) {
54
+ require_output_shape(expected_output_hash, expected_output_script_hash, binding_mode);
55
+ let lp: Pubkey = 0x{{LP_XONLY}};
56
+ jet::bip_0340_verify((lp, jet::sig_all_hash()), lp_signature)
57
+ }
58
+
59
+ fn main() {
60
+ require_definition_anchor();
61
+ require_state_anchor();
62
+ let expected_output_hash: u256 = witness::EXPECTED_PAYOUT_OUTPUT_HASH;
63
+ let expected_output_script_hash: u256 = witness::EXPECTED_PAYOUT_OUTPUT_SCRIPT_HASH;
64
+ let binding_mode: u8 = witness::OUTPUT_BINDING_MODE;
65
+ let signer_signature: Signature = witness::SIGNER_SIGNATURE;
66
+ refund_path(expected_output_hash, expected_output_script_hash, binding_mode, signer_signature)
67
+ }
@@ -0,0 +1,11 @@
1
+ {
2
+ "callId": "CALL-001",
3
+ "fundId": "FUND-2026-ALPHA",
4
+ "lpId": "lp-a",
5
+ "currencyAssetId": "bitcoin",
6
+ "amount": 6000,
7
+ "lpXonly": "f9308a019258c3106ac5d2d1c1d7d7f3c2e5f5b7a9e3d5f2c1a6b8c9d0e1f2a3",
8
+ "managerXonly": "79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798",
9
+ "status": "OPEN",
10
+ "claimCutoffHeight": 2345678
11
+ }
@@ -0,0 +1,8 @@
1
+ {
2
+ "fundId": "FUND-2026-ALPHA",
3
+ "managerEntityId": "manager-a",
4
+ "managerXonly": "79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798",
5
+ "currencyAssetId": "bitcoin",
6
+ "jurisdiction": "JP",
7
+ "vintage": "2026"
8
+ }
@@ -0,0 +1,57 @@
1
+ /*
2
+ * LP distribution claim contract.
3
+ *
4
+ * Fund admin prepares the distribution state off-chain, then the LP claims the
5
+ * payout in a one-shot spend. Runtime output binding is optional.
6
+ */
7
+ fn not(bit: bool) -> bool {
8
+ <u1>::into(jet::complement_1(<bool>::into(bit)))
9
+ }
10
+
11
+ fn require_definition_anchor() {
12
+ let anchored_definition_hash: u256 = 0x{{DEFINITION_HASH}};
13
+ let zero_hash: u256 = 0x0000000000000000000000000000000000000000000000000000000000000000;
14
+ assert!(not(jet::eq_256(anchored_definition_hash, zero_hash)));
15
+ }
16
+
17
+ fn require_state_anchor() {
18
+ let anchored_state_hash: u256 = 0x{{STATE_HASH}};
19
+ let zero_hash: u256 = 0x0000000000000000000000000000000000000000000000000000000000000000;
20
+ assert!(not(jet::eq_256(anchored_state_hash, zero_hash)));
21
+ }
22
+
23
+ fn require_output_shape(expected_output_hash: u256, expected_output_script_hash: u256, binding_mode: u8) {
24
+ match jet::eq_8(binding_mode, 1) {
25
+ true => {
26
+ let actual_output_hash: u256 = match jet::output_hash(0) {
27
+ Some(output_hash : u256) => output_hash,
28
+ None => panic!(),
29
+ };
30
+ assert!(jet::eq_32(jet::num_outputs(), 2));
31
+ assert!(unwrap(jet::output_is_fee(1)));
32
+ assert!(jet::eq_256(actual_output_hash, expected_output_hash));
33
+ },
34
+ false => {
35
+ match jet::eq_8(binding_mode, 2) {
36
+ true => {
37
+ let actual_output_script_hash: u256 = unwrap(jet::output_script_hash(0));
38
+ assert!(jet::eq_32(jet::num_outputs(), 2));
39
+ assert!(unwrap(jet::output_is_fee(1)));
40
+ assert!(jet::eq_256(actual_output_script_hash, expected_output_script_hash));
41
+ },
42
+ false => {},
43
+ }
44
+ },
45
+ }
46
+ }
47
+
48
+ fn main() {
49
+ require_definition_anchor();
50
+ require_state_anchor();
51
+ let expected_output_hash: u256 = witness::EXPECTED_PAYOUT_OUTPUT_HASH;
52
+ let expected_output_script_hash: u256 = witness::EXPECTED_PAYOUT_OUTPUT_SCRIPT_HASH;
53
+ let binding_mode: u8 = witness::OUTPUT_BINDING_MODE;
54
+ require_output_shape(expected_output_hash, expected_output_script_hash, binding_mode);
55
+ let lp: Pubkey = 0x{{LP_XONLY}};
56
+ jet::bip_0340_verify((lp, jet::sig_all_hash()), witness::SIGNER_SIGNATURE)
57
+ }
@@ -0,0 +1,9 @@
1
+ {
2
+ "receivableId": "REC-001",
3
+ "originatorEntityId": "originator-1",
4
+ "debtorEntityId": "debtor-1",
5
+ "currencyAssetId": "bitcoin",
6
+ "faceValue": 10000,
7
+ "dueDate": "2027-12-31T00:00:00Z",
8
+ "controllerXonly": "1111111111111111111111111111111111111111111111111111111111111111"
9
+ }
@@ -0,0 +1,13 @@
1
+ {
2
+ "claimId": "REC-001-FUNDING-CLAIM",
3
+ "claimKind": "FUNDING",
4
+ "receivableId": "REC-001",
5
+ "currentStateHash": "7a61cc669844f3fd96165c99e3ca42cfae916e824dec4d60e51d56ef574e041a",
6
+ "currentStatus": "FUNDED",
7
+ "payerEntityId": "fund-1",
8
+ "payeeEntityId": "originator-1",
9
+ "claimantXonly": "1111111111111111111111111111111111111111111111111111111111111111",
10
+ "currencyAssetId": "bitcoin",
11
+ "amountSat": 10000,
12
+ "eventTimestamp": "2027-01-02T00:00:00Z"
13
+ }
@@ -0,0 +1,58 @@
1
+ /*
2
+ * Receivable funding claim contract.
3
+ *
4
+ * After a receivable moves into FUNDED state off-chain, the funder/SPV funds
5
+ * this one-shot claim contract and the committed claimant releases the payout
6
+ * to the originator-side destination. Runtime output binding is optional.
7
+ */
8
+ fn not(bit: bool) -> bool {
9
+ <u1>::into(jet::complement_1(<bool>::into(bit)))
10
+ }
11
+
12
+ fn require_definition_anchor() {
13
+ let anchored_definition_hash: u256 = 0x{{DEFINITION_HASH}};
14
+ let zero_hash: u256 = 0x0000000000000000000000000000000000000000000000000000000000000000;
15
+ assert!(not(jet::eq_256(anchored_definition_hash, zero_hash)));
16
+ }
17
+
18
+ fn require_state_anchor() {
19
+ let anchored_state_hash: u256 = 0x{{STATE_HASH}};
20
+ let zero_hash: u256 = 0x0000000000000000000000000000000000000000000000000000000000000000;
21
+ assert!(not(jet::eq_256(anchored_state_hash, zero_hash)));
22
+ }
23
+
24
+ fn require_output_shape(expected_output_hash: u256, expected_output_script_hash: u256, binding_mode: u8) {
25
+ match jet::eq_8(binding_mode, 1) {
26
+ true => {
27
+ let actual_output_hash: u256 = match jet::output_hash(0) {
28
+ Some(output_hash : u256) => output_hash,
29
+ None => panic!(),
30
+ };
31
+ assert!(jet::eq_32(jet::num_outputs(), 2));
32
+ assert!(unwrap(jet::output_is_fee(1)));
33
+ assert!(jet::eq_256(actual_output_hash, expected_output_hash));
34
+ },
35
+ false => {
36
+ match jet::eq_8(binding_mode, 2) {
37
+ true => {
38
+ let actual_output_script_hash: u256 = unwrap(jet::output_script_hash(0));
39
+ assert!(jet::eq_32(jet::num_outputs(), 2));
40
+ assert!(unwrap(jet::output_is_fee(1)));
41
+ assert!(jet::eq_256(actual_output_script_hash, expected_output_script_hash));
42
+ },
43
+ false => {},
44
+ }
45
+ },
46
+ }
47
+ }
48
+
49
+ fn main() {
50
+ require_definition_anchor();
51
+ require_state_anchor();
52
+ let expected_output_hash: u256 = witness::EXPECTED_PAYOUT_OUTPUT_HASH;
53
+ let expected_output_script_hash: u256 = witness::EXPECTED_PAYOUT_OUTPUT_SCRIPT_HASH;
54
+ let binding_mode: u8 = witness::OUTPUT_BINDING_MODE;
55
+ require_output_shape(expected_output_hash, expected_output_script_hash, binding_mode);
56
+ let claimant: Pubkey = 0x{{CLAIMANT_XONLY}};
57
+ jet::bip_0340_verify((claimant, jet::sig_all_hash()), witness::SIGNER_SIGNATURE)
58
+ }
@@ -0,0 +1,13 @@
1
+ {
2
+ "claimId": "REC-001-REPAYMENT-CLAIM",
3
+ "claimKind": "REPAYMENT",
4
+ "receivableId": "REC-001",
5
+ "currentStateHash": "13ae81254644a47f33492812584e169b4ae2051dfedc5ad46d00510c137dc333",
6
+ "currentStatus": "REPAID",
7
+ "payerEntityId": "debtor-1",
8
+ "payeeEntityId": "fund-1",
9
+ "claimantXonly": "1111111111111111111111111111111111111111111111111111111111111111",
10
+ "currencyAssetId": "bitcoin",
11
+ "amountSat": 10000,
12
+ "eventTimestamp": "2027-02-01T00:00:00Z"
13
+ }
@@ -0,0 +1,59 @@
1
+ /*
2
+ * Receivable repayment claim contract.
3
+ *
4
+ * After a receivable moves into PARTIALLY_REPAID or REPAID state off-chain,
5
+ * the debtor-side payment funds this one-shot claim contract and the committed
6
+ * claimant releases the payout to the current holder-side destination. Runtime
7
+ * output binding is optional.
8
+ */
9
+ fn not(bit: bool) -> bool {
10
+ <u1>::into(jet::complement_1(<bool>::into(bit)))
11
+ }
12
+
13
+ fn require_definition_anchor() {
14
+ let anchored_definition_hash: u256 = 0x{{DEFINITION_HASH}};
15
+ let zero_hash: u256 = 0x0000000000000000000000000000000000000000000000000000000000000000;
16
+ assert!(not(jet::eq_256(anchored_definition_hash, zero_hash)));
17
+ }
18
+
19
+ fn require_state_anchor() {
20
+ let anchored_state_hash: u256 = 0x{{STATE_HASH}};
21
+ let zero_hash: u256 = 0x0000000000000000000000000000000000000000000000000000000000000000;
22
+ assert!(not(jet::eq_256(anchored_state_hash, zero_hash)));
23
+ }
24
+
25
+ fn require_output_shape(expected_output_hash: u256, expected_output_script_hash: u256, binding_mode: u8) {
26
+ match jet::eq_8(binding_mode, 1) {
27
+ true => {
28
+ let actual_output_hash: u256 = match jet::output_hash(0) {
29
+ Some(output_hash : u256) => output_hash,
30
+ None => panic!(),
31
+ };
32
+ assert!(jet::eq_32(jet::num_outputs(), 2));
33
+ assert!(unwrap(jet::output_is_fee(1)));
34
+ assert!(jet::eq_256(actual_output_hash, expected_output_hash));
35
+ },
36
+ false => {
37
+ match jet::eq_8(binding_mode, 2) {
38
+ true => {
39
+ let actual_output_script_hash: u256 = unwrap(jet::output_script_hash(0));
40
+ assert!(jet::eq_32(jet::num_outputs(), 2));
41
+ assert!(unwrap(jet::output_is_fee(1)));
42
+ assert!(jet::eq_256(actual_output_script_hash, expected_output_script_hash));
43
+ },
44
+ false => {},
45
+ }
46
+ },
47
+ }
48
+ }
49
+
50
+ fn main() {
51
+ require_definition_anchor();
52
+ require_state_anchor();
53
+ let expected_output_hash: u256 = witness::EXPECTED_PAYOUT_OUTPUT_HASH;
54
+ let expected_output_script_hash: u256 = witness::EXPECTED_PAYOUT_OUTPUT_SCRIPT_HASH;
55
+ let binding_mode: u8 = witness::OUTPUT_BINDING_MODE;
56
+ require_output_shape(expected_output_hash, expected_output_script_hash, binding_mode);
57
+ let claimant: Pubkey = 0x{{CLAIMANT_XONLY}};
58
+ jet::bip_0340_verify((claimant, jet::sig_all_hash()), witness::SIGNER_SIGNATURE)
59
+ }
@@ -0,0 +1,20 @@
1
+ {
2
+ "stateId": "REC-001-S1",
3
+ "receivableId": "REC-001",
4
+ "originatorEntityId": "originator-1",
5
+ "debtorEntityId": "debtor-1",
6
+ "holderEntityId": "fund-1",
7
+ "currencyAssetId": "bitcoin",
8
+ "controllerXonly": "1111111111111111111111111111111111111111111111111111111111111111",
9
+ "faceValue": 10000,
10
+ "outstandingAmount": 10000,
11
+ "repaidAmount": 0,
12
+ "status": "FUNDED",
13
+ "createdAt": "2027-01-02T00:00:00Z",
14
+ "previousStateHash": "575a96c8f73f9a68d8bc76f5683cf042f89dcff73c7136939daf26be6128d935",
15
+ "lastTransition": {
16
+ "type": "FUND",
17
+ "amount": 10000,
18
+ "at": "2027-01-02T00:00:00Z"
19
+ }
20
+ }
@@ -0,0 +1,19 @@
1
+ {
2
+ "stateId": "REC-001-S0",
3
+ "receivableId": "REC-001",
4
+ "originatorEntityId": "originator-1",
5
+ "debtorEntityId": "debtor-1",
6
+ "holderEntityId": "originator-1",
7
+ "currencyAssetId": "bitcoin",
8
+ "controllerXonly": "1111111111111111111111111111111111111111111111111111111111111111",
9
+ "faceValue": 10000,
10
+ "outstandingAmount": 10000,
11
+ "repaidAmount": 0,
12
+ "status": "ORIGINATED",
13
+ "createdAt": "2027-01-01T00:00:00Z",
14
+ "lastTransition": {
15
+ "type": "ORIGINATE",
16
+ "amount": 10000,
17
+ "at": "2027-01-01T00:00:00Z"
18
+ }
19
+ }
@@ -0,0 +1,20 @@
1
+ {
2
+ "stateId": "REC-001-S2",
3
+ "receivableId": "REC-001",
4
+ "originatorEntityId": "originator-1",
5
+ "debtorEntityId": "debtor-1",
6
+ "holderEntityId": "fund-1",
7
+ "currencyAssetId": "bitcoin",
8
+ "controllerXonly": "1111111111111111111111111111111111111111111111111111111111111111",
9
+ "faceValue": 10000,
10
+ "outstandingAmount": 0,
11
+ "repaidAmount": 10000,
12
+ "status": "REPAID",
13
+ "createdAt": "2027-02-01T00:00:00Z",
14
+ "previousStateHash": "7a61cc669844f3fd96165c99e3ca42cfae916e824dec4d60e51d56ef574e041a",
15
+ "lastTransition": {
16
+ "type": "REPAY",
17
+ "amount": 10000,
18
+ "at": "2027-02-01T00:00:00Z"
19
+ }
20
+ }
@@ -0,0 +1,60 @@
1
+ /*
2
+ * Recursive delay policy direct-transfer state contract.
3
+ *
4
+ * This variant is used for 1tx required-mode transfers. The current recipient
5
+ * can spend only after the configured relative delay, and only into the next
6
+ * constrained output shape committed through witness values at execution time.
7
+ */
8
+ fn not(bit: bool) -> bool {
9
+ <u1>::into(jet::complement_1(<bool>::into(bit)))
10
+ }
11
+
12
+ fn require_definition_anchor() {
13
+ let anchored_definition_hash: u256 = 0x{{DEFINITION_HASH}};
14
+ let zero_hash: u256 = 0x0000000000000000000000000000000000000000000000000000000000000000;
15
+ assert!(not(jet::eq_256(anchored_definition_hash, zero_hash)));
16
+ }
17
+
18
+ fn require_state_anchor() {
19
+ let anchored_state_hash: u256 = 0x{{STATE_HASH}};
20
+ let zero_hash: u256 = 0x0000000000000000000000000000000000000000000000000000000000000000;
21
+ assert!(not(jet::eq_256(anchored_state_hash, zero_hash)));
22
+ }
23
+
24
+ fn require_policy_hash_anchor() {
25
+ let anchored_policy_hash: u256 = 0x{{POLICY_HASH}};
26
+ let zero_hash: u256 = 0x0000000000000000000000000000000000000000000000000000000000000000;
27
+ assert!(not(jet::eq_256(anchored_policy_hash, zero_hash)));
28
+ }
29
+
30
+ fn require_required_mode() {
31
+ assert!(jet::eq_8({{PROPAGATION_MODE_8}}, 1));
32
+ }
33
+
34
+ fn require_next_transition_witness(next_policy_hash: u256, next_output_descriptor_hash: u256) {
35
+ let zero_hash: u256 = 0x0000000000000000000000000000000000000000000000000000000000000000;
36
+ assert!(not(jet::eq_256(next_policy_hash, zero_hash)));
37
+ assert!(not(jet::eq_256(next_output_descriptor_hash, zero_hash)));
38
+ }
39
+
40
+ fn require_output_shape(expected_next_output_script_hash: u256) {
41
+ assert!(jet::eq_32(jet::num_outputs(), 2));
42
+ assert!(unwrap(jet::output_is_fee(1)));
43
+ let actual_next_output_script_hash: u256 = unwrap(jet::output_script_hash(0));
44
+ assert!(jet::eq_256(actual_next_output_script_hash, expected_next_output_script_hash));
45
+ }
46
+
47
+ fn main() {
48
+ require_definition_anchor();
49
+ require_state_anchor();
50
+ require_policy_hash_anchor();
51
+ require_required_mode();
52
+ let next_policy_hash: u256 = witness::NEXT_POLICY_HASH;
53
+ let next_output_descriptor_hash: u256 = witness::NEXT_OUTPUT_DESCRIPTOR_HASH;
54
+ let expected_next_output_script_hash: u256 = witness::EXPECTED_NEXT_OUTPUT_SCRIPT_HASH;
55
+ require_next_transition_witness(next_policy_hash, next_output_descriptor_hash);
56
+ require_output_shape(expected_next_output_script_hash);
57
+ jet::check_lock_distance({{LOCK_DISTANCE}});
58
+ let signer: Pubkey = 0x{{SIGNER_XONLY}};
59
+ jet::bip_0340_verify((signer, jet::sig_all_hash()), witness::SIGNER_SIGNATURE)
60
+ }
@@ -0,0 +1,88 @@
1
+ /*
2
+ * Recursive delay policy state contract for optional / terminating propagation.
3
+ *
4
+ * The current recipient can spend only after the configured relative delay.
5
+ * In optional mode, callers may either exit plainly or provide witness values
6
+ * that bind the next constrained output script hash in the same transaction.
7
+ */
8
+ fn not(bit: bool) -> bool {
9
+ <u1>::into(jet::complement_1(<bool>::into(bit)))
10
+ }
11
+
12
+ fn require_definition_anchor() {
13
+ let anchored_definition_hash: u256 = 0x{{DEFINITION_HASH}};
14
+ let zero_hash: u256 = 0x0000000000000000000000000000000000000000000000000000000000000000;
15
+ assert!(not(jet::eq_256(anchored_definition_hash, zero_hash)));
16
+ }
17
+
18
+ fn require_state_anchor() {
19
+ let anchored_state_hash: u256 = 0x{{STATE_HASH}};
20
+ let zero_hash: u256 = 0x0000000000000000000000000000000000000000000000000000000000000000;
21
+ assert!(not(jet::eq_256(anchored_state_hash, zero_hash)));
22
+ }
23
+
24
+ fn require_policy_hash_anchor() {
25
+ let anchored_policy_hash: u256 = 0x{{POLICY_HASH}};
26
+ let zero_hash: u256 = 0x0000000000000000000000000000000000000000000000000000000000000000;
27
+ assert!(not(jet::eq_256(anchored_policy_hash, zero_hash)));
28
+ }
29
+
30
+ fn require_next_transition_witness(next_policy_hash: u256, next_output_descriptor_hash: u256) {
31
+ let zero_hash: u256 = 0x0000000000000000000000000000000000000000000000000000000000000000;
32
+ assert!(not(jet::eq_256(next_policy_hash, zero_hash)));
33
+ assert!(not(jet::eq_256(next_output_descriptor_hash, zero_hash)));
34
+ }
35
+
36
+ fn maybe_require_recursive_branch(
37
+ next_policy_hash: u256,
38
+ next_output_descriptor_hash: u256,
39
+ expected_next_output_hash: u256,
40
+ expected_next_output_script_hash: u256
41
+ ) {
42
+ match jet::eq_8({{PROPAGATION_MODE_8}}, 2) {
43
+ true => {
44
+ let zero_hash: u256 = 0x0000000000000000000000000000000000000000000000000000000000000000;
45
+ match not(jet::eq_256(expected_next_output_script_hash, zero_hash)) {
46
+ true => {
47
+ require_next_transition_witness(next_policy_hash, next_output_descriptor_hash);
48
+ assert!(jet::eq_32(jet::num_outputs(), 2));
49
+ assert!(unwrap(jet::output_is_fee(1)));
50
+ match not(jet::eq_256(expected_next_output_hash, zero_hash)) {
51
+ true => {
52
+ let actual_next_output_hash: u256 = match jet::output_hash(0) {
53
+ Some(output_hash : u256) => output_hash,
54
+ None => panic!(),
55
+ };
56
+ assert!(jet::eq_256(actual_next_output_hash, expected_next_output_hash));
57
+ },
58
+ false => {
59
+ let actual_next_output_script_hash: u256 = unwrap(jet::output_script_hash(0));
60
+ assert!(jet::eq_256(actual_next_output_script_hash, expected_next_output_script_hash));
61
+ },
62
+ }
63
+ },
64
+ false => {},
65
+ }
66
+ },
67
+ false => {},
68
+ }
69
+ }
70
+
71
+ fn main() {
72
+ require_definition_anchor();
73
+ require_state_anchor();
74
+ require_policy_hash_anchor();
75
+ let next_policy_hash: u256 = witness::NEXT_POLICY_HASH;
76
+ let next_output_descriptor_hash: u256 = witness::NEXT_OUTPUT_DESCRIPTOR_HASH;
77
+ let expected_next_output_hash: u256 = witness::EXPECTED_NEXT_OUTPUT_HASH;
78
+ let expected_next_output_script_hash: u256 = witness::EXPECTED_NEXT_OUTPUT_SCRIPT_HASH;
79
+ maybe_require_recursive_branch(
80
+ next_policy_hash,
81
+ next_output_descriptor_hash,
82
+ expected_next_output_hash,
83
+ expected_next_output_script_hash
84
+ );
85
+ jet::check_lock_distance({{LOCK_DISTANCE}});
86
+ let signer: Pubkey = 0x{{SIGNER_XONLY}};
87
+ jet::bip_0340_verify((signer, jet::sig_all_hash()), witness::SIGNER_SIGNATURE)
88
+ }
@@ -0,0 +1,72 @@
1
+ /*
2
+ * Recursive delay policy state contract for required propagation.
3
+ *
4
+ * The current recipient can spend only after the configured relative delay,
5
+ * and only into the next constrained output shape supplied at execution time.
6
+ */
7
+ fn not(bit: bool) -> bool {
8
+ <u1>::into(jet::complement_1(<bool>::into(bit)))
9
+ }
10
+
11
+ fn require_definition_anchor() {
12
+ let anchored_definition_hash: u256 = 0x{{DEFINITION_HASH}};
13
+ let zero_hash: u256 = 0x0000000000000000000000000000000000000000000000000000000000000000;
14
+ assert!(not(jet::eq_256(anchored_definition_hash, zero_hash)));
15
+ }
16
+
17
+ fn require_state_anchor() {
18
+ let anchored_state_hash: u256 = 0x{{STATE_HASH}};
19
+ let zero_hash: u256 = 0x0000000000000000000000000000000000000000000000000000000000000000;
20
+ assert!(not(jet::eq_256(anchored_state_hash, zero_hash)));
21
+ }
22
+
23
+ fn require_policy_hash_anchor() {
24
+ let anchored_policy_hash: u256 = 0x{{POLICY_HASH}};
25
+ let zero_hash: u256 = 0x0000000000000000000000000000000000000000000000000000000000000000;
26
+ assert!(not(jet::eq_256(anchored_policy_hash, zero_hash)));
27
+ }
28
+
29
+ fn require_required_mode() {
30
+ assert!(jet::eq_8({{PROPAGATION_MODE_8}}, 1));
31
+ }
32
+
33
+ fn require_next_transition_witness(next_policy_hash: u256, next_output_descriptor_hash: u256) {
34
+ let zero_hash: u256 = 0x0000000000000000000000000000000000000000000000000000000000000000;
35
+ assert!(not(jet::eq_256(next_policy_hash, zero_hash)));
36
+ assert!(not(jet::eq_256(next_output_descriptor_hash, zero_hash)));
37
+ }
38
+
39
+ fn require_output_shape(expected_next_output_hash: u256, expected_next_output_script_hash: u256) {
40
+ assert!(jet::eq_32(jet::num_outputs(), 2));
41
+ assert!(unwrap(jet::output_is_fee(1)));
42
+ let zero_hash: u256 = 0x0000000000000000000000000000000000000000000000000000000000000000;
43
+ match not(jet::eq_256(expected_next_output_hash, zero_hash)) {
44
+ true => {
45
+ let actual_next_output_hash: u256 = match jet::output_hash(0) {
46
+ Some(output_hash : u256) => output_hash,
47
+ None => panic!(),
48
+ };
49
+ assert!(jet::eq_256(actual_next_output_hash, expected_next_output_hash));
50
+ },
51
+ false => {
52
+ let actual_next_output_script_hash: u256 = unwrap(jet::output_script_hash(0));
53
+ assert!(jet::eq_256(actual_next_output_script_hash, expected_next_output_script_hash));
54
+ },
55
+ }
56
+ }
57
+
58
+ fn main() {
59
+ require_definition_anchor();
60
+ require_state_anchor();
61
+ require_policy_hash_anchor();
62
+ require_required_mode();
63
+ let next_policy_hash: u256 = witness::NEXT_POLICY_HASH;
64
+ let next_output_descriptor_hash: u256 = witness::NEXT_OUTPUT_DESCRIPTOR_HASH;
65
+ let expected_next_output_hash: u256 = witness::EXPECTED_NEXT_OUTPUT_HASH;
66
+ let expected_next_output_script_hash: u256 = witness::EXPECTED_NEXT_OUTPUT_SCRIPT_HASH;
67
+ require_next_transition_witness(next_policy_hash, next_output_descriptor_hash);
68
+ require_output_shape(expected_next_output_hash, expected_next_output_script_hash);
69
+ jet::check_lock_distance({{LOCK_DISTANCE}});
70
+ let signer: Pubkey = 0x{{SIGNER_XONLY}};
71
+ jet::bip_0340_verify((signer, jet::sig_all_hash()), witness::SIGNER_SIGNATURE)
72
+ }
@@ -0,0 +1,83 @@
1
+ /*
2
+ * Recursive delay policy state contract.
3
+ *
4
+ * This contract commits the policy template hash, the concrete policy state hash,
5
+ * and a policy hash that binds recipient + params + propagation mode. The holder
6
+ * can spend only after the configured relative delay.
7
+ *
8
+ * In required propagation mode it also enforces a first hop into the generic
9
+ * recursive policy router machine, so the current state cannot directly exit to
10
+ * a plain address.
11
+ */
12
+ fn not(bit: bool) -> bool {
13
+ <u1>::into(jet::complement_1(<bool>::into(bit)))
14
+ }
15
+
16
+ fn require_definition_anchor() {
17
+ let anchored_definition_hash: u256 = 0x{{DEFINITION_HASH}};
18
+ let zero_hash: u256 = 0x0000000000000000000000000000000000000000000000000000000000000000;
19
+ assert!(not(jet::eq_256(anchored_definition_hash, zero_hash)));
20
+ }
21
+
22
+ fn require_state_anchor() {
23
+ let anchored_state_hash: u256 = 0x{{STATE_HASH}};
24
+ let zero_hash: u256 = 0x0000000000000000000000000000000000000000000000000000000000000000;
25
+ assert!(not(jet::eq_256(anchored_state_hash, zero_hash)));
26
+ }
27
+
28
+ fn require_policy_hash_anchor() {
29
+ let anchored_policy_hash: u256 = 0x{{POLICY_HASH}};
30
+ let zero_hash: u256 = 0x0000000000000000000000000000000000000000000000000000000000000000;
31
+ assert!(not(jet::eq_256(anchored_policy_hash, zero_hash)));
32
+ }
33
+
34
+ fn require_router_machine_anchor() {
35
+ let router_machine_script_hash: u256 = 0x{{ROUTER_MACHINE_SCRIPT_HASH_256}};
36
+ let zero_hash: u256 = 0x0000000000000000000000000000000000000000000000000000000000000000;
37
+ match not(jet::eq_8({{PROPAGATION_MODE_8}}, 3)) {
38
+ true => assert!(not(jet::eq_256(router_machine_script_hash, zero_hash))),
39
+ false => {},
40
+ }
41
+ }
42
+
43
+ fn require_required_machine_hop() {
44
+ match jet::eq_8({{REQUIRE_MACHINE_HOP_8}}, 1) {
45
+ true => {
46
+ assert!(jet::eq_32(jet::num_outputs(), 2));
47
+ assert!(unwrap(jet::output_is_fee(1)));
48
+ let router_machine_script_hash: u256 = 0x{{ROUTER_MACHINE_SCRIPT_HASH_256}};
49
+ let next_output_script_hash: u256 = unwrap(jet::output_script_hash(0));
50
+ assert!(jet::eq_256(router_machine_script_hash, next_output_script_hash));
51
+ },
52
+ false => {},
53
+ }
54
+ }
55
+
56
+ fn require_optional_machine_hop_if_selected() {
57
+ match jet::eq_8({{PROPAGATION_MODE_8}}, 2) {
58
+ true => {
59
+ let router_machine_script_hash: u256 = 0x{{ROUTER_MACHINE_SCRIPT_HASH_256}};
60
+ let next_output_script_hash: u256 = unwrap(jet::output_script_hash(0));
61
+ match jet::eq_256(router_machine_script_hash, next_output_script_hash) {
62
+ true => {
63
+ assert!(jet::eq_32(jet::num_outputs(), 2));
64
+ assert!(unwrap(jet::output_is_fee(1)));
65
+ },
66
+ false => {},
67
+ }
68
+ },
69
+ false => {},
70
+ }
71
+ }
72
+
73
+ fn main() {
74
+ require_definition_anchor();
75
+ require_state_anchor();
76
+ require_policy_hash_anchor();
77
+ require_router_machine_anchor();
78
+ require_required_machine_hop();
79
+ require_optional_machine_hop_if_selected();
80
+ jet::check_lock_distance({{LOCK_DISTANCE}});
81
+ let signer: Pubkey = 0x{{SIGNER_XONLY}};
82
+ jet::bip_0340_verify((signer, jet::sig_all_hash()), witness::SIGNER_SIGNATURE)
83
+ }