Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 72 additions & 0 deletions research/weave/EIGHT_CIRCLE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
# Weave eight-circle / two-circle candidate

Status: **implemented candidate; asymmetric security not established.**

This construction records the current user-specified boundary without adding a
selection law that has not been supplied.

## Preserved construction

For each raw byte:

- the byte is eight bits;
- one whole circle plus seven derived circles form the full eight-circle key-set state;
- every circle has an exact 720-degree return;
- every circle has its own relationship to space, and that relationship belongs to the
concrete key set rather than to a universal law;
- the full/private key set contains all eight circles;
- a degenerate public view exposes exactly two circles at a time;
- the two public circles produce two transmitted witness bits for each source bit,
therefore one eight-bit byte produces sixteen transmitted bits.

The implementation uses exact rational turns: 0 <= phase < 2, with 1 turn equal to
360 degrees and 2 turns equal to the complete 720-degree return. This is an executable
representation of positions, not a claim that the mathematical circle has finitely
many possible positions.

No rule is imposed for how key sets choose their circle positions, their relations to
space, or which two circles are exposed. Those are construction-instance data.

## Executable object

`stages/eight_circle.py` provides:

- `Circle`: exact 720-degree position, zero/one positions, and key-set-specific space relation;
- `FullKeySet`: exactly eight distinct circles;
- `FullKeySet.degenerate(i, j)`: exactly two-circle public projection;
- `encode_byte`: eight source bits -> sixteen positional witness bits;
- `decode_byte`: full-key-set recovery API;
- raw-byte `encode` / `decode` helpers.

The candidate is deliberately separate from the older transport profile and is not
silently installed as the complete Weave `bind` law.

## Falsification already obtained

The first independent-bit implementation fails the intended asymmetric property.

Because each source bit is independently mapped to one of two public two-bit witnesses,
a holder of the public pair can evaluate the public forward image of 0 and 1 and recover
every source bit by comparison. The test
`test_independent_bit_baseline_is_publicly_bruteforceable` preserves that attack as
required evidence.

Therefore:

[
8 \to 2
]

is implemented as a geometric degeneration, but **independent per-bit projection is
falsified as the cryptographic relation**.

This does not falsify the eight-circle construction. It identifies what the next
construction must actually use: the message-scoped UCHC origin/axis relational state
must couple the eight circles so that the six omitted circles change the recoverable
trajectory rather than merely sitting unused in the private object.

## hmmm

The remaining construction is the coupled UCHC relation itself. No additional policy
decision is introduced here. The next candidate must make the full eight-circle state
causally necessary for inversion and then be attacked.
178 changes: 178 additions & 0 deletions research/weave/stages/eight_circle.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
"""Eight-circle / two-circle positional degeneration candidate.

This module implements only the geometry and byte-expansion candidate now specified
for Weave:

* one byte is eight bits;
* one whole + seven derived circles form the full eight-circle key-set state;
* every circle uses an exact 720-degree return represented as rational turns in [0, 2);
* each circle's relation to space is key-set data, not a universal law;
* a degenerate public key exposes exactly two circles from the eight;
* each plaintext bit produces one public sheet bit per exposed circle, so one byte
produces sixteen transmitted bits.

The construction is deliberately labelled a candidate. The public two-circle map is
small enough to brute-force per bit, and the tests preserve that attack witness. A
message-coupled UCHC origin/axis relation is therefore still required before this can
support an asymmetric-security claim.
"""
from __future__ import annotations

from dataclasses import dataclass
from fractions import Fraction
from typing import Iterable


TURN_720 = Fraction(2, 1)


def _phase(value: Fraction) -> Fraction:
if type(value) is not Fraction:
raise TypeError("circle positions must be exact fractions")
return value % TURN_720


def _bit(value: int) -> int:
if type(value) is not int or value not in (0, 1):
raise TypeError("bit must be integer 0 or 1")
return value


@dataclass(frozen=True)
class Circle:
"""One exact 720-degree circle instance from a concrete key set."""

identity: str
space: Fraction
zero: Fraction
one: Fraction

def __post_init__(self):
if type(self.identity) is not str or not self.identity:
raise ValueError("circle identity required")
object.__setattr__(self, "space", _phase(self.space))
object.__setattr__(self, "zero", _phase(self.zero))
object.__setattr__(self, "one", _phase(self.one))
if self.zero == self.one:
raise ValueError("zero and one positions must remain distinct")

