이번 글에서는 Cairo 언어로 실행 가능한 프로그램을 작성하고 실행하는 방법을 소개합니다. Starknet 스마트 컨트랙트가 아닌, 일반 Cairo 실행 파일을 만들고 그 안에서 로직을 작성해보고자 합니다.
scarb로 Cairo 프로젝트 생성터미널에서 다음 명령어로 새 Cairo 프로젝트를 생성합니다:
scarb new <패키지명>
예시로는 다음과 같이 진행했습니다:
scarb new cairo_playground
아래와 같은 선택지가 나오게 됩니다:

? Which test runner do you want to set up? ›
❯ Starknet Foundry (default)
Cairo Test
"Cairo Test"를 선택해 일반적인 Cairo 실행 프로젝트로 만듭니다.
Scarb.toml 수정Scarb.toml 파일은 프로젝트 설정 파일입니다. 처음에는 다음과 같이 생성되어 있을 것입니다:
[package]
name = "cairo_playground"
version = "0.1.0"
edition = "2024_07"
[dependencies]
[dev-dependencies]
cairo_test = "2.11.4"
여기서 다음 항목을 추가해줍니다:
[[target.executable]]
name = "main"
function = "cairo_playground::main"
[dependencies]
cairo_execute = "2.11.4"
[[target.executable]]
이 설정은 해당 패키지를 "실행 가능한 프로그램(Executable)"로 정의한다는 의미입니다. 기본적으로 Cairo 프로젝트는 라이브러리 형태로 시작되지만, 이 옵션을 설정함으로써 명령줄에서 실행할 수 있는 형태로 빌드할 수 있게 됩니다.
name = "main"
실행 파일의 이름입니다. scarb execute -p cairo_playground 명령을 사용할 때 이 main이 실행됩니다. 나중에 여러 개의 실행 대상이 있을 경우 이름으로 구분할 수 있습니다.
function = "cairo_playground::main"
이 부분이 가장 중요한데:
cairo_playground는 Scarb.toml의 [package] 섹션에 명시된 패키지 이름입니다.::main은 해당 패키지의 루트 모듈(src/lib.cairo) 안에 정의된 main 함수를 뜻합니다."cairo_playground::main"은 "src/lib.cairo 안의 main 함수를 프로그램 진입점(entry point)으로 사용한다"는 의미입니다.Cairo는 Rust와 비슷한 모듈 시스템을 사용하기 때문에, 패키지명::함수명으로 진입점을 지정할 수 있으며, src/lib.cairo가 암묵적으로 루트 모듈로 취급되므로 별도로 파일 경로를 지정하지 않아도 자동으로 찾아 실행합니다.
cairo_execute = "2.11.4"
Cairo 프로그램을 실행할 수 있도록 도와주는 플러그인입니다. Cairo는 기본적으로 ZK 컨텍스트에서 동작하기 위한 언어이므로, 일반적인 실행 기능은 이 플러그인을 통해 제공됩니다.
"""
이제 src/lib.cairo 파일에 가서 간단한 함수 코드를 작성해봅니다.
/// 두 수를 더해서 결과가 예상한 값과 같은지 검증하는 함수
fn verify_addition(a: u16, b: u16, expected: u16) -> bool {
let result = a + b;
result == expected
}
// 두 수를 곱해서 결과가 예상한 값과 같은지 검증하는 함수
fn verify_multiplication(a: u16, b: u16, expected: u16) -> bool {
let result = a * b;
result == expected
}
#[executable]
fn main(input: (u16, u16, u16, u16)) -> bool {
let (x, y, expectedAdd, exepectedMul) = input;
//verify_addition 와 verify_multiplication 둘다 만족해야함.
verify_addition(x, y, expectedAdd) && verify_multiplication(x, y, exepectedMul)
}
이 코드는 두 수의 합과 곱의 결과를 확인해 리턴합니다. Cairo는 순수 함수형 스타일이며, #[executable] 어노테이션이 붙은 함수가 프로그램의 진입점입니다.
터미널에서 다음 명령어로 실행합니다:
scarb execute -p cairo_playground --print-program-output --arguments "5,6,11,30"
출력 결과는 다음과 같을 것입니다:
Program output:
[0, 1]
[0, 1]에서 0은 정상 종료를 의미하며,1는 실제 반환된 결과값입니다. (참)Cairo의 가장 독특한 기능은 실행 결과에 대해 "정말로 이 코드가 올바르게 실행되었는지"를 증명할 수 있다는 점입니다.
즉, 단순히 어떤 숫자를 더했다는 결과만 보여주는 게 아니라,
"이 코드는 Cairo 프로그램으로 정확히 실행되었고, 그 결과가 맞다는 것을 수학적으로 증명할 수 있다"
는 것입니다.
이런 방식의 증명을 Zero-Knowledge Proof (ZKP) 라고 부릅니다. Cairo는 이 기능을 기본으로 내장하고 있어서, 몇 가지 명령어만으로 증명을 생성할 수 있습니다.
scarb prove --execution-id <번호>
<번호>는 실행했던 기록의 ID입니다. 예를 들어, execution1 디렉토리가 생겼다면 --execution-id 1로 입력합니다.
예시
scarb prove --execution-id 1
성공적으로 생성이 완료되면 다음과 같이 출력됩니다.
Proving cairo_playground
Saving proof to: target/execute/cairo_playground/execution1/proof/proof.json
proof.json 파일은 실행의 정확성을 증명하는 데이터입니다. 누군가에게 이 파일과 함께 실행 입력을 주면, 결과가 올바른지 검증할 수 있습니다.
이제 생성된 증명을 검증해보겠습니다:
scarb verify --execution-id 5
성공적으로 검증되면 다음과 같은 메시지를 확인할 수 있습니다:
Verifying cairo_playground
Verified proof successfully
위에서 실행한 (5,6,11,30) → 1 계산이 올바르게 수행되었음을 보장하는 제로 지식 증명(ZK proof) 이 생성되었으며, 제3자는 입력값이나 내부 과정을 보지 않고도 이 결과가 맞다는 것을 검증할 수 있습니다.
코드의 길이가 너무 짧으면 Verify에 실패할 수도 있습니다.
다음은 target/execute/cairo_playground/execution5/폴더 구조의 예시이다:
target/
└── execute/
└── cairo_playground/
└── execution5/
├── memory.bin
├── trace.bin
├── air_public_input.json
├── air_private_input.json
├── program_output.json
└── proof/
└── proof.json
trace.bin, memory.bin: 프로그램의 실행 추적 및 메모리 상태air_*.json: STARK 증명 시스템용 입력proof/proof.json: 최종 생성된 증명 파일program_output.json: 프로그램 실행 결과이런 구조 덕분에 Cairo는 일반적인 실행 언어가 아니라 ZK-Friendly한 실행 언어이라는 것을 알 수 있다.
Cairo로 실행 가능한 프로그램을 만들고 증명·검증까지 수행하는 전체 흐름을 아래에 정리했습니다.
| 단계 | 명령어 | 설명 |
|---|---|---|
| 프로젝트 생성 | scarb new <패키지명> | 새 Cairo 프로젝트를 생성합니다. |
| 디렉토리 이동 | cd <패키지명> | 생성된 프로젝트 폴더로 이동합니다. |
| 빌드 | scarb build | 프로그램을 컴파일합니다. |
| 실행 | scarb execute -p <패키지명> --print-program-output --arguments "5,6,11,30" | 실행 결과를 확인합니다. |
| 증명 생성 | scarb prove --execution-id <번호> | 해당 실행 결과에 대한 ZK 증명을 생성합니다. |
| 증명 검증 | scarb verify --execution-id <번호> |