Implement PoCW consensus mechanism for ordinary transfers - #15
Open
ABresting wants to merge 12 commits into
Open
Implement PoCW consensus mechanism for ordinary transfers#15ABresting wants to merge 12 commits into
ABresting wants to merge 12 commits into
Conversation
FoldObserver hooks into ConsensusManager after fold commit to compute economic summaries. Sets executed_by on events in tee_executor.
Transfer.burn_fee flows from validator through enclave to runtime. Sender pays amount + burn_fee; recipient gets only amount. Burned flux is destroyed (supply reduction). Zero burn_fee preserves existing behavior.
After fold commit, FoldObserver computes economics and apply_reward_minting
writes cumulative rewards to ROOT subnet SMT under "pocw:reward:{solver_id}"
keys. Rewards accumulate across folds. Adds get_value() to GlobalStateManager
for reading state by key.
5 tasks
ivan-xin
added a commit
to ivan-xin/Setu
that referenced
this pull request
Apr 22, 2026
…e_df_oid
types (new dynamic_field module):
- DfFieldValue { name_type_tag, name_bcs, value_type_tag, value_bcs }
— payload persisted in ObjectEnvelope.data for DF entries (ownership =
ObjectOwner(parent)); BCS-serializable, serde Debug/Clone/Eq
- DfAccessMode enum (Read/Mutate/Create/Delete) for client-declared intent;
JSON shape locked via unit test
- derive_df_oid(parent, name_type_tag, name_bcs) -> ObjectId
— BLAKE3(b"SETU_DF:" || parent || type_tag || 0x00 || bcs); canonical
type tag STRING rather than &TypeTag so types/ keeps its single
internal dep on setu-vlc (G4). VM-side callers pass
TypeTag::to_canonical_string().as_str(). See design.md §3.2 +
implementation-log.md §2 drift note.
- 8 unit tests: deterministic, parent-sensitive, type-tag-sensitive,
bcs-sensitive, empty-bcs edge, preimage-layout lock,
DfFieldValue bcs roundtrip, DfAccessMode JSON shape
types (solver_task.rs — ResolvedInputs extension):
- ResolvedDynamicField { parent_object_id, df_object_id, name_type_tag,
name_bcs, value_bytes: Option<Vec<u8>>, value_type_tag, mode }
- ResolvedInputs.dynamic_fields: Vec<ResolvedDynamicField> with
#[serde(default)] — top-level per v1.3 §3.5 (NOT nested inside
OperationType::MoveCall) so future operations can adopt DF without a
breaking enum layout change
- All 6 constructors (new / transfer / merge_coins / split_coin /
merge_then_transfer / move_call) initialize dynamic_fields: Vec::new()
- 3 unit tests: serde legacy-payload compat (default empty),
ResolvedDynamicField bcs roundtrip (Create + Read modes),
ResolvedInputs.dynamic_fields roundtrip
setu-framework/sources/dynamic_field.move (new stdlib module AdvaitaLabs#15):
- 5 public funs: add / remove / borrow / borrow_mut / exists_
- 5 native forward-declarations (runtime lives in M2)
- 6 error codes: E_FIELD_ALREADY_EXISTS=0, E_FIELD_DOES_NOT_EXIST=1,
E_FIELD_TYPE_MISMATCH=2, E_DF_VALUE_HAS_KEY=3, E_DF_NOT_PRELOADED=100,
E_DF_DUPLICATE_DECLARATION=101
- Ability constraints: K: copy + drop + store; V: store (V: key rejected
at runtime in M2 native since Move signatures cannot express "store !key")
- Compiled to 492-byte dynamic_field.mv via tools/move-compile
setu-move-vm/build.rs:
- stdlib modules 14 -> 15 (added "dynamic_field"); build_stdlib.sh sync
check confirmed green
setu-validator/src/task_preparer/single.rs:954 + setu-enclave/src/mock/mod.rs:934:
- Ownership::ObjectOwner(_) match arm comment clarified from the stale
"/* Move runtime handles */" to explicit DF semantics: "Owned by another
object (e.g. a dynamic field entry). Sender authorization is proxied
through the parent." No code behavior change.
Validation:
- cargo check -p setu-types: clean
- cargo test -p setu-types --lib: 128 passed / 0 failed (incl. 11 new)
- cargo check -p setu-move-vm: clean
- bash scripts/build_stdlib.sh: 15 modules, build.rs in sync
- bash ai/scripts/validate.sh --quick: 2/2 passed (compile + architecture)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Ordinary transfers in the Setu consensus pipeline do not produce causally meaningful work. There is no solver competition, no quality variance, and no downstream computational impact that PoCW can evaluate. The three PoCW scoring signals (distance, necessity, contribution) degenerate when applied to transfers: any correct executor produces an identical result, so there is no meaningful basis for differentiated reward distribution. Given this, the most appropriate economic treatment for ordinary transfers is a flat fee, configurable via
PoCWConfig.transfer_fee(default 21,000), that is deducted from the sender's coin alongside the transfer amount and permanently destroyed, reducing total supply. Fee enforcement occurs within the TEE execution environment: the runtime withdrawsamount + feeatomically, and if the combined total exceeds available balance, the transfer produces zero state changes. This was validated at precise boundary conditions against live validator runs.A fold-time economic observer has been introduced into the consensus pipeline to handle the reward side for solver-executed work. At each fold, the observer aggregates per-event burn and power consumption metrics, then computes per-solver PoCW scores across three DAG-derived signals: depth contribution (position of solver events within the causal chain), necessity (fraction of solver events that are ancestors of the fold's tip events), and gas usage (TEE-attested computational effort). These scores are normalized and used to distribute minted Flux proportionally to participating solvers. Cumulative rewards are persisted in the ROOT subnet's sparse Merkle tree under
pocw:reward:{solver_id}keys, and each event now carries anexecuted_byfield to distinguish the executing solver from the originating validator.The entire economic layer is gated behind
PoCWConfig.enabled. When disabled, the fee defaults to zero, no fold observer executes, no rewards are minted, and all existing behaviour remains unchanged. Configuration is read from environment variables (POCW_ENABLED,POCW_TRANSFER_FEE) via the dotenv support introduced in the companion PR #13. Naming conventions were standardised across the codebase:burn_feewas renamed tofeeas the burn mechanism is an implementation detail, andtransfer_fixed_feewas simplified totransfer_fee.Closes #8
Test plan