def position(self, bit: int, origin: Fraction) -> Fraction:
"""Exact key-set position relative to this circle's space attachment."""
_bit(bit)
return _phase((self.one if bit else self.zero) - self.space + _phase(origin))
Comment on lines +59 to +62

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Leave the circle-space relation unresolved

When the intended UCHC circle/space relation is anything other than an additive scalar offset, this formula silently replaces it with bit_position - space + origin (mod 2), even though EIGHT_CIRCLE.md says no rule for those relations has been supplied and the existing Weave specification leaves native origin/axis binding open. The resulting round-trip and attack evidence therefore measures an invented geometry; this operation should remain hmmm or be supplied explicitly by a source-backed construction instance.

AGENTS.md reference: AGENTS.md:L22-L26

Useful? React with 👍 / 👎.


def public_sheet(self, bit: int, origin: Fraction) -> int:
"""Degenerate 720->two-sheet witness: first or second visible 360-degree return."""
return 0 if self.position(bit, origin) < 1 else 1


@dataclass(frozen=True)
class FullKeySet:
"""Full/private construction instance: exactly eight circles."""

circles: tuple[Circle, ...]

def __post_init__(self):
if type(self.circles) is not tuple or len(self.circles) != 8:
raise ValueError("full key set requires exactly eight circles")
if any(type(circle) is not Circle for circle in self.circles):
raise TypeError("full key set members must be Circle instances")
identities = tuple(circle.identity for circle in self.circles)
if len(set(identities)) != 8:
raise ValueError("circle identities must be unique")
Comment on lines +80 to +82

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Reject unrelated circles as a derived key set

When callers provide eight arbitrary Circle objects—as the new test fixture does—this constructor accepts them solely because their labels differ, even though nothing identifies one as the whole circle or proves that the other seven derive from it. Consequently, the implementation and receipt report an eight-circle construction while testing only tuple cardinality; because the derivation law is unresolved, this boundary should remain hmmm or require explicit derivation provenance rather than accepting unrelated circles.

AGENTS.md reference: AGENTS.md:L22-L26

Useful? React with 👍 / 👎.


def degenerate(self, left: int, right: int) -> "PublicPair":
if any(type(i) is not int or not 0 <= i < 8 for i in (left, right)):
raise ValueError("public circle indices must be integers in [0, 7]")
if left == right:
raise ValueError("degeneration requires two distinct circles")
return PublicPair((left, right), (self.circles[left], self.circles[right]))


@dataclass(frozen=True)
class PublicPair:
"""Exactly two circles exposed by one public degeneration."""

indices: tuple[int, int]
circles: tuple[Circle, Circle]

def __post_init__(self):
if (type(self.indices) is not tuple or len(self.indices) != 2
or len(set(self.indices)) != 2):
raise ValueError("public degeneration requires exactly two distinct indices")
if type(self.circles) is not tuple or len(self.circles) != 2:
raise ValueError("public degeneration exposes exactly two circles")
if any(type(circle) is not Circle for circle in self.circles):
raise TypeError("public circles must be Circle instances")
Comment on lines +103 to +106

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Require two distinct circles in PublicPair

When PublicPair is instantiated directly, PublicPair((0, 1), (circle, circle)) passes validation and is accepted by encode_byte, so a single circle can masquerade as the promised two-circle public degeneration. Validate distinct circle identities (or prevent direct construction) in addition to distinct indices so the public-pair invariant holds for every accepted encoder input.

Useful? React with 👍 / 👎.


def witness(self, bit: int, origin: Fraction) -> tuple[int, int]:
_bit(bit)
return tuple(circle.public_sheet(bit, origin) for circle in self.circles)


def encode_byte(public: PublicPair, value: int, origin: Fraction) -> tuple[int, ...]:
"""Encode one byte as sixteen public positional witness bits."""
if type(public) is not PublicPair:
raise TypeError("two-circle public key required")
if type(value) is not int or not 0 <= value <= 255:
raise ValueError("value must be one byte")
out: list[int] = []
for shift in range(7, -1, -1):
bit = (value >> shift) & 1
zero = public.witness(0, origin)
one = public.witness(1, origin)
if zero == one:
raise ValueError("two-circle degeneration is ambiguous at this origin")
out.extend(public.witness(bit, origin))
return tuple(out)


