Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
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
1 change: 1 addition & 0 deletions .github/workflows/eas-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ on:
pull_request:
branches:
- main
- benchmarks

jobs:
android_build:
Expand Down
5 changes: 4 additions & 1 deletion .github/workflows/trunk-check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ permissions: read-all
jobs:
trunk_check:
name: Trunk Check Runner
runs-on: ubuntu-latest
runs-on: macos-15
permissions:
checks: write # For trunk to post annotations
contents: read # For repo checkout
Expand All @@ -22,6 +22,9 @@ jobs:
with:
submodules: recursive

- name: Setup lld linker
run: brew install lld

- name: Set up Rust toolchain
run: |
rustup show
Expand Down
4 changes: 4 additions & 0 deletions .trunk/configs/osv-scanner.toml
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
[[IgnoredVulns]]
id = "RUSTSEC-2023-0089"
reason = "atomic-polyfill - temporary ignore until upstream fixes"

[[IgnoredVulns]]
id = "RUSTSEC-2024-0388"
reason = "derivative - temporary ignore until upstream fixes"
Expand Down
85 changes: 65 additions & 20 deletions app/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,17 @@ import { QueryClient, QueryClientProvider } from "@tanstack/react-query";

// Components
import { ProgramDropdown, Program } from "../components/ProgramDropdown";
import { SystemDropdown } from "../components/SystemDropdown";
import { FIBONACCI_MAX_INPUT, NumberInput } from "../components/NumberInput";
import { ActionButtons } from "../components/ActionButtons";
import { ResultsDisplay } from "../components/ResultsDisplay";

// Data and Utils
import { Programs } from "../components/data/constants";
import {
Systems,
SystemPrograms,
SystemConfigurations,
} from "../components/data/constants";

// Styles
import { colors } from "../components/styles/colors";
Expand Down Expand Up @@ -47,18 +52,44 @@ const queryClient = new QueryClient({
});

