Repository navigation
Commit bd1bc68
Add PausableSapient support to Trails intents (#367)
* refactor: remove unused CreateIntentConfigurationWithTimedRefundSapient
The wrapper hardcodes checkpoint=0, which no real caller can use (intent
wallets need a salt-derived checkpoint), and has no production callers
anywhere in the workspace — only its own test and two trails-watchtower
test files exercise it. Callers build the timed-refund sapient leaf
directly via TimedRefundSapientImageHash and pass it to
CreateIntentConfiguration, which remains unchanged.
* feat: add optional payload gate leaf to CreateIntentTree/CreateIntentConfiguration
CreateIntentTree and CreateIntentConfiguration take a new payloadGateLeafNode
parameter: when set, the wallet is satisfied by [calls && payloadGateLeafNode]
signing together (a 2-of-2 subtree that caps the calls' any-address-subdigest
leaves' own, otherwise uncapped, weight) OR by sapientSignerLeafNode,
untouched. This lets a caller gate payload execution behind a revocable
signer (e.g. a pausable contract) while leaving other leaves (e.g. a
timed-refund signer) unaffected. Passing nil preserves the exact legacy tree
shape, so already-derived counterfactual addresses do not change.
* feat: gate sapient signer leaves behind the payload gate too
CreateIntentTree/CreateIntentConfiguration now wrap sapientSignerLeafNode
in its own independent 2-of-2 subtree with payloadGateLeafNode, the same
way the calls leaves already are, when both are provided. A deposit or
timed-refund sapient leaf is a payload-execution path just like the
calls leaves, so withholding the gate leaf's signature blocks it too.
mainSigner is never gated, so the owner can always act (e.g. recover
funds) regardless of the gate's state.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* fix: skip the calls gate when there are no call batches
A sapient-only config (empty calls) left wrapPayloadGate's inner
threshold-1 node wrapping zero protected leaves, producing a NestedLeaf
with a nil Tree that panics on ImageHash or any other tree traversal.
Omit the calls gate entirely when there are no calls to gate, leaving
the separately gated sapient leaf intact.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* fix: cap payloadGateLeaf to weight 1 in wrapPayloadGate
payloadGateLeafNode is an opaque, caller-supplied v3.WalletConfigTree.
Inserted raw, a misweighted or malicious leaf (weight >= 2) could meet
wrapPayloadGate's threshold-2 requirement on its own, with the
protected leaves contributing nothing — silently collapsing "calls &&
gate" down to "gate alone". Wrap it in its own weight-1 nested leaf so
its contribution is capped regardless of its declared weight.
Also rewrites the sapient-leaf-gated signature test to check each
leaf's wiring independently instead of combining two signatures in one
BuildIntentConfigurationSignature call: once the gate leaf alone
already meets the wallet's overall threshold (via the calls gate's
auto-satisfying any-address-subdigest leaf), that combination races
BuildRegularSignature's early-cancellation against collecting the
other signer's signature, an existing behavior unrelated to this fix.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* refactor: merge calls and sapient behind a single payload gate
Share one OR-nest gate (threshold = gateWeight+1) so either group needs the
payload gate's co-signature, without separate per-leaf gates or weight-1 rejection.
* fix: reject WalletConfigTreeNestedLeaf in leafWeight
leafWeight backs wrapPayloadGate's cap on payloadGateLeaf's contribution.
Only terminal leaf types (address, sapient signer) have a weight that
actually bounds what they contribute; a NestedLeaf's declared Weight
doesn't bound its subtree, so accepting it let a caller understate the
gate leaf's real contribution.
* fix: match full signer identity in BuildIntentConfigurationSignature
signingFunc matched signerSignatures by Address only, so two Signer
values sharing an address but differing in IsSapient/ImageHash (e.g. a
payload gate and a sapient signer leaf on the same contract) could
both receive the first same-address signature, leaving one leaf
signed for the wrong image hash.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
* feat: thread payloadGateLeafNode through GetIntentConfigurationSignature
GetIntentConfigurationSignature previously hardcoded nil for the payload
gate leaf when building its intent configuration, so a caller with a
pausable gate configured got a signature for the wrong (ungated) wallet
config. Add the payloadGateLeafNode param, matching
CreateIntentConfiguration's signature, and update all callers.
Add subtests covering GetIntentConfigurationSignature with the gate
alone and with the gate plus a sapient signer leaf.
* fix: embed supplied signatures deterministically in intent config signatures
BuildIntentConfigurationSignature routed pre-collected signatures through
BuildRegularSignature's signing orchestrator, which cancels outstanding
signers once the config threshold looks met. Subdigest leaves report max
weight regardless of payload, so a payload gate signature arriving first
satisfied the threshold and nondeterministically dropped the sapient
signature that recovery of a non-matching payload still needs.
Add WalletConfig.BuildRegularSignatureFromSignatures, which builds the
signature tree directly from the supplied signatures with no orchestration
or cancellation, and use it in BuildIntentConfigurationSignature.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* refactor: replace optional leaf params with functional options
Add IntentConfigOption with WithPayloadGate and WithSapientSigner so
CreateIntentTree, CreateIntentConfiguration and
GetIntentConfigurationSignature take named options instead of adjacent
positional WalletConfigTree params. Future optional leaves become
additive options rather than signature breaks.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* fix: ignore nil IntentConfigOption values
An untyped nil is assignable to the variadic option type, so legacy
calls passing nil for the removed positional leaf params compile and
then panicked at invocation. Skip nil options instead; nil meant "no
leaf" under the positional API and now means "no option", preserving
identical behavior for those callers.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* fix: reject payload gate signer among gated leaves
A gated signer leaf sharing the gate's identity satisfies both sides of
the outer threshold with one signature, letting the gate authorize
alone. Replace leafWeight with signerLeaf, which also returns the
leaf's signer identity, and reject configs where the gate signer
appears among the gated leaves.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* fix: reject payload-matching leaves as payload gate
Payload-matching leaves (subdigest and any-address-subdigest) carry no
signer and match any weight requirement, so one used as the gate would
authorize alone. Report them from signerLeaf with a signerless identity
and maxUint256 weight, and cap the gate weight at maxUint64 so they are
rejected before the threshold conversion can truncate.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* fix: reject typed-nil payload gate leaves
A typed-nil leaf pointer passes the interface nil check, so signerLeaf
dereferenced it and CreateIntentConfiguration panicked instead of
returning an invalid-gate error. Check the concrete pointer for nil in
both signer cases before reading its fields.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* refactor: rename payloadGate to gate
The gate co-signs more than just the payload (e.g. sapient leaves), so drop the payload- prefix from the leaf, option, and helper names.
Co-authored-by: Cursor <cursoragent@cursor.com>
* fix: reject gate signer at any depth in gated subtree
Gated leaves may be nested trees, so check the gate identity against the
full recursive signer set (WalletConfig.Signers) instead of only
top-level terminal leaves.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: Cursor <cursoragent@cursor.com>1 parent 1396641 commit bd1bc68
5 files changed
Lines changed: 758 additions & 128 deletions
File tree
- core/v3
- testutil
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
2096 | 2096 | | |
2097 | 2097 | | |
2098 | 2098 | | |
| 2099 | + | |
| 2100 | + | |
| 2101 | + | |
| 2102 | + | |
| 2103 | + | |
| 2104 | + | |
| 2105 | + | |
| 2106 | + | |
| 2107 | + | |
| 2108 | + | |
| 2109 | + | |
| 2110 | + | |
| 2111 | + | |
| 2112 | + | |
| 2113 | + | |
| 2114 | + | |
| 2115 | + | |
| 2116 | + | |
| 2117 | + | |
| 2118 | + | |
| 2119 | + | |
| 2120 | + | |
| 2121 | + | |
| 2122 | + | |
2099 | 2123 | | |
2100 | 2124 | | |
2101 | 2125 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | 2 | | |
3 | 3 | | |
4 | | - | |
5 | 4 | | |
6 | 5 | | |
7 | 6 | | |
| |||
186 | 185 | | |
187 | 186 | | |
188 | 187 | | |
189 | | - | |
| 188 | + | |
| 189 | + | |
| 190 | + | |
| 191 | + | |
| 192 | + | |
| 193 | + | |
| 194 | + | |
| 195 | + | |
| 196 | + | |
| 197 | + | |
| 198 | + | |
| 199 | + | |
| 200 | + | |
| 201 | + | |
| 202 | + | |
| 203 | + | |
| 204 | + | |
| 205 | + | |
| 206 | + | |
| 207 | + | |
| 208 | + | |
| 209 | + | |
| 210 | + | |
| 211 | + | |
| 212 | + | |
| 213 | + | |
| 214 | + | |
| 215 | + | |
| 216 | + | |
| 217 | + | |
| 218 | + | |
| 219 | + | |
| 220 | + | |
| 221 | + | |
| 222 | + | |
| 223 | + | |
| 224 | + | |
| 225 | + | |
| 226 | + | |
| 227 | + | |
| 228 | + | |
| 229 | + | |
| 230 | + | |
| 231 | + | |
| 232 | + | |
| 233 | + | |
| 234 | + | |
| 235 | + | |
| 236 | + | |
| 237 | + | |
| 238 | + | |
| 239 | + | |
| 240 | + | |
| 241 | + | |
| 242 | + | |
| 243 | + | |
| 244 | + | |
| 245 | + | |
| 246 | + | |
| 247 | + | |
| 248 | + | |
| 249 | + | |
| 250 | + | |
| 251 | + | |
| 252 | + | |
| 253 | + | |
| 254 | + | |
| 255 | + | |
| 256 | + | |
| 257 | + | |
| 258 | + | |
| 259 | + | |
| 260 | + | |
| 261 | + | |
| 262 | + | |
| 263 | + | |
| 264 | + | |
| 265 | + | |
| 266 | + | |
| 267 | + | |
| 268 | + | |
| 269 | + | |
| 270 | + | |
| 271 | + | |
| 272 | + | |
| 273 | + | |
| 274 | + | |
| 275 | + | |
| 276 | + | |
| 277 | + | |
| 278 | + | |
| 279 | + | |
| 280 | + | |
| 281 | + | |
| 282 | + | |
| 283 | + | |
| 284 | + | |
| 285 | + | |
| 286 | + | |
| 287 | + | |
| 288 | + | |
| 289 | + | |
190 | 290 | | |
191 | | - | |
| 291 | + | |
192 | 292 | | |
193 | 293 | | |
194 | 294 | | |
195 | 295 | | |
196 | | - | |
197 | | - | |
198 | | - | |
| 296 | + | |
| 297 | + | |
| 298 | + | |
| 299 | + | |
| 300 | + | |
| 301 | + | |
| 302 | + | |
| 303 | + | |
| 304 | + | |
| 305 | + | |
| 306 | + | |
| 307 | + | |
| 308 | + | |
| 309 | + | |
| 310 | + | |
| 311 | + | |
| 312 | + | |
199 | 313 | | |
200 | 314 | | |
201 | 315 | | |
202 | | - | |
| 316 | + | |
203 | 317 | | |
204 | 318 | | |
205 | 319 | | |
206 | 320 | | |
207 | 321 | | |
208 | | - | |
| 322 | + | |
209 | 323 | | |
210 | 324 | | |
211 | 325 | | |
212 | 326 | | |
213 | 327 | | |
214 | | - | |
| 328 | + | |
215 | 329 | | |
216 | 330 | | |
217 | | - | |
| 331 | + | |
218 | 332 | | |
219 | 333 | | |
220 | 334 | | |
221 | 335 | | |
222 | 336 | | |
223 | | - | |
224 | | - | |
225 | | - | |
| 337 | + | |
| 338 | + | |
| 339 | + | |
| 340 | + | |
| 341 | + | |
| 342 | + | |
| 343 | + | |
| 344 | + | |
| 345 | + | |
| 346 | + | |
226 | 347 | | |
227 | 348 | | |
228 | | - | |
229 | | - | |
| 349 | + | |
| 350 | + | |
| 351 | + | |
| 352 | + | |
| 353 | + | |
| 354 | + | |
| 355 | + | |
| 356 | + | |
230 | 357 | | |
231 | 358 | | |
232 | 359 | | |
| |||
238 | 365 | | |
239 | 366 | | |
240 | 367 | | |
241 | | - | |
242 | | - | |
243 | | - | |
| 368 | + | |
| 369 | + | |
| 370 | + | |
| 371 | + | |
| 372 | + | |
| 373 | + | |
| 374 | + | |
| 375 | + | |
| 376 | + | |
| 377 | + | |
| 378 | + | |
244 | 379 | | |
245 | 380 | | |
246 | 381 | | |
247 | | - | |
| 382 | + | |
| 383 | + | |
| 384 | + | |
248 | 385 | | |
249 | 386 | | |
250 | 387 | | |
251 | 388 | | |
252 | 389 | | |
253 | | - | |
254 | | - | |
255 | | - | |
256 | | - | |
257 | | - | |
| 390 | + | |
| 391 | + | |
| 392 | + | |
| 393 | + | |
258 | 394 | | |
259 | | - | |
260 | 395 | | |
261 | 396 | | |
262 | | - | |
263 | | - | |
264 | | - | |
265 | | - | |
266 | | - | |
267 | | - | |
| 397 | + | |
268 | 398 | | |
269 | | - | |
270 | 399 | | |
271 | 400 | | |
272 | 401 | | |
| |||
284 | 413 | | |
285 | 414 | | |
286 | 415 | | |
287 | | - | |
288 | 416 | | |
| 417 | + | |
289 | 418 | | |
290 | | - | |
| 419 | + | |
| 420 | + | |
291 | 421 | | |
292 | 422 | | |
293 | 423 | | |
| |||
0 commit comments