def decode_byte(full: FullKeySet, public_indices: tuple[int, int],
witness: Iterable[int], origin: Fraction) -> int:
"""Recover one byte with the full key-set object.

Current candidate recovery consults the same selected circles. This is intentional:
the accompanying attack test demonstrates that this baseline does not yet require
the six hidden circles and therefore cannot establish the intended asymmetric
property.
"""
if type(full) is not FullKeySet:
raise TypeError("full eight-circle key set required")
if type(public_indices) is not tuple or len(public_indices) != 2:
raise ValueError("exactly two public indices required")
public = full.degenerate(*public_indices)
bits = tuple(witness)
if len(bits) != 16 or any(type(bit) is not int or bit not in (0, 1) for bit in bits):
raise ValueError("byte witness must contain exactly sixteen integer bits")

value = 0
zero = public.witness(0, origin)
one = public.witness(1, origin)
if zero == one:
raise ValueError("two-circle degeneration is ambiguous at this origin")
for offset in range(0, 16, 2):
pair = bits[offset:offset + 2]
if pair == zero:
bit = 0
elif pair == one:
bit = 1
else:
raise ValueError("witness is not admitted by this key-set projection")
value = (value << 1) | bit
return value


def encode(data: bytes, public: PublicPair, origin: Fraction) -> tuple[int, ...]:
"""Raw bytes -> exactly twice as many transmitted bits as source bits."""
if type(data) is not bytes:
raise TypeError("raw bytes required")
return tuple(bit for byte in data for bit in encode_byte(public, byte, origin))


def decode(full: FullKeySet, public_indices: tuple[int, int],
witness: Iterable[int], origin: Fraction) -> bytes:
bits = tuple(witness)
if len(bits) % 16:
raise ValueError("ciphertext witness length must be a multiple of sixteen bits")
return bytes(decode_byte(full, public_indices, bits[i:i + 16], origin)
for i in range(0, len(bits), 16))
17 changes: 11 additions & 6 deletions research/weave/test.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#!/usr/bin/env python3
"""Run all local assembly/transport tests and emit an honest source-bound receipt.
"""Run all local assembly/transport/candidate tests and emit an honest source-bound receipt.

Usage: python test.py --receipt /tmp/weave-check.json
No dependency installation or network. Native corpus replay is NOT executed by
Expand Down Expand Up @@ -35,27 +35,32 @@ def main():
after = snapshot()
passed = (result.wasSuccessful() and not result.skipped
and not result.expectedFailures and not result.unexpectedSuccesses
and result.testsRun == 52 and before == after)
and result.testsRun == 58 and before == after)
receipt = {
'schema':'weave.transport-evidence/v1',
'status':'PASSED' if passed else 'FAILED',
'python':platform.python_version(),
'tests':result.testsRun,
'failures':len(result.failures),'errors':len(result.errors),'skipped':len(result.skipped),
'source_unchanged':before == after,
'expected_test_methods':52,
'expected_test_methods':58,
'coverage_status':'WITNESSED' if passed else 'NOT_ACCEPTED',
'source_sha256':hashlib.sha256(json.dumps(before,sort_keys=True,separators=(',',':')).encode()).hexdigest(),
'source_files':before,
'coverage':{'binary_messages':8191,'binary_lengths_inclusive':[0,12],
'assembly_switch_masks':512,'transport_switch_masks':32,
'valid_transport_masks':28,'incompatible_transport_masks':4,
'largest_roundtrip_bytes':65536,'separate_process_roundtrip_bytes':1026},
'largest_roundtrip_bytes':65536,'separate_process_roundtrip_bytes':1026,
'eight_circle_full_members':8,'degenerate_public_members':2,
'candidate_expansion_bits_per_byte':16},
'full_weave':Pipeline().plan(),
'native_corpus_replay':'NOT_EXECUTED: source inspected; no constructed database materialized here',
'native_adapter_tests':'missing-input/source-identity refusal only; not successful real-corpus replay',
'security_observations':['fixed-map recovery succeeds against this transport candidate at 137 bits in 8 queries',
'wrong material can yield wrong plaintext without an authentication error'],
'security_observations':[
'fixed-map recovery succeeds against the older transport candidate at 137 bits in 8 queries',
'wrong material can yield wrong plaintext without an authentication error',
'independent-bit eight-to-two sheet projection is publicly brute-forceable and is preserved only as a falsified baseline'
],
'nonclaim':'No complete native Weave or asymmetric security result; no independent researcher review.'
}
sys.stderr.write(report.getvalue())
Expand Down
102 changes: 102 additions & 0 deletions research/weave/tests/test_eight_circle.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
"""Tests for the explicit eight-circle -> two-circle Weave candidate.

These prove construction properties and preserve the current attack witness. They do
not claim asymmetric security.
"""
from fractions import Fraction
import unittest

