Skip to content

Implement graph validation before deployment #9

Description

@Pvsaint

Summary

Before a contract graph is compiled or deployed, it should be validated across five distinct layers: structural integrity, field completeness, Stellar address format, cross-block semantic consistency, and circular dependency detection. The result must be surfaced as structured, per-node errors on the canvas and must gate the Compile, Simulate, and Deploy buttons.

This is significantly more complex than it first appears — it requires a full multi-pass validation pipeline that understands the semantics of each block type, propagates errors to the correct canvas nodes, and integrates with the existing validateContractGraph / validateGraphStructure stack already in src/lib/compile/validate.ts.

Background

A basic structural validator (validateGraphStructure) already exists and checks reachability and executable-block presence. This issue extends it into a deep semantic validator that catches errors the current compiler only discovers at cargo build time — or never, silently producing broken contracts.

Required Validation Passes

Pass 1 — Structural (extend existing)

  • All nodes reachable from the single default (Start) node.
  • Exactly one Start node exists.
  • No duplicate node IDs or edge IDs.

Pass 2 — Field completeness per block type

Block Required fields Error code
Transfer params.token or params.asset.contractId non-empty MISSING_TOKEN
Storage params.storageKey non-empty and ≤ 9 chars (Soroban symbol limit) MISSING_STORAGE_KEY / STORAGE_KEY_TOO_LONG
Event params.eventName non-empty MISSING_EVENT_NAME
Condition params.conditionExpression present and complete (both operands non-empty) INCOMPLETE_EXPRESSION

Pass 3 — Stellar address format

  • All fields that accept an Address (token contract ID, asset contractId) must either be empty or match the Stellar strkey pattern: 56 characters starting with C (contract) or G (account).
  • Error code: INVALID_STELLAR_ADDRESS
  • Error must identify both the node ID and the specific field name.

Pass 4 — Semantic cross-block rules

  • An Auth block must appear before any Transfer block in the topological execution order (auth-before-transfer rule). Violation → AUTH_AFTER_TRANSFER.
  • A Condition block with a storageKey operand must have a Storage (write) block for that key reachable from Start in the same graph. Violation → UNRESOLVED_STORAGE_REF.
  • A Condition block using an invocationArg operand must reference a name that exists in the deriveParams output for the current graph. Violation → UNRESOLVED_ARG_REF.

Pass 5 — Cycle detection (extend existing)

  • Detect any directed cycle in the graph using DFS.
  • Report the cycle node IDs in the error details array.
  • Error code: GRAPH_CYCLE_DETECTED

Validation Result Type

export interface NodeValidationError {
  nodeId: string
  code: string
  message: string
  field?: string      // e.g. "params.storageKey"
}

export interface GraphValidationResult {
  valid: boolean
  nodeErrors: NodeValidationError[]   // per-node, for canvas highlighting
  graphErrors: CompileError[]         // graph-level (cycle, missing start, etc.)
}

export function validateGraphDeep(graph: ContractGraph): GraphValidationResult

Canvas Integration (BlockEditor.tsx)

  • Run validateGraphDeep debounced (300 ms) on every nodes/edges change.
  • Pass nodeErrors down to BlockNode via node data; nodes with errors render a red border and a warning icon badge showing the error count.
  • Hovering the warning badge shows a tooltip with all error messages for that node.
  • The Compile, Simulate, and Deploy buttons are disabled and show a red badge with the total error count while !result.valid.

Acceptance Criteria

  • validateGraphDeep is implemented and exported from src/lib/compile/validate.ts.
  • All five validation passes are implemented and covered by unit tests.
  • A Transfer node with an empty token field fails with MISSING_TOKEN.
  • A Storage node with a key longer than 9 characters fails with STORAGE_KEY_TOO_LONG.
  • An invalid Stellar address string fails with INVALID_STELLAR_ADDRESS and identifies the field name.
  • An Auth block placed after a Transfer in execution order fails with AUTH_AFTER_TRANSFER.
  • A cycle in the graph fails with GRAPH_CYCLE_DETECTED and lists the involved node IDs.
  • Nodes with errors render a red border and warning badge on the canvas.
  • Hovering the warning badge shows a tooltip with the error messages.
  • Compile, Simulate, and Deploy buttons are disabled when any validation error exists.
  • Unit tests in validate.test.ts cover all five passes with at least two cases each (valid and invalid).
  • A Playwright E2E test: adds a Storage block with a 10-character key, asserts the node turns red, fixes the key, asserts the red border disappears.
  • All existing tests continue to pass.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions