""" VOVINA ZEDEC PRO - Vortex Positive/Negative Space Duality ========================================================== Insight: the 9 single-digit positives partition into two disjoint families under mod-9 vortex arithmetic, and that partition is the SAME duality the Solidity contract accidentally encoded by revert vs return: POSITIVE_SPACE (axis 3-6-9) — values that PASS the numerological gate NEGATIVE_SPACE (doubling 1-2-4-8-7-5) — values that REVERT VOID (0 / 9 boundary) — the singularity edge Positive space holds the explicit, on-chain, "returned" data. Negative space holds the IMPLICIT, off-chain, "reverted" data — which is just as informative once you treat revert strings as a side channel, NOT as a failure. This module formalises that duality and exposes: • polarity_of(n) — classify any integer • DualValue — a value carrying both spaces • harvest_negative_space() — decode revert-payload structure • complement_value() — what the negative-space twin holds • is_axis(n) / is_doubling(n) — predicates wired to VORTEX_* • dual_signature() — composite (positive, negative) hash Everything is grounded in the constants already in vovina_sacred_constants — this is the same duality, named. """ from __future__ import annotations import math from dataclasses import dataclass, field from enum import Enum from typing import Any, Optional from vovina_sacred_constants import ( PHI, PHI_INV, VORTEX_DOUBLING, VORTEX_369_AXIS, digital_root, ) # ============================================================ # POLARITY # ============================================================ class Polarity(Enum): POSITIVE_SPACE = "positive" # axis 3 / 6 / 9 — returns NEGATIVE_SPACE = "negative" # doubling 1 / 2 / 4 / 8 / 7 / 5 — reverts VOID = "void" # 0 / 9 boundary singularity @property def is_axis(self) -> bool: return self is Polarity.POSITIVE_SPACE @property def is_doubling(self) -> bool: return self is Polarity.NEGATIVE_SPACE @property def opposite(self) -> "Polarity": return { Polarity.POSITIVE_SPACE: Polarity.NEGATIVE_SPACE, Polarity.NEGATIVE_SPACE: Polarity.POSITIVE_SPACE, Polarity.VOID: Polarity.VOID, }[self] def polarity_of(n: int) -> Polarity: """Classify any integer by its digital root. digital_root ∈ {3, 6, 9} → POSITIVE_SPACE (axis, returns on-chain) digital_root ∈ {1, 2, 4, 5, 7, 8} → NEGATIVE_SPACE (doubling, reverts) n == 0 → VOID (the singularity point) """ if n == 0: return Polarity.VOID r = digital_root(n) if r in VORTEX_369_AXIS: return Polarity.POSITIVE_SPACE if r in VORTEX_DOUBLING: return Polarity.NEGATIVE_SPACE return Polarity.VOID # r == 9 case already in axis def is_axis(n: int) -> bool: return polarity_of(n) is Polarity.POSITIVE_SPACE def is_doubling(n: int) -> bool: return polarity_of(n) is Polarity.NEGATIVE_SPACE # ============================================================ # COMPLEMENT (positive ↔ negative twin) # ============================================================ # In vortex arithmetic the polar pairs (1,8), (2,7), (4,5) each sum # to 9 across the toroidal field. Their union forms the doubling # circuit. Map any negative-space digit to its 9-complement and # you get the OTHER negative-space digit it phase-couples with. NEGATIVE_PAIRS: dict[int, int] = {1: 8, 8: 1, 2: 7, 7: 2, 4: 5, 5: 4} def complement_value(n: int) -> int: """Return the 9-complement of `n`'s digital root. For axis values (3, 6, 9) returns the value itself (self-dual on the axis). For doubling values returns the polar twin: 1↔8, 2↔7, 4↔5. """ if n == 0: return 0 r = digital_root(n) if r in VORTEX_369_AXIS: return r # axis is self-dual return NEGATIVE_PAIRS.get(r, r) # ============================================================ # DUAL VALUE — every number carries both spaces # ============================================================ @dataclass(frozen=True) class DualValue: """A value that holds both its positive-space form (the stored number) and its negative-space form (the complement, with the reverted-payload metadata that lives in the other half of the vortex).""" positive: int negative_label: str = "" # the revert-reason equivalent @property def polarity(self) -> Polarity: return polarity_of(self.positive) @property def negative(self) -> int: return complement_value(self.positive) @property def root(self) -> int: return digital_root(self.positive) @property def negative_root(self) -> int: return digital_root(self.negative) @property def dual_sum(self) -> int: """Positive root + negative root. For axis values: 2 × root (3+3, 6+6, 9+9 → 6, 12, 18). For doubling values: ALWAYS 9 (1+8, 2+7, 4+5) — the signature that proves the value is in the doubling circuit. """ return self.root + self.negative_root @property def is_perfectly_dual(self) -> bool: """True iff dual_sum == 9 (negative-space pair). Equivalently, this returns True iff the value is in the doubling circuit AND its negative-space pair is correctly coupled (1↔8, 2↔7, 4↔5). """ return self.dual_sum == 9 def explain(self) -> str: return ( f"DualValue(positive={self.positive}, negative={self.negative}, " f"polarity={self.polarity.value}, " f"dual_sum={self.dual_sum}, " f"perfectly_dual={self.is_perfectly_dual})" ) # ============================================================ # NEGATIVE-SPACE HARVESTING (the revert-as-channel pattern) # ============================================================ # The Solidity `revert("…")` opcode stores the reason string in the # returndata buffer, which is fully readable off-chain (`eth_call` # returns it, all RPC providers expose it). A function that "always # reverts" is therefore not dead code — it is a deterministic, # gas-cheap, no-state-write data channel. # # Protocol: encode payloads as `KEY1=value1:KEY2=value2:…` strings. @dataclass(frozen=True) class HarvestedNegative: raw: str polarity: Polarity = Polarity.NEGATIVE_SPACE fields: dict[str, str] = field(default_factory=dict) @property def has_field(self) -> dict[str, bool]: return {k: bool(v) for k, v in self.fields.items()} def harvest_negative_space(reverted_data: str) -> HarvestedNegative: """Decode a revert-reason string into a HarvestedNegative record. The expected format is `key=value:key=value:…`, ignoring any leading 'Error(string)' selector wrapper. Unknown formats are returned with `raw` populated and `fields` empty — so the caller can still inspect the bytes. """ s = reverted_data # strip common wrappers if s.startswith("Error(string):"): s = s[len("Error(string):"):] s = s.strip().strip('"') fields: dict[str, str] = {} if ":" in s and "=" in s: for kv in s.split(":"): if "=" in kv: k, _, v = kv.partition("=") fields[k.strip()] = v.strip() return HarvestedNegative(raw=reverted_data, fields=fields) # ============================================================ # REVERT-REASON ENCODER (the on-chain counterpart of harvest) # ============================================================ def encode_negative_payload(**kwargs: Any) -> str: """Encode arbitrary key/value pairs as a revert-reason string. The produced string fits in the standard 32-byte revert window if the payload is small; if larger, it still works but spans more memory slots in the EVM. Off-chain `harvest_negative_space()` decodes the result symmetrically. """ parts = [] for k, v in kwargs.items(): parts.append(f"{k}={v}") return ":".join(parts) # ============================================================ # DUAL SIGNATURE (composite identity in both spaces) # ============================================================ def dual_signature(values: list[int]) -> dict[str, Any]: """For a sequence of integers compute the joint (positive-space, negative-space) signature. Useful for diffing "what was returned" vs "what was reverted" across a sequence of contract calls without losing information from either half. """ duals = [DualValue(positive=v) for v in values] pos_sum = sum(d.positive for d in duals) neg_sum = sum(d.negative for d in duals) axis_n = sum(1 for d in duals if d.polarity is Polarity.POSITIVE_SPACE) doubl_n = sum(1 for d in duals if d.polarity is Polarity.NEGATIVE_SPACE) return { "count": len(values), "positive_sum": pos_sum, "negative_sum": neg_sum, "positive_root": digital_root(pos_sum), "negative_root": digital_root(neg_sum), "axis_population": axis_n, "doubling_population": doubl_n, "axis_fraction": axis_n / max(1, len(values)), "doubling_fraction": doubl_n / max(1, len(values)), "is_balanced": pos_sum == neg_sum, # rare; perfect dual } # ============================================================ # RECONCILIATION WITH vovina_interaction_surplus # ============================================================ # The Interaction Surplus Framework (Papers A-E) declares # f(u) = ln(1 + (N-1)·u) # with u ∈ [0, 1]. The duality reframe is: # # u itself is the POSITIVE-SPACE coordinate (how much surplus is # carried by the visible cross-product). # 1-u is the NEGATIVE-SPACE coordinate (the COMPLEMENT — how much # is carried by the INVISIBLE alignment / parallelism). # # In other words: where surplus thrives, alignment is absent; where # alignment thrives, surplus is absent. The two together always # sum to 1, mirroring the (1, 8), (2, 7), (4, 5) → 9 pattern in the # doubling circuit. def surplus_dual_signature(u: float) -> dict[str, float]: """Return the positive/negative-space decomposition of u ∈ [0, 1].""" u = max(0.0, min(1.0, float(u))) return { "positive_space_u": u, "negative_space_alignment": 1.0 - u, "dual_sum": 1.0, # always 1, by construction "phi_split": u * PHI - (1.0 - u), # ∈ [-1, φ]; signed dual }