Create your first Midnight contract
이 튜토리얼에서는 첫 번째 Compact smart contract를 작성하고, Preprod 테스트 네트워크에 배포한 뒤, 프라이버시 보존 로직으로 blockchain에 Hello World 메시지를 기록합니다.
완료하면 다음을 수행할 수 있습니다:
- 상태를 저장하는 Compact smart contract 작성
- Contract를 zero-knowledge circuit으로 컴파일
- Preprod 테스트 네트워크에 contract 배포
- Blockchain에 Hello World 메시지 기록
Prerequisites
시작하기 전에 다음을 확인하세요:
- Toolchain 설치 가이드 완료
- Node.js v22 이상
Set up project
스타터 레포를 클론하세요:
git clone https://github.com/midnightntwrk/example-hello-world.git
의존성을 설치하세요:
npm install
필요한 디렉토리를 생성하세요:
mkdir contracts
contracts 폴더에 Compact smart contract 소스 파일을 저장합니다.
Create the contract file
contracts 디렉토리에 hello-world.compact라는 새 파일을 생성하세요:
touch contracts/hello-world.compact
VS Code에서 이 파일을 여세요:
code .
Create the Compact Smart Contract
pragma language_version 0.22;
export ledger message: Opaque<"string">;
export circuit storeMessage(newMessage: Opaque<"string">): [] {
message = disclose(newMessage);
}
pragma language_version은 contract가 사용하는 Compact 버전을 지정합니다.ledger message는 온체인 상태에 문자열 값을 저장하는message라는 state variable을 생성합니다. 온체인 상태는 blockchain에서 공개적이고 영구적입니다.circuit storeMessage는 온체인 상태를 수정하는 로직을 정의하는 Compact circuit입니다.newMessage: Opaque<"string">는 입력 파라미터입니다. Circuit 파라미터는 기본적으로 비공개입니다.disclose()함수는 비공개 값을 공개 저장해도 안전하다고 표시합니다. 이 함수 없이newMessage를 ledger에 직접 할당하면 컴파일러 오류가 발생합니다.
Compile the contract
컴파일은 Compact 코드를 zero-knowledge circuit으로 변환하고, 암호화 키를 생성하며, DApp에서 사용할 TypeScript API와 JavaScript 구현을 만들어 줍니다.
프로젝트 루트에서 컴파일러를 실행하세요:
npm run compile
다음과 같은 출력이 표시됩니다:
Compiling 1 circuits:
circuit "storeMessage" (k=6, rows=26)
컴파일 과정에서 수행되는 작업:
- Compact 코드를 파싱하고 유효성을 검사합니다.
- 로직에서 zero-knowledge circuit을 생성합니다.
- Circuit용 proving key와 verifying key를 생성합니다.
- Contract용 TypeScript API와 JavaScript 구현을 생성합니다.
컴파일이 완료되면 새로운 디렉토리 구조가 나타납니다:
contracts/
├── managed/
| └── hello-world/
| ├── compiler/
| ├── contract/
| ├── keys/
| └── zkir/
└── hello-world.compact
각 디렉토리의 역할:
- contract/: JavaScript 구현과 타입 정의가 포함된 컴파일된 contract artifact.
- keys/: Zero-knowledge proof 생성에 필요한 암호화 proving key와 verifying key.
- zkir/: Zero-Knowledge Intermediate Representation. Compact와 ZK 백엔드 사이의 중간 표현.
- compiler/: 다른 도구에서 contract 구조를 파악하는 데 활용할 수 있는 컴파일러 생성 JSON 출력.
Deploy Contract to Preprod
Contract 컴파일이 완료되었으므로 blockchain에 배포합니다.
Docker 엔진이 실행 중인지 확인하고, 별도의 터미널에서 proof server를 시작하세요:
npm run start-proof-server
다음 단계를 위해 proof server를 실행 상태로 유지하세요.
Contract 배포에는 wallet이 필요합니다. 배포 스크립트가 새 wallet 생성을 안내합니다.
다음 단계에서 필요하므로 seed phrase를 반드시 저장하세요.
배포 스크립트를 실행하세요:
npm run deploy
Deployment Failed!
Contract 배포가 실패합니다:
(FiberFailure) Wallet.Transacting: Not enough Dust generated to pay the fee
Midnight 네트워크에서 transaction을 실행하려면 DUST가 필요합니다. DUST는 faucet에서 받은 NIGHT로부터 생성되지만, 생성에 시간이 걸립니다. NIGHT가 많을수록 DUST가 더 빠르게 생성됩니다. 잠시 후 다시 시도하세요.
배포 스크립트를 다시 실행하되, 이번에는 옵션 2 'Restore from seed'를 선택하고 이전에 생성한 wallet의 seed를 붙여넣으세요:
npm run deploy
배포가 완료되면 다음과 유사한 출력이 표시됩니다:
✅ Contract deployed successfully!
Contract Address: 0x1234567890abcdef...
Saved to deployment.json
Contract interaction
Contract가 성공적으로 배포되었습니다. 이제 상호작용해 봅시다:
npm run cli
프롬프트가 나타나면 wallet seed를 입력하고 Preprod 네트워크에 연결될 때까지 기다리세요.
옵션 [2]를 선택해서 현재 메시지가 "(empty)"인지 확인하세요:
[1] Store a message
[2] Read current message
[3] Exit
그다음 옵션 1을 선택하고 "Hello World!"를 입력하세요. 메시지가 성공적으로 저장됩니다:
✅ Message stored!
Transaction: 0007f15ce66f14b01ff7d5c2b4fbf4a40f65630cd7950785a81832b11103c5a0f1
Block: 402893
옵션 [2]를 다시 선택하면 "Hello World!" 메시지가 표시됩니다:
Reading message from blockchain...
Current message: "Hello World!"
Hello World! 첫 번째 Midnight DApp을 성공적으로 만들었습니다. 더 다양한 DApp 빌드 방법은 튜토리얼을 참고하세요!
Troubleshoot
컴파일 중 발생할 수 있는 일반적인 문제와 해결 방법입니다.
Compiler not found
compact compile 명령어가 인식되지 않으면 설치 상태를 확인하세요:
- Compact 개발 도구가 설치되어 있는지 확인:
which compact또는compact --version - 1단계가 성공하면 컴파일러 toolchain 설치 여부 확인:
compact compile --version - 자세한 내용은 Toolchain 설치 가이드를 참고하세요.
Compilation errors
구문 또는 타입 오류가 발생하면:
pragma language_version이 컴파일러 버전과 일치하는지 확인하세요.- 필요한 import가 모두 있는지 확인하세요.
- 필요한 위치에
disclose연산자를 사용했는지 확인하세요. - 오류 메시지의 라인 번호와 구체적인 문제를 확인하세요.
Next steps
Midnight DApp 빌드에 대해 더 알아보려면 튜토리얼을 살펴보세요. 다양한 DApp의 간략한 워크스루는 예제에서 확인할 수 있습니다.