from stages.eight_circle import Circle, FullKeySet, encode, decode, encode_byte


def circle(i: int, *, shift: int = 0) -> Circle:
# Exact rational positions over a 720-degree return. 1 turn = 360 degrees.
return Circle(
identity=f"g{i}",
space=Fraction((i * 3 + shift) % 16, 8),
zero=Fraction((i * 3 + shift + 1) % 16, 8),
one=Fraction((i * 3 + shift + 9) % 16, 8),
)


def keyset(*, shift: int = 0) -> FullKeySet:
return FullKeySet(tuple(circle(i, shift=shift) for i in range(8)))


class EightCircleTests(unittest.TestCase):
def test_full_key_is_exactly_eight_and_public_is_exactly_two(self):
full = keyset()
public = full.degenerate(1, 6)
self.assertEqual(len(full.circles), 8)
self.assertEqual(public.indices, (1, 6))
self.assertEqual(len(public.circles), 2)
self.assertEqual(tuple(c.identity for c in public.circles), ("g1", "g6"))
with self.assertRaises(ValueError):
full.degenerate(2, 2)

def test_positions_use_exact_720_degree_return(self):
c = Circle("x", Fraction(15, 8), Fraction(1, 8), Fraction(9, 8))
self.assertEqual(c.position(0, Fraction(1, 4)), Fraction(1, 2))
self.assertEqual(c.position(1, Fraction(1, 4)), Fraction(3, 2))
self.assertEqual(c.position(0, Fraction(9, 4)), Fraction(1, 2))
self.assertEqual(c.public_sheet(0, Fraction(1, 4)), 0)
self.assertEqual(c.public_sheet(1, Fraction(1, 4)), 1)

def test_key_set_space_relations_are_data_not_a_global_rule(self):
origin = Fraction(1, 8)
a = keyset(shift=0).degenerate(0, 1)
b = keyset(shift=5).degenerate(0, 1)
# The API accepts both key sets without privileging either space relation.
self.assertNotEqual(
tuple(c.space for c in a.circles),
tuple(c.space for c in b.circles),
)
self.assertEqual(len(encode_byte(a, 0xA5, origin)), 16)
self.assertEqual(len(encode_byte(b, 0xA5, origin)), 16)

def test_raw_bytes_double_in_bit_length_and_roundtrip(self):
full = keyset()
public = full.degenerate(0, 3)
origin = Fraction(3, 16)
data = bytes(range(256))
witness = encode(data, public, origin)
self.assertEqual(len(witness), len(data) * 16)
self.assertEqual(decode(full, public.indices, witness, origin), data)

def test_malformed_or_nonadmitted_witness_fails(self):
full = keyset()
public = full.degenerate(0, 3)
origin = Fraction(3, 16)
witness = list(encode_byte(public, 0x5A, origin))
# Fixture admits only (0,0) and (1,1); mixed pair is impossible.
witness[0:2] = [0, 1]
with self.assertRaises(ValueError):
decode(full, public.indices, witness, origin)
with self.assertRaises(ValueError):
decode(full, public.indices, (0,) * 15, origin)

def test_independent_bit_baseline_is_publicly_bruteforceable(self):
"""Falsification boundary: two public circles alone decode this baseline.

An attacker can compare each observed two-bit witness with the public forward
images of 0 and 1. Therefore this independent-bit sheet projection is a useful
executable geometry scaffold but NOT the intended asymmetric construction.
The missing requirement is the message-coupled UCHC origin/axis relation in
which the six omitted circles alter the recoverable trajectory.
"""
full = keyset()
public = full.degenerate(2, 7)
origin = Fraction(5, 16)
value = 0xD3
witness = encode_byte(public, value, origin)

recovered = 0
code = {public.witness(bit, origin): bit for bit in (0, 1)}
self.assertEqual(len(code), 2)
for i in range(0, 16, 2):
recovered = (recovered << 1) | code[witness[i:i + 2]]
self.assertEqual(recovered, value)


if __name__ == "__main__":
unittest.main()
Loading