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
20 changes: 20 additions & 0 deletions contracts/shared/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Shared Contract Crypto Formats

Status: placeholder for future implementation.

This folder is reserved for shared Solidity hash helpers once the v0 crypto schemas are reviewed.

Do not add production contract logic here until:

- `crypto/FLOWMEMORY_CRYPTO_SPEC.md` is accepted or revised
- `crypto/TEST_VECTORS.md` has automated checks
- `docs/DECISIONS/2026-05-13-flowmemory-crypto-v0-foundation.md` is accepted or superseded

Expected future contents:

- type hash constants
- pure hash functions for observation ids, receipts, artifact roots, storage commitments, reports, and signatures
- Merkle proof verification for accepted root schemes
- Solidity tests against the JSON vectors

See `RECEIPT_VERIFIER_BOUNDARY.md` for the draft boundary of a future `ReceiptVerifier` adapter.
78 changes: 78 additions & 0 deletions contracts/shared/RECEIPT_VERIFIER_BOUNDARY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
# Future ReceiptVerifier Boundary

Status: draft boundary for issue #28.

This document defines what a future `ReceiptVerifier` contract may verify after FlowMemory v0 schemas are accepted. It is not a contract implementation.

## Why Wait

`ReceiptVerifier` should wait until these schemas are accepted or superseded:

- FlowPulse observation identity
- receipt hashing
- verifier report id
- worker and verifier signature envelopes
- artifact root scheme
- storage receipt commitment format

Premature implementation risks baking in the wrong observation identity or replay domain.

## What A v0 Contract Could Verify

A future contract can safely verify compact, already-derived inputs:

- `observationId` hash recomputation from supplied chain/log metadata
- `eventArgsHash` recomputation from supplied FlowPulse args
- `receiptHash` recomputation from supplied observation and commitment fields
- `artifactRoot` envelope hash recomputation
- Merkle proof verification for accepted root schemes
- `reportId` recomputation from supplied report fields
- EIP-712 digest construction for worker or verifier signatures
- secp256k1 signer recovery, if key registry policy exists

## What A v0 Contract Must Not Claim

A future contract must not claim to verify:

- that `txHash`, `transactionIndex`, or `logIndex` were known during FlowPulse emission
- that a supplied receipt/log is canonical without an accepted chain proof or trusted oracle path
- that off-chain artifact bytes are available forever
- that a URI is short, private, resolvable, or honest
- that a verifier attestation is a trustless proof
- that model output or worker behavior is correct
- that a storage provider will satisfy future retrieval requests

## Required Inputs

Any future adapter should make its trust boundary explicit by accepting already-derived fields:

- `chainId`
- `emittingContract`
- `blockNumber`
- `blockHash`
- `txHash`
- `transactionIndex`
- `logIndex`
- `eventSignature`
- `pulseId`
- `rootfieldId`
- `eventArgsHash`
- `receiptHash`
- `reportId`

The caller, indexer, oracle, or proof system remains responsible for establishing that those fields are canonical.

## Implementation Prerequisites

Before adding Solidity beyond pure helpers:

- accept or revise `crypto/FLOWMEMORY_CRYPTO_SPEC.md`
- automate `crypto/test-vectors/flowpulse-observation-v0.json` validation
- define key registry and verifier set root governance
- decide whether on-chain verification is advisory, challenge evidence, or state-changing
- document gas limits for Merkle verification and signature recovery
- add focused tests for every accepted hash helper

## MVP Recommendation

Keep `ReceiptVerifier` out of production contracts for now. Add pure helper libraries in `contracts/shared/` only after schemas stabilize, then add tests against the JSON vectors. Treat any on-chain adapter as an evidence checker, not as proof of full trustlessness.
3 changes: 3 additions & 0 deletions crypto/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
node_modules/
coverage/
.nyc_output/
198 changes: 198 additions & 0 deletions crypto/ATTESTATIONS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,198 @@
# FlowMemory Attestations And Reports

Status: draft v0.

Attestations are signed envelopes over receipts, artifacts, or reports. They provide accountability. They do not make the system fully trustless.

## Worker Signature Envelope

Type string:

```solidity
FlowMemoryWorkerSignatureV0(bytes32 receiptHash,bytes32 workerId,bytes32 workerKeyId,uint64 workerSequence,uint64 expiresAtUnixMs,bytes32 artifactRoot,bytes32 nonce)
```

Struct hash:

```text
workerStructHash = keccak256(abi.encode(
WORKER_SIGNATURE_TYPEHASH,
receiptHash,
workerId,
workerKeyId,
workerSequence,
expiresAtUnixMs,
artifactRoot,
nonce
))
```

Worker signatures bind an off-chain worker to a receipt and optional artifact root. They do not prove the worker's output is correct.

## Verifier Report V0