function AppContent() {
const { state, setState, handleProgramSelect } = useAppState();
const mutations = useComputationMutations(state, setState);
const {
state,
setState,
getCurrentInputValue,
setCurrentInputValue,
getCurrentComputationResult,
setCurrentComputationResult,
handleProgramSelect,
handleSystemSelect,
} = useAppState();
const mutations = useComputationMutations(
state,
setState,
setCurrentComputationResult,
getCurrentComputationResult,
getCurrentInputValue,
);
const { errorMessage, hasError } = useErrorHandling(mutations);

const { generateProofMutation, verifyProofMutation } = mutations;
const currentComputationResult = getCurrentComputationResult();

const currentSystemConfig = SystemConfigurations[state.selectedSystem];
const currentSystemPrograms = SystemPrograms[state.selectedSystem];
const currentProgramAvailable =
Programs.find((p) => p.type === state.selectedProgram)?.available ?? false;
currentSystemPrograms.find((p) => p.type === state.selectedProgram)
?.available ?? false;

// Get the current system label for the header
const currentSystemLabel =
Systems.find((s) => s.type === state.selectedSystem)?.label || "Unknown";

const handleGenerateProof = () => {
if (state.selectedProgram === "fibonacci") {
const numValue = parseInt(state.inputValue, 10);
if (
state.selectedProgram === "fibonacci" &&
state.selectedSystem === "cairo-m"
) {
const numValue = parseInt(getCurrentInputValue(), 10);

if (numValue > FIBONACCI_MAX_INPUT) {
Alert.alert(
Expand All @@ -82,32 +113,42 @@ Please use an input inferior to ${FIBONACCI_MAX_INPUT}.`,

{/* App Title */}
<View style={styles.header}>
<Text style={typography.appTitle}>Cairo M</Text>
<Text style={typography.appTitle}>{currentSystemLabel}</Text>
</View>

<ScrollView
style={styles.scrollView}
contentContainerStyle={styles.content}
showsVerticalScrollIndicator={false}
>
{/* Program Selection and Input Section */}
{/* System and Program Selection Section */}
<View style={styles.inputSection}>
{/* System Selection */}
<SystemDropdown
selectedSystem={state.selectedSystem}
onSystemSelect={(system) => handleSystemSelect(system, mutations)}
systems={Systems}
/>

{/* Program Selection */}
<ProgramDropdown
selectedProgram={state.selectedProgram}
onProgramSelect={(program) =>
handleProgramSelect(program, mutations)
}
Programs={Programs}
Programs={currentSystemPrograms}
/>

{/* Number Input - Only show if fibonacci is selected and available */}
{state.selectedProgram === "fibonacci" &&
{/* Number Input - Only show if system supports input and fibonacci is selected */}
{currentSystemConfig.supportsInput &&
state.selectedProgram === "fibonacci" &&
currentProgramAvailable && (
<NumberInput
value={state.inputValue}
onValueChange={(value) => setState({ inputValue: value })}
placeholder="Enter fibonacci term"
value={getCurrentInputValue()}
onValueChange={(value) => setCurrentInputValue(value)}
placeholder={
currentSystemConfig.inputPlaceholder || "Enter input"
}
/>
)}
</View>
Expand All @@ -117,10 +158,13 @@ Please use an input inferior to ${FIBONACCI_MAX_INPUT}.`,
onGenerateProof={handleGenerateProof}
onVerifyProof={verifyProofMutation.mutate}
isProofDisabled={
!currentProgramAvailable || generateProofMutation.isPending
!currentProgramAvailable ||
generateProofMutation.isPending ||
(currentSystemConfig.supportsInput &&
!getCurrentInputValue().trim())
}
isVerifyDisabled={
!state.computationResult?.runProofResult ||
!currentComputationResult?.runProofResult ||
verifyProofMutation.isPending
}
/>
Expand All @@ -133,12 +177,13 @@ Please use an input inferior to ${FIBONACCI_MAX_INPUT}.`,
)}

{/* Results - Only show if we have results and program is available */}
{currentProgramAvailable && state.computationResult && (
{currentProgramAvailable && currentComputationResult && (
<View style={styles.resultsSection}>
<ResultsDisplay
result={state.computationResult}
showProof={!!state.computationResult.runProofResult}
showVerification={!!state.computationResult.verifyResult}
result={currentComputationResult}
showProof={!!currentComputationResult.runProofResult}
showVerification={!!currentComputationResult.verifyResult}
systemType={state.selectedSystem}
/>
</View>
)}
Expand Down
14 changes: 14 additions & 0 deletions assets/noir/noir_fib.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"noir_version": "1.0.0-beta.6+9e90bf45d4386bd7762a0d08b3c548d729a3a9b7",
"hash": "2225960857419704904",
"abi": {
"parameters": [],
"return_type": { "abi_type": { "kind": "field" }, "visibility": "public" },
"error_types": {}
},
"bytecode": "H4sIAAAAAAAA/6XOyQmAMBQE0AQs6C/JX262krX/EkRQRNST7zIwh2FiuMTwdHbrkfAP3rZGIZVGGcdEZxMANyDonWqxKq6pTeZUOYu3iajmlC2TKCRLvH9bwrsYvm23BOwW9AAAAA==",
"debug_symbols": "XY5BCsQwCEXv4rqLWfcqw1BsaosgJtikMITefWyYQOlK/3/6tcJCc9km1jXuML4rzMYivE0SA2aO6m49B+hyykbkFty4byU00gyjFpEBDpTShvaE2mpGc/oagHTx6oErC13d+XGBge158UBjnIX+ci0abjR/Uyf942Qx0FKMrqTGPPsH",
"file_map": {},
"names": ["main"],
"brillig_names": []
}
10 changes: 5 additions & 5 deletions cairo-m/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion cairo-m/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ cairo-m-common = { git = "https://github.com/kkrt-labs/cairo-m" }
cairo-m-runner = { git = "https://github.com/kkrt-labs/cairo-m" }
cairo-m-prover = { git = "https://github.com/kkrt-labs/cairo-m" }
thiserror = "2.0.12"
sonic-rs = "0.5.1"
sonic-rs = "0.5.2"
stwo-prover = { git = "https://github.com/starkware-libs/stwo", features = [
"parallel",
], rev = "ab57a1c" }
Expand Down
3 changes: 3 additions & 0 deletions cairo-m/rust-toolchain.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[toolchain]
channel = "nightly-2025-04-06"
profile = "default"
130 changes: 130 additions & 0 deletions components/BaseResultsDisplay.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
import React from "react";
import { StyleSheet, View, Text } from "react-native";
import { colors } from "./styles/colors";
import { Accordion } from "./Accordion";
import { formatFrequency, formatTime } from "./utils/computation";
import { ComputationResult } from "../hooks/types";

export interface BaseResultsDisplayProps {
result: ComputationResult;
showProof: boolean;
showVerification: boolean;
}

export const ResultItem: React.FC<{
label: string;
value: string | number;
}> = ({ label, value }) => (
<View style={styles.resultItem}>
<Text style={styles.compactResultLabel}>{label}</Text>
<Text style={styles.compactResultValue}>{value}</Text>
</View>
);

export const JsonResultItem: React.FC<{ label: string; value: string }> = ({
label,
value,
}) => (
<View style={styles.resultItem}>
<Text style={styles.compactResultLabel}>{label}</Text>
<Text style={styles.jsonResultValue}>{value}</Text>
</View>
);

export const formatProofSize = (sizeInBytes: number): string => {
const sizeInKB = sizeInBytes / 1024;
if (sizeInKB < 1) {
return `${sizeInBytes} B`;
}
return `${sizeInKB.toFixed(2)} KB`;
};

export const formatSteps = (steps: number): string => {
return steps.toLocaleString();
};

interface AccordionSectionProps {
title: string;
showSection: boolean;
children: React.ReactNode;
}

export const AccordionSection: React.FC<AccordionSectionProps> = ({
title,
showSection,
children,
}) => {
if (!showSection) return null;

return (
<Accordion title={title} defaultExpanded={true}>
{children}
</Accordion>
);
};

export const BaseResultsContainer: React.FC<{ children: React.ReactNode }> = ({
children,
}) => (
<View style={styles.container}>
<View style={styles.accordionContainer}>{children}</View>
</View>
);

// Shared verification results component
export const VerificationResults: React.FC<{
result: ComputationResult;
showVerification: boolean;
}> = ({ result, showVerification }) => {
if (!showVerification || !result.verifyResult) {
return null;
}

return (
<AccordionSection title="Verification Results" showSection={true}>
<ResultItem
label="Verification Duration"
value={formatTime(result.verifyResult.verificationDuration)}
/>
</AccordionSection>
);
};

const styles = StyleSheet.create({
container: {
flex: 1,
},
accordionContainer: {
gap: 0, // Remove gap between accordions
},
resultItem: {
flexDirection: "row",
justifyContent: "space-between",
alignItems: "baseline",
paddingVertical: 4,
},
compactResultLabel: {
fontSize: 14,
fontWeight: "400",
color: colors.onBackground,
fontFamily: "Inter_400Regular",
opacity: 0.8,
letterSpacing: 0.1,
},
compactResultValue: {
fontSize: 18,
fontWeight: "700",
color: colors.secondary,
fontFamily: "Inter_700Bold",
letterSpacing: 0.2,
},
jsonResultValue: {
fontSize: 14,
fontWeight: "500",
color: colors.secondary,
fontFamily: "Inter_500Medium",
letterSpacing: 0.1,
flexShrink: 1,
maxWidth: 200,
},
});
Loading
Loading