@crediolabs/policy-synth 0.2.0 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -4
- package/dist/adapters/interpreter/adapter.d.ts +19 -25
- package/dist/adapters/interpreter/adapter.js +54 -487
- package/dist/errors.d.ts +1 -1
- package/dist/index.d.ts +1 -4
- package/dist/index.js +1 -4
- package/dist/install/build-add-context-rule.d.ts +3 -19
- package/dist/install/build-add-context-rule.js +3 -98
- package/dist/install/build-install-policy.d.ts +4 -53
- package/dist/install/build-install-policy.js +44 -123
- package/dist/install/index.d.ts +0 -2
- package/dist/install/index.js +0 -7
- package/dist/predicate/decode.d.ts +1 -1
- package/dist/predicate/decode.js +2 -70
- package/dist/predicate/encode.js +45 -229
- package/dist/predicate/from-json.js +1 -42
- package/dist/record/decode.js +3 -8
- package/dist/record/freshness.d.ts +17 -11
- package/dist/record/freshness.js +28 -18
- package/dist/review-card/builder.d.ts +4 -3
- package/dist/review-card/builder.js +18 -162
- package/dist/review-card/cross-check.js +2 -105
- package/dist/review-card/render-leaf.d.ts +4 -0
- package/dist/review-card/render-leaf.js +47 -0
- package/dist/run/index.d.ts +36 -139
- package/dist/run/index.js +125 -437
- package/dist/run/schemas.d.ts +168 -1929
- package/dist/run/schemas.js +40 -269
- package/dist/{synth → simulate}/deny-cases.d.ts +4 -8
- package/dist/simulate/deny-cases.js +282 -0
- package/dist/simulate/evaluate.d.ts +18 -0
- package/dist/simulate/evaluate.js +271 -0
- package/dist/simulate/index.d.ts +4 -0
- package/dist/simulate/index.js +8 -0
- package/dist/synth/compose-from-recording.d.ts +24 -51
- package/dist/synth/compose-from-recording.js +120 -282
- package/dist/synth/index.d.ts +0 -5
- package/dist/synth/index.js +0 -5
- package/dist/synth/synthesize-from-recording.d.ts +1 -29
- package/dist/synth/synthesize-from-recording.js +41 -356
- package/dist/types.d.ts +8 -60
- package/dist/types.js +5 -2
- package/dist-cjs/adapters/interpreter/adapter.d.ts +19 -25
- package/dist-cjs/adapters/interpreter/adapter.js +56 -489
- package/dist-cjs/errors.d.ts +1 -1
- package/dist-cjs/index.d.ts +1 -4
- package/dist-cjs/index.js +1 -4
- package/dist-cjs/install/build-add-context-rule.d.ts +3 -19
- package/dist-cjs/install/build-add-context-rule.js +1 -97
- package/dist-cjs/install/build-install-policy.d.ts +4 -53
- package/dist-cjs/install/build-install-policy.js +44 -122
- package/dist-cjs/install/index.d.ts +0 -2
- package/dist-cjs/install/index.js +2 -23
- package/dist-cjs/predicate/decode.d.ts +1 -1
- package/dist-cjs/predicate/decode.js +2 -70
- package/dist-cjs/predicate/encode.js +45 -229
- package/dist-cjs/predicate/from-json.js +1 -42
- package/dist-cjs/record/decode.js +3 -8
- package/dist-cjs/record/freshness.d.ts +17 -11
- package/dist-cjs/record/freshness.js +28 -18
- package/dist-cjs/review-card/builder.d.ts +4 -3
- package/dist-cjs/review-card/builder.js +23 -167
- package/dist-cjs/review-card/cross-check.js +7 -110
- package/dist-cjs/review-card/render-leaf.d.ts +4 -0
- package/dist-cjs/review-card/render-leaf.js +52 -0
- package/dist-cjs/run/index.d.ts +36 -139
- package/dist-cjs/run/index.js +125 -444
- package/dist-cjs/run/schemas.d.ts +168 -1929
- package/dist-cjs/run/schemas.js +41 -270
- package/dist-cjs/{synth → simulate}/deny-cases.d.ts +4 -8
- package/dist-cjs/simulate/deny-cases.js +286 -0
- package/dist-cjs/simulate/evaluate.d.ts +18 -0
- package/dist-cjs/simulate/evaluate.js +274 -0
- package/dist-cjs/simulate/index.d.ts +4 -0
- package/dist-cjs/simulate/index.js +13 -0
- package/dist-cjs/synth/compose-from-recording.d.ts +24 -51
- package/dist-cjs/synth/compose-from-recording.js +120 -282
- package/dist-cjs/synth/index.d.ts +0 -5
- package/dist-cjs/synth/index.js +1 -11
- package/dist-cjs/synth/synthesize-from-recording.d.ts +1 -29
- package/dist-cjs/synth/synthesize-from-recording.js +39 -354
- package/dist-cjs/types.d.ts +8 -60
- package/dist-cjs/types.js +6 -3
- package/package.json +5 -5
- package/src/adapters/interpreter/adapter.ts +76 -572
- package/src/errors.ts +0 -19
- package/src/index.ts +1 -4
- package/src/install/build-add-context-rule.ts +5 -139
- package/src/install/build-install-policy.ts +93 -214
- package/src/install/index.ts +0 -34
- package/src/predicate/decode.ts +2 -70
- package/src/predicate/encode.ts +49 -261
- package/src/predicate/from-json.ts +1 -43
- package/src/record/decode.ts +3 -8
- package/src/record/freshness.ts +29 -18
- package/src/review-card/builder.ts +19 -168
- package/src/review-card/cross-check.ts +3 -105
- package/src/review-card/render-leaf.ts +48 -0
- package/src/run/index.ts +144 -572
- package/src/run/schemas.ts +42 -291
- package/src/simulate/deny-cases.ts +334 -0
- package/src/simulate/evaluate.ts +284 -0
- package/src/simulate/index.ts +11 -0
- package/src/synth/compose-from-recording.ts +148 -347
- package/src/synth/index.ts +0 -13
- package/src/synth/synthesize-from-recording.ts +43 -456
- package/src/types.ts +13 -49
- package/dist/adapters/interpreter/index.d.ts +0 -1
- package/dist/adapters/interpreter/index.js +0 -2
- package/dist/adapters/oz/adapter.d.ts +0 -20
- package/dist/adapters/oz/adapter.js +0 -295
- package/dist/adapters/oz/index.d.ts +0 -1
- package/dist/adapters/oz/index.js +0 -2
- package/dist/codegen/compile-gate.d.ts +0 -33
- package/dist/codegen/compile-gate.js +0 -124
- package/dist/codegen/index.d.ts +0 -2
- package/dist/codegen/index.js +0 -8
- package/dist/codegen/template.d.ts +0 -18
- package/dist/codegen/template.js +0 -148
- package/dist/install/authority-overlap.d.ts +0 -134
- package/dist/install/authority-overlap.js +0 -0
- package/dist/install/build-install-predicate.d.ts +0 -96
- package/dist/install/build-install-predicate.js +0 -444
- package/dist/install/build-merge-policy.d.ts +0 -70
- package/dist/install/build-merge-policy.js +0 -130
- package/dist/install/plan-merge-policy.d.ts +0 -49
- package/dist/install/plan-merge-policy.js +0 -86
- package/dist/install/read-account-rules.d.ts +0 -100
- package/dist/install/read-account-rules.js +0 -283
- package/dist/ir/index.d.ts +0 -1
- package/dist/ir/index.js +0 -2
- package/dist/ir/types.d.ts +0 -140
- package/dist/ir/types.js +0 -11
- package/dist/mandate/index.d.ts +0 -2
- package/dist/mandate/index.js +0 -2
- package/dist/mandate/to-ir.d.ts +0 -3
- package/dist/mandate/to-ir.js +0 -60
- package/dist/mandate/types.d.ts +0 -20
- package/dist/mandate/types.js +0 -8
- package/dist/seams/index.d.ts +0 -1
- package/dist/seams/index.js +0 -2
- package/dist/seams/types.d.ts +0 -66
- package/dist/seams/types.js +0 -11
- package/dist/synth/deny-cases.js +0 -562
- package/dist/synth/evaluate.d.ts +0 -39
- package/dist/synth/evaluate.js +0 -551
- package/dist/synth/harness.d.ts +0 -28
- package/dist/synth/harness.js +0 -47
- package/dist/synth/minimize.d.ts +0 -4
- package/dist/synth/minimize.js +0 -38
- package/dist/synth/permit-context.d.ts +0 -15
- package/dist/synth/permit-context.js +0 -116
- package/dist/synth/predicate-literals.d.ts +0 -5
- package/dist/synth/predicate-literals.js +0 -25
- package/dist/synth/synthesize-from-mandate.d.ts +0 -20
- package/dist/synth/synthesize-from-mandate.js +0 -59
- package/dist/verify/envelope.d.ts +0 -15
- package/dist/verify/envelope.js +0 -22
- package/dist/verify/index.d.ts +0 -3
- package/dist/verify/index.js +0 -3
- package/dist/verify/simulate.d.ts +0 -31
- package/dist/verify/simulate.js +0 -258
- package/dist/verify/verify.d.ts +0 -21
- package/dist/verify/verify.js +0 -189
- package/dist-cjs/adapters/interpreter/index.d.ts +0 -1
- package/dist-cjs/adapters/interpreter/index.js +0 -8
- package/dist-cjs/adapters/oz/adapter.d.ts +0 -20
- package/dist-cjs/adapters/oz/adapter.js +0 -300
- package/dist-cjs/adapters/oz/index.d.ts +0 -1
- package/dist-cjs/adapters/oz/index.js +0 -8
- package/dist-cjs/codegen/compile-gate.d.ts +0 -33
- package/dist-cjs/codegen/compile-gate.js +0 -128
- package/dist-cjs/codegen/index.d.ts +0 -2
- package/dist-cjs/codegen/index.js +0 -14
- package/dist-cjs/codegen/template.d.ts +0 -18
- package/dist-cjs/codegen/template.js +0 -151
- package/dist-cjs/install/authority-overlap.d.ts +0 -134
- package/dist-cjs/install/authority-overlap.js +0 -0
- package/dist-cjs/install/build-install-predicate.d.ts +0 -96
- package/dist-cjs/install/build-install-predicate.js +0 -479
- package/dist-cjs/install/build-merge-policy.d.ts +0 -70
- package/dist-cjs/install/build-merge-policy.js +0 -134
- package/dist-cjs/install/plan-merge-policy.d.ts +0 -49
- package/dist-cjs/install/plan-merge-policy.js +0 -90
- package/dist-cjs/install/read-account-rules.d.ts +0 -100
- package/dist-cjs/install/read-account-rules.js +0 -296
- package/dist-cjs/ir/index.d.ts +0 -1
- package/dist-cjs/ir/index.js +0 -3
- package/dist-cjs/ir/types.d.ts +0 -140
- package/dist-cjs/ir/types.js +0 -12
- package/dist-cjs/mandate/index.d.ts +0 -2
- package/dist-cjs/mandate/index.js +0 -6
- package/dist-cjs/mandate/to-ir.d.ts +0 -3
- package/dist-cjs/mandate/to-ir.js +0 -63
- package/dist-cjs/mandate/types.d.ts +0 -20
- package/dist-cjs/mandate/types.js +0 -9
- package/dist-cjs/seams/index.d.ts +0 -1
- package/dist-cjs/seams/index.js +0 -3
- package/dist-cjs/seams/types.d.ts +0 -66
- package/dist-cjs/seams/types.js +0 -12
- package/dist-cjs/synth/deny-cases.js +0 -568
- package/dist-cjs/synth/evaluate.d.ts +0 -39
- package/dist-cjs/synth/evaluate.js +0 -554
- package/dist-cjs/synth/harness.d.ts +0 -28
- package/dist-cjs/synth/harness.js +0 -50
- package/dist-cjs/synth/minimize.d.ts +0 -4
- package/dist-cjs/synth/minimize.js +0 -41
- package/dist-cjs/synth/permit-context.d.ts +0 -15
- package/dist-cjs/synth/permit-context.js +0 -119
- package/dist-cjs/synth/predicate-literals.d.ts +0 -5
- package/dist-cjs/synth/predicate-literals.js +0 -28
- package/dist-cjs/synth/synthesize-from-mandate.d.ts +0 -20
- package/dist-cjs/synth/synthesize-from-mandate.js +0 -62
- package/dist-cjs/verify/envelope.d.ts +0 -15
- package/dist-cjs/verify/envelope.js +0 -23
- package/dist-cjs/verify/index.d.ts +0 -3
- package/dist-cjs/verify/index.js +0 -8
- package/dist-cjs/verify/simulate.d.ts +0 -31
- package/dist-cjs/verify/simulate.js +0 -261
- package/dist-cjs/verify/verify.d.ts +0 -21
- package/dist-cjs/verify/verify.js +0 -192
- package/src/adapters/interpreter/index.ts +0 -8
- package/src/adapters/oz/adapter.ts +0 -376
- package/src/adapters/oz/index.ts +0 -9
- package/src/codegen/compile-gate.ts +0 -167
- package/src/codegen/index.ts +0 -17
- package/src/codegen/template.ts +0 -165
- package/src/install/authority-overlap.ts +0 -0
- package/src/install/build-merge-policy.ts +0 -219
- package/src/install/plan-merge-policy.ts +0 -133
- package/src/install/read-account-rules.ts +0 -376
- package/src/ir/index.ts +0 -13
- package/src/ir/types.ts +0 -132
- package/src/mandate/index.ts +0 -4
- package/src/mandate/to-ir.ts +0 -71
- package/src/mandate/types.ts +0 -21
- package/src/seams/index.ts +0 -11
- package/src/seams/types.ts +0 -81
- package/src/synth/deny-cases.ts +0 -663
- package/src/synth/evaluate.ts +0 -613
- package/src/synth/harness.ts +0 -68
- package/src/synth/minimize.ts +0 -48
- package/src/synth/permit-context.ts +0 -136
- package/src/synth/predicate-literals.ts +0 -27
- package/src/synth/synthesize-from-mandate.ts +0 -82
- package/src/verify/envelope.ts +0 -28
- package/src/verify/index.ts +0 -5
- package/src/verify/simulate.ts +0 -311
- package/src/verify/verify.ts +0 -243
|
@@ -8,8 +8,8 @@ export interface BuildAddContextRuleArgs {
|
|
|
8
8
|
* admin session. The deployer signs the install call via the admin rule
|
|
9
9
|
* already on the account, which is separate from this list. */
|
|
10
10
|
signers: SignerDraft[];
|
|
11
|
-
/** The policy(ies) to attach to the new rule.
|
|
12
|
-
*
|
|
11
|
+
/** The policy(ies) to attach to the new rule. `interpreter` is the only
|
|
12
|
+
* kind: the OpenZeppelin built-in backend was removed. */
|
|
13
13
|
policies: PolicyRef[];
|
|
14
14
|
/** Per-policy install nonce; 1 for a fresh install. */
|
|
15
15
|
installNonce: number;
|
|
@@ -19,19 +19,11 @@ export interface BuildAddContextRuleArgs {
|
|
|
19
19
|
encodedPredicate: string;
|
|
20
20
|
/** Hex sha256 of the canonical predicate XDR bytes. */
|
|
21
21
|
predicateHash: string;
|
|
22
|
-
/** Per-policy oracle overrides. Absent on any key uses the wasm default. */
|
|
23
|
-
oracleParams?: {
|
|
24
|
-
maxStalenessSeconds?: number;
|
|
25
|
-
maxDeviationBps?: number;
|
|
26
|
-
/** Bound between the primary and secondary feeds. Tighten-only against
|
|
27
|
-
* the wasm default, like the other two. */
|
|
28
|
-
maxCrossFeedDeviationBps?: number;
|
|
29
|
-
};
|
|
30
22
|
/** Hard pin to the interpreter's wasm grammar. Refusing here fails closed
|
|
31
23
|
* before the chain does; the contract will refuse a mismatch again. */
|
|
32
24
|
grammarVersion?: number;
|
|
33
25
|
}
|
|
34
|
-
export declare const DEFAULT_GRAMMAR_VERSION:
|
|
26
|
+
export declare const DEFAULT_GRAMMAR_VERSION: 3;
|
|
35
27
|
/** The verb `add_context_rule` takes on the wire. */
|
|
36
28
|
export declare const ADD_CONTEXT_RULE_SYMBOL: "add_context_rule";
|
|
37
29
|
/** Tuple of `ScVal` arguments to pass to `Operation.invokeHostFunction` for
|
|
@@ -46,11 +38,3 @@ export type AddContextRuleArgs = readonly [
|
|
|
46
38
|
/** Build the `add_context_rule` invocation args. Throws a `ToolError`-shaped
|
|
47
39
|
* error on limit breaches or malformed input. */
|
|
48
40
|
export declare function buildAddContextRuleArgs(draft: ContextRuleDraft, args: BuildAddContextRuleArgs): AddContextRuleArgs;
|
|
49
|
-
/** The `PolicyInstallParams` ScVal an interpreter policy receives.
|
|
50
|
-
*
|
|
51
|
-
* Exported so the merge remedy can re-install a policy through `add_policy`
|
|
52
|
-
* using the SAME encoder as a fresh install. Re-implementing it would risk
|
|
53
|
-
* exactly the drift this file warns about: the field order is ABI-significant
|
|
54
|
-
* and a differing encoding yields a rule that denies every call. */
|
|
55
|
-
export type PolicyInstallParamArgs = Pick<BuildAddContextRuleArgs, 'encodedPredicate' | 'predicateHash' | 'installNonce' | 'oracleParams' | 'grammarVersion'>;
|
|
56
|
-
export declare function encodePolicyInstallParams(args: PolicyInstallParamArgs): xdr.ScVal;
|
|
@@ -48,8 +48,8 @@
|
|
|
48
48
|
// the account refuses with `Error(Auth, InvalidAction)`.
|
|
49
49
|
import { createHash } from 'node:crypto';
|
|
50
50
|
import { Address, xdr } from '@stellar/stellar-sdk';
|
|
51
|
-
import { OZ_LIMITS, } from "../types.js";
|
|
52
|
-
export const DEFAULT_GRAMMAR_VERSION =
|
|
51
|
+
import { GRAMMAR_VERSION, OZ_LIMITS, } from "../types.js";
|
|
52
|
+
export const DEFAULT_GRAMMAR_VERSION = GRAMMAR_VERSION;
|
|
53
53
|
/** The verb `add_context_rule` takes on the wire. */
|
|
54
54
|
export const ADD_CONTEXT_RULE_SYMBOL = 'add_context_rule';
|
|
55
55
|
/** Build the `add_context_rule` invocation args. Throws a `ToolError`-shaped
|
|
@@ -65,15 +65,6 @@ export function buildAddContextRuleArgs(draft, args) {
|
|
|
65
65
|
if (args.signers.length === 0 && args.policies.length === 0) {
|
|
66
66
|
throw limitError('INSTALL_BUILD_FAILED', 'a rule with no signers and no policies is refused at install (NoSignersAndPolicies)');
|
|
67
67
|
}
|
|
68
|
-
// OZ's spending_limit caps spend on the CONTEXT CONTRACT - it takes no
|
|
69
|
-
// token argument - so it refuses a Default rule on chain with a bare
|
|
70
|
-
// #3227. Say which rule shape it needs here, before the encoding, rather
|
|
71
|
-
// than letting the user read a numeric trap.
|
|
72
|
-
if (args.policies.some((p) => p.kind === 'oz_builtin' && p.primitive.primitive === 'spending_limit')) {
|
|
73
|
-
if (draft.contextRuleType.kind !== 'call_contract') {
|
|
74
|
-
throw limitError('INSTALL_BUILD_FAILED', `spending_limit caps spend on the rule's context contract, so the rule must be call_contract-scoped to that token - a "${draft.contextRuleType.kind}" rule is refused on chain (#3227)`);
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
68
|
// ---- 2. context_type encoding ----
|
|
78
69
|
const contextType = encodeContextRuleType(draft.contextRuleType);
|
|
79
70
|
// ---- 3. name (string) + valid_until (Option<u32>) ----
|
|
@@ -95,15 +86,6 @@ const POLICY_INSTALL_PARAM_FIELDS = [
|
|
|
95
86
|
'install_nonce',
|
|
96
87
|
'predicate',
|
|
97
88
|
'predicate_hash',
|
|
98
|
-
'oracle_max_staleness_seconds',
|
|
99
|
-
'oracle_max_deviation_bps',
|
|
100
|
-
// Cross-feed divergence bound. A field added to the contract's
|
|
101
|
-
// `PolicyInstallParams` changes the ABI: the host unpacks the map by field
|
|
102
|
-
// count, so omitting one fails the entire install with
|
|
103
|
-
// `Error(Object, UnexpectedSize)` and no indication of which field is
|
|
104
|
-
// missing. The Rust tests build that struct in Rust and never cross this
|
|
105
|
-
// boundary, so only a real install against a deployed contract catches it.
|
|
106
|
-
'oracle_max_xfeed_dev_bps',
|
|
107
89
|
];
|
|
108
90
|
function encodeContextRuleType(rule) {
|
|
109
91
|
switch (rule.kind) {
|
|
@@ -145,76 +127,11 @@ function encodePoliciesMap(args) {
|
|
|
145
127
|
val: encodePolicyInstallParams(args),
|
|
146
128
|
}));
|
|
147
129
|
}
|
|
148
|
-
else if (ref.kind === 'oz_builtin') {
|
|
149
|
-
entries.push(new xdr.ScMapEntry({
|
|
150
|
-
key: Address.fromString(ref.instanceAddress).toScVal(),
|
|
151
|
-
val: encodeOzPrimitiveParams(ref.primitive),
|
|
152
|
-
}));
|
|
153
|
-
}
|
|
154
130
|
}
|
|
155
131
|
entries.sort(sortByScValSymbolString);
|
|
156
132
|
return xdr.ScVal.scvMap(entries);
|
|
157
133
|
}
|
|
158
|
-
|
|
159
|
-
*
|
|
160
|
-
* Field names and types are read from the deployed contracts' own spec:
|
|
161
|
-
* SpendingLimitAccountParams { period_ledgers: u32, spending_limit: i128 }
|
|
162
|
-
* SimpleThresholdAccountParams { threshold: u32 }
|
|
163
|
-
* WeightedThresholdAccountParams { signer_weights: map, threshold: u32 }
|
|
164
|
-
* Entries are symbol-string ordered for the same reason the interpreter's
|
|
165
|
-
* are: the host orders by symbol, not by XDR bytes.
|
|
166
|
-
*/
|
|
167
|
-
function encodeOzPrimitiveParams(primitive) {
|
|
168
|
-
const entries = [];
|
|
169
|
-
const push = (name, val) => entries.push(new xdr.ScMapEntry({ key: xdr.ScVal.scvSymbol(name), val }));
|
|
170
|
-
const p = primitive.params;
|
|
171
|
-
switch (primitive.primitive) {
|
|
172
|
-
case 'spending_limit': {
|
|
173
|
-
const limit = p.spending_limit;
|
|
174
|
-
const period = p.period_ledgers;
|
|
175
|
-
if (typeof limit !== 'string' || typeof period !== 'number') {
|
|
176
|
-
throw limitError('INSTALL_BUILD_FAILED', 'spending_limit needs { spending_limit: string; period_ledgers: number }');
|
|
177
|
-
}
|
|
178
|
-
push('period_ledgers', xdr.ScVal.scvU32(period));
|
|
179
|
-
push('spending_limit', encodeI128(limit));
|
|
180
|
-
break;
|
|
181
|
-
}
|
|
182
|
-
case 'simple_threshold': {
|
|
183
|
-
const threshold = p.threshold;
|
|
184
|
-
if (typeof threshold !== 'number') {
|
|
185
|
-
throw limitError('INSTALL_BUILD_FAILED', 'simple_threshold needs { threshold: number }');
|
|
186
|
-
}
|
|
187
|
-
push('threshold', xdr.ScVal.scvU32(threshold));
|
|
188
|
-
break;
|
|
189
|
-
}
|
|
190
|
-
case 'weighted_threshold': {
|
|
191
|
-
const threshold = p.threshold;
|
|
192
|
-
const weights = p.weights;
|
|
193
|
-
if (typeof threshold !== 'number' || !weights) {
|
|
194
|
-
throw limitError('INSTALL_BUILD_FAILED', 'weighted_threshold needs { threshold: number; weights: Record<address, number> }');
|
|
195
|
-
}
|
|
196
|
-
const weightEntries = Object.entries(weights)
|
|
197
|
-
.map(([addr, w]) => new xdr.ScMapEntry({
|
|
198
|
-
key: Address.fromString(addr).toScVal(),
|
|
199
|
-
val: xdr.ScVal.scvU32(w),
|
|
200
|
-
}))
|
|
201
|
-
.sort((a, b) => (a.key().toXDR('base64') < b.key().toXDR('base64') ? -1 : 1));
|
|
202
|
-
push('signer_weights', xdr.ScVal.scvMap(weightEntries));
|
|
203
|
-
push('threshold', xdr.ScVal.scvU32(threshold));
|
|
204
|
-
break;
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
entries.sort((a, b) => sortBySymbolString(a.key(), b.key()));
|
|
208
|
-
return xdr.ScVal.scvMap(entries);
|
|
209
|
-
}
|
|
210
|
-
function encodeI128(value) {
|
|
211
|
-
const v = BigInt(value);
|
|
212
|
-
return xdr.ScVal.scvI128(new xdr.Int128Parts({
|
|
213
|
-
hi: new xdr.Int64(BigInt.asIntN(64, v >> 64n)),
|
|
214
|
-
lo: new xdr.Uint64(BigInt.asUintN(64, v)),
|
|
215
|
-
}));
|
|
216
|
-
}
|
|
217
|
-
export function encodePolicyInstallParams(args) {
|
|
134
|
+
function encodePolicyInstallParams(args) {
|
|
218
135
|
const predicate = Buffer.from(args.encodedPredicate, 'base64');
|
|
219
136
|
const computedHash = createHash('sha256').update(predicate).digest('hex');
|
|
220
137
|
if (computedHash !== args.predicateHash) {
|
|
@@ -223,15 +140,11 @@ export function encodePolicyInstallParams(args) {
|
|
|
223
140
|
// Per-field value encoders. Each entry returns the ScVal to drop into the
|
|
224
141
|
// map; the key symbol comes from the surrounding loop. Adding a field is
|
|
225
142
|
// one row here plus the symbol in POLICY_INSTALL_PARAM_FIELDS.
|
|
226
|
-
const oracleParams = args.oracleParams;
|
|
227
143
|
const valueFor = {
|
|
228
144
|
grammar_version: () => xdr.ScVal.scvU32(args.grammarVersion ?? DEFAULT_GRAMMAR_VERSION),
|
|
229
145
|
install_nonce: () => xdr.ScVal.scvU32(args.installNonce),
|
|
230
146
|
predicate: () => xdr.ScVal.scvBytes(predicate),
|
|
231
147
|
predicate_hash: () => xdr.ScVal.scvBytes(Buffer.from(args.predicateHash, 'hex')),
|
|
232
|
-
oracle_max_staleness_seconds: () => encodeOptionU32(oracleParams?.maxStalenessSeconds),
|
|
233
|
-
oracle_max_deviation_bps: () => encodeOptionU32(oracleParams?.maxDeviationBps),
|
|
234
|
-
oracle_max_xfeed_dev_bps: () => encodeOptionU32(oracleParams?.maxCrossFeedDeviationBps),
|
|
235
148
|
};
|
|
236
149
|
const entries = POLICY_INSTALL_PARAM_FIELDS.map((k) => new xdr.ScMapEntry({ key: xdr.ScVal.scvSymbol(k), val: valueFor[k]() }));
|
|
237
150
|
// The host orders map entries by the SYMBOL STRING, not by XDR bytes. A
|
|
@@ -241,14 +154,6 @@ export function encodePolicyInstallParams(args) {
|
|
|
241
154
|
entries.sort((a, b) => sortBySymbolString(a.key(), b.key()));
|
|
242
155
|
return xdr.ScVal.scvMap(entries);
|
|
243
156
|
}
|
|
244
|
-
function encodeOptionU32(v) {
|
|
245
|
-
if (v === undefined)
|
|
246
|
-
return xdr.ScVal.scvVoid();
|
|
247
|
-
if (!Number.isFinite(v) || v < 0 || v > 0xffffffff) {
|
|
248
|
-
throw limitError('INSTALL_BUILD_FAILED', `oracle params value ${v} is outside u32 range`);
|
|
249
|
-
}
|
|
250
|
-
return xdr.ScVal.scvU32(v);
|
|
251
|
-
}
|
|
252
157
|
/** Sort host-map keys by their symbol-string form. The host orders map
|
|
253
158
|
* entries by the SYMBOL STRING, not by the key's XDR bytes (a length
|
|
254
159
|
* prefix in the encoding would otherwise put `amount` before `address`).
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { rpc, type Transaction } from '@stellar/stellar-sdk';
|
|
2
|
+
import type { ContextRuleDraft } from '../types.ts';
|
|
3
3
|
/** Minimal Soroban RPC surface the install pipeline needs. Test seams
|
|
4
4
|
* inject a stub so the builder stays deterministic; production builds
|
|
5
5
|
* the real one via `createRpcServer` from `../record/rpc.ts`. */
|
|
@@ -31,20 +31,14 @@ export interface BuildInstallPolicyArgs {
|
|
|
31
31
|
sourceAccount: string;
|
|
32
32
|
/** Network passphrase - pins the hash the auth digest binds. */
|
|
33
33
|
networkPassphrase: string;
|
|
34
|
-
/** The new rule to install.
|
|
35
|
-
rule:
|
|
34
|
+
/** The new rule to install. */
|
|
35
|
+
rule: ContextRuleDraft;
|
|
36
36
|
/** Per-rule install nonce; 1 for a fresh install. */
|
|
37
37
|
installNonce: number;
|
|
38
38
|
/** Already-encoded (base64) canonical ScVal of the predicate. */
|
|
39
39
|
encodedPredicate: string;
|
|
40
40
|
/** Hex sha256 of the canonical predicate XDR bytes. */
|
|
41
41
|
predicateHash: string;
|
|
42
|
-
/** Per-policy oracle overrides. */
|
|
43
|
-
oracleParams?: {
|
|
44
|
-
maxStalenessSeconds?: number;
|
|
45
|
-
maxDeviationBps?: number;
|
|
46
|
-
maxCrossFeedDeviationBps?: number;
|
|
47
|
-
};
|
|
48
42
|
/** Grammar version override; defaults to 1. */
|
|
49
43
|
grammarVersion?: number;
|
|
50
44
|
/** Base fee in stroops; defaults to BASE_FEE (100). */
|
|
@@ -54,41 +48,6 @@ export interface BuildInstallPolicyArgs {
|
|
|
54
48
|
/** Ledger window (in ledgers) for the auth entry's `validUntil`. */
|
|
55
49
|
authValidUntilLedgers?: number;
|
|
56
50
|
}
|
|
57
|
-
export type BuildInstallPolicyRuleDraft = {
|
|
58
|
-
contextRuleType: {
|
|
59
|
-
kind: 'default';
|
|
60
|
-
} | {
|
|
61
|
-
kind: 'call_contract';
|
|
62
|
-
contract: string;
|
|
63
|
-
} | {
|
|
64
|
-
kind: 'create_contract';
|
|
65
|
-
wasmHash: string;
|
|
66
|
-
};
|
|
67
|
-
name: string;
|
|
68
|
-
validUntilLedger: number | null;
|
|
69
|
-
signers: BuildInstallPolicySignerDraft[];
|
|
70
|
-
policies: BuildInstallPolicyPolicyRef[];
|
|
71
|
-
};
|
|
72
|
-
export type BuildInstallPolicySignerDraft = {
|
|
73
|
-
kind: 'delegated';
|
|
74
|
-
address: string;
|
|
75
|
-
} | {
|
|
76
|
-
kind: 'external';
|
|
77
|
-
verifier: string;
|
|
78
|
-
keyBytes: string;
|
|
79
|
-
};
|
|
80
|
-
export type BuildInstallPolicyPolicyRef = {
|
|
81
|
-
kind: 'interpreter';
|
|
82
|
-
interpreterAddress: string;
|
|
83
|
-
predicateBlobBase64: string;
|
|
84
|
-
} | {
|
|
85
|
-
kind: 'oz_builtin';
|
|
86
|
-
instanceAddress: string;
|
|
87
|
-
primitive: {
|
|
88
|
-
primitive: 'spending_limit' | 'simple_threshold' | 'weighted_threshold';
|
|
89
|
-
params: Record<string, unknown>;
|
|
90
|
-
};
|
|
91
|
-
};
|
|
92
51
|
/** Human-readable description of the install call, decoded FROM the built
|
|
93
52
|
* XDR (not from the input args). The XDR is the source of truth: a
|
|
94
53
|
* human approving a review card needs the description to mirror the bytes
|
|
@@ -134,10 +93,6 @@ export interface InstallCallDescribes {
|
|
|
134
93
|
installNonce: number;
|
|
135
94
|
predicateHash: string;
|
|
136
95
|
predicateSha256OfEmbeddedBytes: string;
|
|
137
|
-
} | {
|
|
138
|
-
kind: 'oz_builtin';
|
|
139
|
-
address: string;
|
|
140
|
-
primitive: 'spending_limit' | 'simple_threshold' | 'weighted_threshold';
|
|
141
96
|
}>;
|
|
142
97
|
/** The install nonce, decoded from the interpreter policy's
|
|
143
98
|
* `install_nonce` field. Echoed at the top level for reviewer convenience;
|
|
@@ -217,7 +172,3 @@ export interface BuildRevokePolicyResult {
|
|
|
217
172
|
authValidUntilLedger: number;
|
|
218
173
|
rootInvocationXdr: string;
|
|
219
174
|
}
|
|
220
|
-
/** Re-export so the run-layer does not need to import from
|
|
221
|
-
* build-add-context-rule.ts (keeps the install/ -> install/ dependency
|
|
222
|
-
* direction intact). */
|
|
223
|
-
export { Contract, DEFAULT_GRAMMAR_VERSION };
|
|
@@ -17,8 +17,8 @@
|
|
|
17
17
|
// forwards each install_param to that policy, so the interpreter stores the
|
|
18
18
|
// predicate document as part of this same transaction.
|
|
19
19
|
import { createHash } from 'node:crypto';
|
|
20
|
-
import { Address, BASE_FEE, Contract, Keypair, Operation, rpc, scValToBigInt, TransactionBuilder, xdr, } from '@stellar/stellar-sdk';
|
|
21
|
-
import { buildAddContextRuleArgs
|
|
20
|
+
import { Account, Address, BASE_FEE, Contract, Keypair, Operation, rpc, scValToBigInt, TransactionBuilder, xdr, } from '@stellar/stellar-sdk';
|
|
21
|
+
import { buildAddContextRuleArgs } from "./build-add-context-rule.js";
|
|
22
22
|
import { accountEntry, authDigest, authPayload, delegatedSignerEntry, signaturePayload, } from "./oz-auth.js";
|
|
23
23
|
/** Convert a real rpc.Server into the InstallRpcClient surface. The
|
|
24
24
|
* `getContractVersion` lookup uses `simulateTransaction` against
|
|
@@ -72,73 +72,21 @@ export async function buildInstallPolicyXdr(args) {
|
|
|
72
72
|
name: args.rule.name,
|
|
73
73
|
validUntilLedger: args.rule.validUntilLedger,
|
|
74
74
|
signers: args.rule.signers,
|
|
75
|
-
policies: args.rule.policies
|
|
75
|
+
policies: args.rule.policies,
|
|
76
76
|
}, {
|
|
77
77
|
signers: args.rule.signers,
|
|
78
|
-
policies: args.rule.policies
|
|
78
|
+
policies: args.rule.policies,
|
|
79
79
|
installNonce: args.installNonce,
|
|
80
80
|
encodedPredicate: args.encodedPredicate,
|
|
81
81
|
predicateHash: args.predicateHash,
|
|
82
|
-
...(args.oracleParams ? { oracleParams: args.oracleParams } : {}),
|
|
83
82
|
...(args.grammarVersion !== undefined ? { grammarVersion: args.grammarVersion } : {}),
|
|
84
83
|
});
|
|
85
|
-
// 2.
|
|
86
|
-
// bare host call. The recording pass assigns the smart-account auth nonce
|
|
87
|
-
// and root invocation needed to construct OZ's AuthPayload.
|
|
88
|
-
const source = await args.rpc.getAccount(args.sourceAccount);
|
|
89
|
-
const hostFunction = xdr.HostFunction.hostFunctionTypeInvokeContract(new xdr.InvokeContractArgs({
|
|
90
|
-
contractAddress: new Address(args.smartAccount).toScAddress(),
|
|
91
|
-
functionName: 'add_context_rule',
|
|
92
|
-
args: [...callArgs],
|
|
93
|
-
}));
|
|
94
|
-
const makeOperation = (auth = []) => Operation.invokeHostFunction({ func: hostFunction, auth });
|
|
95
|
-
const baseFee = args.baseFee !== undefined ? String(args.baseFee) : BASE_FEE;
|
|
96
|
-
const buildTx = (op) => buildUnsignedTx({
|
|
97
|
-
sourceAccount: args.sourceAccount,
|
|
98
|
-
sequence: source.sequenceNumber(),
|
|
99
|
-
fee: baseFee,
|
|
100
|
-
networkPassphrase: args.networkPassphrase,
|
|
101
|
-
op,
|
|
102
|
-
});
|
|
103
|
-
const recordingTx = buildTx(makeOperation());
|
|
104
|
-
// 3. Recording simulation: capture the smart account's nonce and invocation
|
|
105
|
-
// tree. Nothing is signed here.
|
|
106
|
-
const recorded = await args.rpc.simulateTransaction(recordingTx);
|
|
107
|
-
if (rpc.Api.isSimulationError(recorded)) {
|
|
108
|
-
// Short, stable reason. The full `simulateTransaction` error (which
|
|
109
|
-
// carries host + URL detail) stays in the SDK's own logs - never
|
|
110
|
-
// reflected back into a user-facing message where it would
|
|
111
|
-
// reconnoitre the RPC.
|
|
112
|
-
throw new Error('install_policy: simulateTransaction failed');
|
|
113
|
-
}
|
|
114
|
-
const original = (recorded.result?.auth ?? []).find((entry) => entry.credentials().switch().name === 'sorobanCredentialsAddress' &&
|
|
115
|
-
Address.fromScAddress(entry.credentials().address().address()).toString() ===
|
|
116
|
-
args.smartAccount);
|
|
117
|
-
if (!original) {
|
|
118
|
-
throw new Error(`install_policy: no Soroban auth entry for smart account ${args.smartAccount}; this call does not route through the smart account`);
|
|
119
|
-
}
|
|
120
|
-
// 4. `add_context_rule` is authorised by the deploy-time admin rule (rule 0).
|
|
84
|
+
// 2. `add_context_rule` is authorised by the deploy-time admin rule (rule 0).
|
|
121
85
|
// The delegated signer uses source-account credentials, so its signature
|
|
122
86
|
// bytes stay empty and the ordinary transaction-envelope signature covers
|
|
123
87
|
// the call when the consumer signs it.
|
|
124
|
-
const validUntilLedger =
|
|
125
|
-
|
|
126
|
-
const contextRuleIds = [0];
|
|
127
|
-
const digest = authDigest(signaturePayload(args.networkPassphrase, original.credentials().address().nonce(), validUntilLedger, original.rootInvocation()), contextRuleIds);
|
|
128
|
-
const authEntries = [
|
|
129
|
-
accountEntry(original, validUntilLedger, authPayload([args.sourceAccount], contextRuleIds, () => Buffer.alloc(0))),
|
|
130
|
-
...contextRuleIds.map(() => delegatedSignerEntry(args.smartAccount, digest)),
|
|
131
|
-
];
|
|
132
|
-
// 5. Simulate again with the OZ entries already attached. The SDK preserves
|
|
133
|
-
// existing auth during assembly and adds the simulated Soroban footprint +
|
|
134
|
-
// resource fee, yielding a complete unsigned envelope.
|
|
135
|
-
const txWithAuth = buildTx(makeOperation(authEntries));
|
|
136
|
-
const enforcing = await args.rpc.simulateTransaction(txWithAuth);
|
|
137
|
-
if (rpc.Api.isSimulationError(enforcing)) {
|
|
138
|
-
throw new Error('install_policy: auth simulateTransaction failed');
|
|
139
|
-
}
|
|
140
|
-
const finalTx = rpc.assembleTransaction(txWithAuth, enforcing).build();
|
|
141
|
-
// 6. Decode the structured description FROM the final assembled transaction.
|
|
88
|
+
const { finalTx, original, validUntilLedger } = await buildAuthorisedSmartAccountTx(args, 'add_context_rule', [...callArgs], 'install_policy');
|
|
89
|
+
// 3. Decode the structured description FROM the final assembled transaction.
|
|
142
90
|
// The human approval binds to the exact bytes the wallet will sign.
|
|
143
91
|
const describes = decodeInstallCallDescribes(finalTx, args.installNonce);
|
|
144
92
|
return {
|
|
@@ -164,11 +112,39 @@ export async function buildInstallPolicyXdr(args) {
|
|
|
164
112
|
* deployer can revoke. This builder does not pre-check the signer: it would
|
|
165
113
|
* be guessing at a contract it cannot read, and the chain is the authority. */
|
|
166
114
|
export async function buildRevokePolicyXdr(args) {
|
|
115
|
+
// Removal is master-only, so the deploy-time admin rule authorises it. The
|
|
116
|
+
// recorded rootInvocation still includes remove_context_rule(ruleId), binding
|
|
117
|
+
// the auth payload to the exact rule being removed. As with install,
|
|
118
|
+
// source-account credentials carry the delegated signer entry and the
|
|
119
|
+
// consumer supplies only the ordinary envelope signature.
|
|
120
|
+
const { finalTx, original, validUntilLedger } = await buildAuthorisedSmartAccountTx(args, 'remove_context_rule', [xdr.ScVal.scvU32(args.ruleId)], 'revoke_policy');
|
|
121
|
+
return {
|
|
122
|
+
unsignedXdr: finalTx.toEnvelope().toXDR().toString('base64'),
|
|
123
|
+
smartAccount: args.smartAccount,
|
|
124
|
+
sourceAccount: args.sourceAccount,
|
|
125
|
+
call: { contract: args.smartAccount, fn: 'remove_context_rule', ruleId: args.ruleId },
|
|
126
|
+
authNonce: original.credentials().address().nonce().toString(),
|
|
127
|
+
authValidUntilLedger: validUntilLedger,
|
|
128
|
+
rootInvocationXdr: original.rootInvocation().toXDR().toString('base64'),
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
/** ~25 minutes at 5s/ledger. */
|
|
132
|
+
const DEFAULT_AUTH_VALID_UNTIL_LEDGERS = 300;
|
|
133
|
+
// ---- internals ----
|
|
134
|
+
/** Record a bare call to the smart account, attach the deploy-time admin rule's
|
|
135
|
+
* auth entries, and re-simulate to assemble the footprint.
|
|
136
|
+
*
|
|
137
|
+
* Install and revoke differ only in the call they wrap, so they share this
|
|
138
|
+
* spine: the recording pass supplies the auth nonce and root invocation OZ's
|
|
139
|
+
* AuthPayload binds to, and the second simulation adds the Soroban footprint +
|
|
140
|
+
* resource fee. Nothing here is signed. `errorPrefix` names the calling tool in
|
|
141
|
+
* the fail-closed messages so a caller can still tell which call failed. */
|
|
142
|
+
async function buildAuthorisedSmartAccountTx(args, functionName, callArgs, errorPrefix) {
|
|
167
143
|
const source = await args.rpc.getAccount(args.sourceAccount);
|
|
168
144
|
const hostFunction = xdr.HostFunction.hostFunctionTypeInvokeContract(new xdr.InvokeContractArgs({
|
|
169
145
|
contractAddress: new Address(args.smartAccount).toScAddress(),
|
|
170
|
-
functionName
|
|
171
|
-
args:
|
|
146
|
+
functionName,
|
|
147
|
+
args: callArgs,
|
|
172
148
|
}));
|
|
173
149
|
const makeOperation = (auth = []) => Operation.invokeHostFunction({ func: hostFunction, auth });
|
|
174
150
|
const baseFee = args.baseFee !== undefined ? String(args.baseFee) : BASE_FEE;
|
|
@@ -185,19 +161,14 @@ export async function buildRevokePolicyXdr(args) {
|
|
|
185
161
|
// carries host + URL detail) stays in the SDK's own logs - never
|
|
186
162
|
// reflected back into a user-facing message where it would
|
|
187
163
|
// reconnoitre the RPC.
|
|
188
|
-
throw new Error(
|
|
164
|
+
throw new Error(`${errorPrefix}: simulateTransaction failed`);
|
|
189
165
|
}
|
|
190
166
|
const original = (recorded.result?.auth ?? []).find((entry) => entry.credentials().switch().name === 'sorobanCredentialsAddress' &&
|
|
191
167
|
Address.fromScAddress(entry.credentials().address().address()).toString() ===
|
|
192
168
|
args.smartAccount);
|
|
193
169
|
if (!original) {
|
|
194
|
-
throw new Error(
|
|
170
|
+
throw new Error(`${errorPrefix}: no Soroban auth entry for smart account ${args.smartAccount}; this call does not route through the smart account`);
|
|
195
171
|
}
|
|
196
|
-
// Removal is master-only, so the deploy-time admin rule authorises it. The
|
|
197
|
-
// recorded rootInvocation still includes remove_context_rule(ruleId), binding
|
|
198
|
-
// the auth payload to the exact rule being removed. As with install,
|
|
199
|
-
// source-account credentials carry the delegated signer entry and the
|
|
200
|
-
// consumer supplies only the ordinary envelope signature.
|
|
201
172
|
const validUntilLedger = (await args.rpc.getLatestLedger()).sequence +
|
|
202
173
|
(args.authValidUntilLedgers ?? DEFAULT_AUTH_VALID_UNTIL_LEDGERS);
|
|
203
174
|
const contextRuleIds = [0];
|
|
@@ -209,38 +180,12 @@ export async function buildRevokePolicyXdr(args) {
|
|
|
209
180
|
const txWithAuth = buildTx(makeOperation(authEntries));
|
|
210
181
|
const enforcing = await args.rpc.simulateTransaction(txWithAuth);
|
|
211
182
|
if (rpc.Api.isSimulationError(enforcing)) {
|
|
212
|
-
throw new Error(
|
|
213
|
-
}
|
|
214
|
-
const finalTx = rpc.assembleTransaction(txWithAuth, enforcing).build();
|
|
215
|
-
return {
|
|
216
|
-
unsignedXdr: finalTx.toEnvelope().toXDR().toString('base64'),
|
|
217
|
-
smartAccount: args.smartAccount,
|
|
218
|
-
sourceAccount: args.sourceAccount,
|
|
219
|
-
call: { contract: args.smartAccount, fn: 'remove_context_rule', ruleId: args.ruleId },
|
|
220
|
-
authNonce: original.credentials().address().nonce().toString(),
|
|
221
|
-
authValidUntilLedger: validUntilLedger,
|
|
222
|
-
rootInvocationXdr: original.rootInvocation().toXDR().toString('base64'),
|
|
223
|
-
};
|
|
224
|
-
}
|
|
225
|
-
/** ~25 minutes at 5s/ledger. */
|
|
226
|
-
const DEFAULT_AUTH_VALID_UNTIL_LEDGERS = 300;
|
|
227
|
-
// ---- internals ----
|
|
228
|
-
/** Adapter: turn the install-policy wire `PolicyRef` shape into the core
|
|
229
|
-
* `PolicyRef` shape `buildAddContextRuleArgs` expects. Keeps the wire
|
|
230
|
-
* schema hand-rolled + flat (the strict union would need a recursive
|
|
231
|
-
* schema) while delegating to the proven encoder for the actual bytes. */
|
|
232
|
-
function adaptPolicyRef(p) {
|
|
233
|
-
if (p.kind === 'interpreter') {
|
|
234
|
-
return {
|
|
235
|
-
kind: 'interpreter',
|
|
236
|
-
interpreterAddress: p.interpreterAddress,
|
|
237
|
-
predicateBlobBase64: p.predicateBlobBase64,
|
|
238
|
-
};
|
|
183
|
+
throw new Error(`${errorPrefix}: auth simulateTransaction failed`);
|
|
239
184
|
}
|
|
240
185
|
return {
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
186
|
+
finalTx: rpc.assembleTransaction(txWithAuth, enforcing).build(),
|
|
187
|
+
original,
|
|
188
|
+
validUntilLedger,
|
|
244
189
|
};
|
|
245
190
|
}
|
|
246
191
|
/** Build an unsigned Soroban transaction envelope. The `sequence` is
|
|
@@ -294,14 +239,13 @@ function decodeInstallCallDescribes(tx, expectedInstallNonce) {
|
|
|
294
239
|
if (scvArgs.length !== 5) {
|
|
295
240
|
throw new Error(`install_policy: built op has ${scvArgs.length} args, expected 5 (context_type, name, valid_until, signers, policies)`);
|
|
296
241
|
}
|
|
297
|
-
const contextType = scvArgs[0];
|
|
298
242
|
const nameScv = scvArgs[1];
|
|
299
243
|
const validUntilScv = scvArgs[2];
|
|
300
244
|
const signersScv = scvArgs[3];
|
|
301
245
|
const policiesScv = scvArgs[4];
|
|
302
246
|
// The length check above pins these as defined; the local references
|
|
303
247
|
// satisfy noUncheckedIndexedAccess on the accessors below.
|
|
304
|
-
if (!nameScv || !validUntilScv || !signersScv || !policiesScv
|
|
248
|
+
if (!nameScv || !validUntilScv || !signersScv || !policiesScv) {
|
|
305
249
|
throw new Error('install_policy: built op args include an undefined slot despite length check');
|
|
306
250
|
}
|
|
307
251
|
// name
|
|
@@ -382,7 +326,6 @@ function decodeInstallCallDescribes(tx, expectedInstallNonce) {
|
|
|
382
326
|
fields.set(fk.sym().toString(), inner.val());
|
|
383
327
|
}
|
|
384
328
|
// Interpreter policy fields carry grammar_version/install_nonce/predicate.
|
|
385
|
-
// OZ primitives carry spending_limit/period_ledgers/threshold/signers.
|
|
386
329
|
if (fields.has('predicate') || fields.has('grammar_version') || fields.has('install_nonce')) {
|
|
387
330
|
const installNonceScv = fields.get('install_nonce');
|
|
388
331
|
if (installNonceScv?.switch().name !== 'scvU32') {
|
|
@@ -411,21 +354,6 @@ function decodeInstallCallDescribes(tx, expectedInstallNonce) {
|
|
|
411
354
|
observedInstallNonce = installNonce;
|
|
412
355
|
continue;
|
|
413
356
|
}
|
|
414
|
-
// OZ built-in primitive. Distinguish by the parameter shape we
|
|
415
|
-
// emitted; matching one of the three primitives exactly pins the
|
|
416
|
-
// kind we built.
|
|
417
|
-
if (fields.has('spending_limit') && fields.has('period_ledgers')) {
|
|
418
|
-
policies.push({ kind: 'oz_builtin', address, primitive: 'spending_limit' });
|
|
419
|
-
continue;
|
|
420
|
-
}
|
|
421
|
-
if (fields.has('threshold') && fields.has('signer_weights')) {
|
|
422
|
-
policies.push({ kind: 'oz_builtin', address, primitive: 'weighted_threshold' });
|
|
423
|
-
continue;
|
|
424
|
-
}
|
|
425
|
-
if (fields.has('threshold')) {
|
|
426
|
-
policies.push({ kind: 'oz_builtin', address, primitive: 'simple_threshold' });
|
|
427
|
-
continue;
|
|
428
|
-
}
|
|
429
357
|
throw new Error(`install_policy: policies[${address}] value has an unknown field set; the encoder may have drifted`);
|
|
430
358
|
}
|
|
431
359
|
// `observedInstallNonce` is the nonce baked into whichever interpreter
|
|
@@ -454,10 +382,3 @@ function decodeInstallCallDescribes(tx, expectedInstallNonce) {
|
|
|
454
382
|
installNonce,
|
|
455
383
|
};
|
|
456
384
|
}
|
|
457
|
-
/** Re-export so the run-layer does not need to import from
|
|
458
|
-
* build-add-context-rule.ts (keeps the install/ -> install/ dependency
|
|
459
|
-
* direction intact). */
|
|
460
|
-
export { Contract, DEFAULT_GRAMMAR_VERSION };
|
|
461
|
-
// Local re-import to avoid pulling the class from the SDK module path
|
|
462
|
-
// at the top of the file (avoids the unused-import lint).
|
|
463
|
-
import { Account } from '@stellar/stellar-sdk';
|
package/dist/install/index.d.ts
CHANGED
|
@@ -1,3 +1 @@
|
|
|
1
|
-
export { ANY, type AuthorityOverlap, type ContextType, effectiveSelectors, findAuthorityOverlaps, type IntendedInstall, intersectSelectors, type MergeResult, mergeIntoAnd, type ObservedRule, type OverlapSeverity, permittedSelectors, type RuleClass, type Selector, signerKey, } from './authority-overlap.ts';
|
|
2
1
|
export { ADD_CONTEXT_RULE_SYMBOL, type AddContextRuleArgs, type BuildAddContextRuleArgs, buildAddContextRuleArgs, DEFAULT_GRAMMAR_VERSION, } from './build-add-context-rule.ts';
|
|
3
|
-
export { type AccountRuleReader, accountRuleReaderFromServer, type CollectedRules, collectObservedRules, decodeContextRule, decodeContextType, decodeSigner, docLedgerKey, MAX_RULE_ID_SCAN, } from './read-account-rules.ts';
|
package/dist/install/index.js
CHANGED
|
@@ -12,11 +12,4 @@
|
|
|
12
12
|
// Exported here rather than from the package root to keep the root surface
|
|
13
13
|
// about synthesis, and because these are transaction-building primitives whose
|
|
14
14
|
// callers should know they are reaching for them.
|
|
15
|
-
// Cross-rule authority analysis. A caller installing a policy needs to know
|
|
16
|
-
// whether its signers can already reach the same calls through another context
|
|
17
|
-
// rule, because OZ lets the signer name the rule and enforces only that one's
|
|
18
|
-
// policies. Without this, a second, tighter rule reads as a restriction while
|
|
19
|
-
// restricting nothing.
|
|
20
|
-
export { ANY, effectiveSelectors, findAuthorityOverlaps, intersectSelectors, mergeIntoAnd, permittedSelectors, signerKey, } from "./authority-overlap.js";
|
|
21
15
|
export { ADD_CONTEXT_RULE_SYMBOL, buildAddContextRuleArgs, DEFAULT_GRAMMAR_VERSION, } from "./build-add-context-rule.js";
|
|
22
|
-
export { accountRuleReaderFromServer, collectObservedRules, decodeContextRule, decodeContextType, decodeSigner, docLedgerKey, MAX_RULE_ID_SCAN, } from "./read-account-rules.js";
|
|
@@ -2,7 +2,7 @@ import { xdr } from '@stellar/stellar-sdk';
|
|
|
2
2
|
import type { PredicateLeaf, PredicateNode } from '../types.ts';
|
|
3
3
|
/** One leaf. Order of the bare-literal checks mirrors `decode_leaf` in dsl.rs. */
|
|
4
4
|
export declare function decodeLeaf(v: xdr.ScVal): PredicateLeaf;
|
|
5
|
-
/** One node.
|
|
5
|
+
/** One node. The comparison ops wrap two LEAVES. */
|
|
6
6
|
export declare function decodeNode(v: xdr.ScVal): PredicateNode;
|
|
7
7
|
/** Decode a predicate from the wire bytes the interpreter stores.
|
|
8
8
|
*
|