Verifier reports are deterministic from their inputs. They should not include nondeterministic prose in the `reportId`.

Type string:

```solidity
FlowMemoryVerifierReportV0(bytes32 reportSchemaHash,bytes32 observationId,bytes32 receiptHash,bytes32 verifierId,bytes32 verifierSetRoot,uint8 status,bytes32 checksRoot,uint64 finalizedBlockNumber,bytes32 finalizedBlockHash,uint16 reportVersion)
```

Hash:

```text
reportId = keccak256(abi.encode(
VERIFIER_REPORT_TYPEHASH,
reportSchemaHash,
observationId,
receiptHash,
verifierId,
verifierSetRoot,
status,
checksRoot,
finalizedBlockNumber,
finalizedBlockHash,
reportVersion
))
```

`checksRoot` commits to a deterministic checks document or Merkle tree of check results.

## Verifier Signature Envelope

Type string:

```solidity
FlowMemoryVerifierSignatureV0(bytes32 reportId,bytes32 verifierId,bytes32 verifierKeyId,bytes32 verifierSetRoot,uint64 issuedAtUnixMs,uint64 expiresAtUnixMs,bytes32 nonce)
```

Struct hash:

```text
verifierStructHash = keccak256(abi.encode(
VERIFIER_SIGNATURE_TYPEHASH,
reportId,
verifierId,
verifierKeyId,
verifierSetRoot,
issuedAtUnixMs,
expiresAtUnixMs,
nonce
))
```

The signature proves a verifier key signed the report id. It does not prove that the report is correct unless users trust the verifier or can independently replay the checks.

## Generic Attestation Envelope

Type string:

```solidity
FlowMemoryAttestationEnvelopeV0(bytes32 subjectHash,uint8 subjectKind,bytes32 attesterId,bytes32 attesterKeyId,bytes32 verifierSetRoot,uint64 issuedAtUnixMs,uint64 expiresAtUnixMs,bytes32 nonce)
```

Hash:

```text
attestationEnvelopeHash = keccak256(abi.encode(
ATTESTATION_ENVELOPE_TYPEHASH,
subjectHash,
subjectKind,
attesterId,
attesterKeyId,
verifierSetRoot,
issuedAtUnixMs,
expiresAtUnixMs,
nonce
))
```

Suggested subject kinds:

```text
1 = receipt
2 = verifier report
3 = artifact root
4 = storage receipt commitment
5 = challenge evidence
```

The package implements this as `attestationEnvelopeHash` and aliases it as `attestationDigest`.

## Local Signature Helpers

The package includes `publicKeyFromPrivateKey`, `signDigest`, and `verifyDigest` for deterministic secp256k1 tests using local generated test keys only. These helpers are not key management, do not load real secrets, and do not assert production verifier identity. Production services must provide their own secure signer, key registry checks, expiry policy, and verifier set validation.

## Signature Mode Comparison

### EIP-712 Typed Signatures

Pros:

- Best fit for EVM wallets, contracts, and typed domain separation.
- Binds chain id, verifying contract or registry, and deployment salt cleanly.
- Human and tooling support is better than raw hashes.

Cons:

- More implementation complexity.
- Needs careful domain management before registries exist.
- Less natural for non-EVM device keys.

### Simple Domain-Separated Keccak Hashes

Pros:

- Simple for services, hardware, and non-EVM agents.
- Easy to reproduce in verifier tests.
- Can be wrapped by many signature systems.

Cons:

- Weaker wallet UX.
- More risk of accidental replay if domain fields are omitted.
- Contracts need explicit recovery logic per key type.

MVP choice:

- Use EIP-712 for EVM/secp256k1 worker and verifier signatures.
- Use simple typed Keccak hashes for object ids, roots, report ids, and future non-EVM key adapters.
- Do not accept ambiguous `personal_sign` messages for protocol-critical attestations.

## Status Vocabulary

```text
0 = reserved
1 = observed
2 = verified
3 = unresolved
4 = unsupported
5 = failed
6 = reorged
7 = superseded
```

Minimum evidence:

- `observed`: receipt/log was read, but finality or evidence checks are incomplete.
- `verified`: observation id, event args, commitments, artifacts, and signatures required by policy passed.
- `unresolved`: data is missing or unavailable, but failure is not proven.
- `unsupported`: schema, pulse type, root scheme, or key type is unknown.
- `failed`: a required check failed.
- `reorged`: the block/log is no longer canonical under the finality policy.
- `superseded`: a newer report replaces this report.

## Replay Protection

Verifier and worker signatures must bind:

- chain id
- deployment id or registry
- key id
- verifier set root where relevant
- sequence or nonce
- expiry
- receipt hash or report id

Off-chain services should reject duplicate `(workerId, workerSequence)` and duplicate verifier nonces unless the policy explicitly treats exact duplicate signatures as idempotent.
Loading
Loading