Skip to content

SDK: restrict Object::set to an output nothing has pinned yet - #224

Open
robknight wants to merge 1 commit into
sdk-statementsfrom
sdk-set-guard
Open

SDK: restrict Object::set to an output nothing has pinned yet#224
robknight wants to merge 1 commit into
sdk-statementsfrom
sdk-set-guard

Conversation

@robknight

@robknight robknight commented Aug 21, 2026

Copy link
Copy Markdown
Collaborator

SDK: only allow Object::set on an output nothing has used yet

set adds entries to an object's dict without advancing the object's ts. That is what makes it cheap: a new object's initial state is a single dict value, checked with DictContains, instead of a chain of transitions costing a wildcard per key.

The catch is that the ts machinery cannot see the change. If an earlier operation already recorded the dict's exact contents, a later set makes that record wrong, and the action fails during proving with nothing to point at the set.

So reject the two cases where a set cannot work:

  • On an input or a mutate. There it writes into the object's pre-state, which the transaction proves against a state root it cannot change.
  • On an output whose contents are already fixed by an update, a statement, an intro pod, or pow_obj_grind. That last one reads a dict without recording an Inst, so it now marks the var it read.

Stack created with GitHub Stacks CLIGive Feedback 💬

`set` writes its literal initializer into the object's dict without advancing
the object's ts, which is what makes it cheap: the initial state of a new
object is one dict value asserted by DictContains, not a chain of transitions
costing a wildcard per key. The cost is that a `set` is invisible to the ts
machinery, so it can retroactively falsify what an earlier operation recorded,
and the action then fails while proving with nothing pointing at the `set`.

Reject the positions where it cannot hold: on an input or a mutate, where it
would write into a pre-state the transaction proves against a state root, and
on an output whose contents an update, a statement, an intro pod or
`pow_obj_grind` already committed to. `pow_obj_grind` is the one operation
that reads a dict while recording no Inst, so it now marks the var it read.

Repeated sets stay allowed. A set only asserts containment, which survives
later inserts, so several in a row are consistent -- `test_cross_read_into_set`
covers that. This drops the README's "forbid multiple Object::set" item, which
asked for something that would break working scripts.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant