
Solana 빌더: ZK Compression
Helius와 Light Protocol이 Solana 기반 Zero-Knowledge(ZK) Compression 프로젝트를 발표한 이후 며칠간 ZK Compression에 관한 논의가 활발했습니다. 대화의 상당 부분은 명칭에 집중됐습니다. ZK 롤업일까요? L2일까요? 아니면 완전히 다른 무언가일까요?
이것이 왜 중요할까요? Solana 생태계의 일부는 명칭을 둘러싼 논쟁이 불필요하다고 봅니다. 어떤 이름을 쓰는지보다 무엇을 하는지가 더 중요하다는 데는 어느 정도 동의합니다. 하지만 이름도 여전히 중요합니다. 이름은 특정 특성을 지닌 구조를 가리키고 이를 하나의 범주로 묶기 때문입니다. 따라서 이를 XYZ라고 부르면 그 특성과 신뢰 가정을 알 수 있으며, 이는 반드시 주의 깊게 살펴봐야 합니다!
특성
ZK-Compression의 맥락에서 평가하기 전에, 먼저 관심 있는 Solana의 특성을 나열해 보겠습니다.
- 동기식 원자적 조합성
- 동시성
- 안전성
- 활성성
- 검열 저항성
초기 신뢰 가정
풀 노드의 보안 가정을 설명할 때 "무신뢰"라는 용어를 사용하겠습니다. 이 정의가 기준입니다. 풀 노드가 단독으로 수행할 수 없는 모든 작업에는 추가 신뢰 가정이 필요합니다.
풀 노드는 프로토콜과 상호작용하는 유일한 무신뢰 방식입니다. 누군가 브리지, 위원회, 다중 서명, ZK, 사기 증명 등 추가 신뢰 가정을 도입하면서 무신뢰라고 주장한다면 틀린 말입니다.
배경지식
간단한 글머리 기호를 사용해 ZK-Compression을 이해하는 데 필요한 Solana의 배경지식을 짧게 설명하겠습니다.
- Solana 상태는 풀 노드의 디스크에 있는 “AccountsDB”에 저장됩니다
- 저장 단위는 "계정"이라고 합니다
- 계정에는 주소가 있습니다(각 32바이트)
- 계정이 저장할 수 있는 데이터 양은 0~10MB(최대)로 다양합니다
- Solana에서 10MB를 저장하려면 계정 생성자가 약 70 SOL을 지불해야 합니다. 이 비용은 계정 수가 아니라 저장 용량에 따라 결정됩니다. 10MB 계정 1개일 수도 있고 10KB 계정 1,000개일 수도 있습니다.
- 현재 Solana의 모든 계정 크기는 76GB입니다(압축 기준)
- 모든 Solana 트랜잭션은 읽고 쓸 계정을 모두 지정해야 합니다
- 현재 Solana 트랜잭션의 최대 크기는 1,232바이트입니다(이를 늘리는 제안이 있습니다)
- 각 Solana 트랜잭션은 다음과 같은 텍스트를 지정해야 합니다
- 서명(각 64바이트)
- 계정(각 32바이트)
- 명령 데이터(임의 길이)
- 최근 블록 해시(32바이트)
- 프로그램 주소(각 32바이트)(CPI: 프로그램 간 호출)
- Solana 트랜잭션에는 32바이트의 “최근 블록 해시”가 포함됩니다. 이는 가장 최근 150개 블록 이내에 포함되어야 하며, 그렇지 않으면 무효로 간주되어 다시 서명하고 제출해야 합니다
일반 트랜잭션의 수명 주기
일반적으로 트랜잭션이 실행되는 수명 주기는 다음과 같습니다.
- 먼저 트랜잭션에 대해 유효 기간 확인(최근 트랜잭션만 유효), 중복 제거, 구조 검증, 수수료(gas), 서명 확인을 수행합니다
- 프로그램 주소를 기반으로 프로그램 바이트코드를 로드하고 Solana Virtual Machine(SVM)을 인스턴스화합니다
- 트랜잭션이 참조하는 모든 계정을 확인하고 저장소에서 메모리로 로드한 뒤 SVM에 전달합니다
- 프로그램 바이트코드를 실행합니다
- 수정된 모든 계정을 업데이트된 상태로 저장소에 다시 동기화합니다
ZK-Compression의 주요 목적은 다음과 같습니다.
- 온체인 상태는 비쌉니다. 예를 들어 계정 1,000개의 비용은 70 SOL이므로 Drip Haus 같은 제품은 비용이 빠르게 증가합니다
- 전체 상태를 머클화하지 않더라도 디스크에 저장할 계정이 많아지면 스냅샷과 인덱스 등이 커집니다
- 모든 계정이 자주 사용되는 것은 아니므로 지속적인 리소스 비용을 부담할 필요가 없습니다
그렇다면 압축을 구현하는 가장 간단한 방법은 무엇일까요?
계정을 디스크에 저장했다가 필요할 때 읽는 대신(트랜잭션 실행 수명 주기의 3단계), 트랜잭션이 페이로드의 일부로 계정 데이터를 전달하면 온체인 저장 비용을 절감할 수 있습니다. 하지만 여기서 새로운 문제가 생깁니다. 사용자가 상태를 속이지 못하도록 어떻게 강제할 수 있을까요?
예를 들어 토큰 잔액을 저장하는 계정의 오프체인 값이 1200이고 소유자 필드가 “BYixJwV32DjeuyRww72PwZMyKcaedN533GBrv7CDh4n9”라고 가정해 보겠습니다.
이 데이터로 트랜잭션을 체인에 제출한다면, 체인은 “BYixJwV32DjeuyRww72PwZMyKcaedN533GBrv7CDh4n9” 주소가 보유한 토큰 수를 속이지 않았다는 것을 어떻게 알 수 있을까요?
트랜잭션을 처리하는 풀 노드는 오프체인 데이터에 접근할 수 없습니다. 사용자가 트랜잭션과 함께 데이터를 제공하기를 기대합니다.
여기에는 머클 증명을 사용할 수 있습니다. 자세한 설명은 생략하겠지만, 머클 증명은 작은 온체인 저장 공간만으로 특정 데이터에 검증 가능한 방식으로 "커밋"하는 방법입니다. 체인과 동기화된 모든 풀 노드는 이 작은 "커밋먼트"를 저장합니다. 누군가 트랜잭션에 데이터를 제공할 때는 커밋먼트에 대해 검증할 수 있는 "증명"도 같은 트랜잭션에 담을 수 있습니다. 이 증명은 암호학적으로 안전합니다.
여기에 문제가 있을까요?
문제는 머클 증명이 클 수 있다는 점입니다. 트리에 계정이 100,000개 있으면 계정 하나의 증명 크기는 17 * 32 = 544바이트입니다. 여러 계정의 증명을 제공하려면 최악의 경우 증명 크기만큼 배가됩니다. 따라서 계정 10개는 최악의 경우 10 * 544 = 5440바이트가 됩니다. 이 공간 문제는 특히 Solana에서 두드러집니다. 현재 Solana 트랜잭션은 1,232바이트로 제한되지만 다른 체인은 대체로 제한이 덜하기 때문입니다. 프로그램, 서명, 최근 블록 해시 등 각 구성 요소의 크기를 나열한 위 섹션을 참고하세요. 따라서 최상의 경우에도 머클 증명만으로 트랜잭션 크기의 절반을 사용합니다.
여기서 몇 가지 질문이 생깁니다.
트랜잭션 크기가 1,232바이트라면 전체 데이터를 어떻게 트랜잭션의 일부로 전송하나요?
아주 좋은 질문입니다. ZK Compression은 적은 양의 데이터로 구성된 매우 많은 계정에 유용합니다. 토큰 잔액(토큰당 8바이트), NFT의 소량 메타데이터 등 100바이트의 데이터는 트랜잭션에 쉽게 담을 수 있습니다. 하지만 다른 데이터도 들어가므로 1,000바이트는 어렵습니다. 계정에 더 많은 데이터를 저장해야 한다면 이 방법과 ZK Compression은 사용할 수 없습니다.
다만 이 주장에는 한 가지 미묘한 점이 있습니다. ZK Compression에 사용되는 동일한 로직을 계정 상태의 일부에 적용할 수 있습니다. 즉, 계정의 전체 데이터를 단일 트랜잭션 페이로드에 담을 수 없더라도 우회할 방법은 있습니다. 구체적으로 일부 데이터에 커밋하고 증명을 제공하는 방식입니다.
머클 증명만 사용할 수 있나요?
아닙니다. 머클 증명은 벡터 커밋먼트의 한 종류일 뿐입니다. 커밋먼트 크기는 32바이트이고 증명 크기는 Log2(N) * 32바이트입니다. 여기서 N은 커밋할 벡터의 크기입니다. Log2(100000)이 17이므로 앞서 17이라는 값을 얻었습니다. 하지만 증명 크기가 일정한 커밋먼트도 있습니다(KZG, Pedersen). 실제로 ZK-Compression은 이러한 방법 중 하나를 사용합니다!
일반적으로 상태의 일부로 풀 노드에 저장되는 계정 데이터를 트랜잭션과 함께 제공해야 한다고 했습니다. 이 데이터는 어디에 저장되나요?
아주 좋은 질문이며, 신뢰 가정과 특성에 영향을 미치는 부분입니다. 답은 어디든 가능하다는 것입니다! 특화된 RPC 서버가 이 데이터를 저장할 수 있고, Filecoin이나 IPFS의 일부로 저장할 수도 있으며, 사용자가 자신의 컴퓨터에 직접 저장할 수도 있습니다. 중요한 점은 벡터의 모든 요소가 어딘가에 저장되어 있기만 하면 필요할 때 증명을 계산할 수 있다는 것입니다. 저장 위치에 따른 영향은 특성 섹션에서 다루겠습니다.
다른 체인에서도 가능한가요?
ZK-Compression을 사용하려면 특히 zk-SNARK 검증 비용이 저렴해야 합니다. Solana에서는 저장보다 연산이 저렴하므로 잘 맞습니다. 각 트랜잭션에 제공되는 데이터에 벡터 커밋먼트와 증명을 사용하는 일반화된 개념은 다른 체인에서도 가능하지만, 연산 비용이 비싸므로 Solana만큼 장단점이 뚜렷하지 않습니다. 실제로 일회성 SSTORE와 비교하면 지속적인 검증 gas 비용은 EVM 기반 체인에서 오히려 더 비쌉니다.
ZK Compression이란 무엇인가요?
- ZK Compression이 무엇인지 모른다면 이 섹션에서 알아볼 수 있습니다
- 대략적인 개념만 알고 있더라도 흔한 오해가 있으므로 이 섹션을 읽어보시기를 권합니다
- 정확히 알고 있다면 제가 잘못 설명한 부분을 바로잡을 수 있도록 읽어주시기를 부탁드립니다 :)
위 섹션을 이해했다면 ZK Compression의 90%를 이해한 것입니다. 핵심 문제는 머클 증명의 크기였습니다. ZK Compression은 계산을 증명하는 방식을 사용하는 것이 전부입니다.
ZK가 무엇인지 몰라도 크게 문제되지 않습니다. 계산을 "올바르게" 수행했다는 것을 증명하는 방법이라는 점만 알면 됩니다. 간단한 예로 두 수를 곱해 세 번째 수를 얻었다는 것을 증명하려 한다고 가정해 보겠습니다. 즉, 4*3 = 12입니다.
이를 증명하는 “ZK 방식”은 다음 함수를 사용하는 것입니다.
f(x,y) = x*y
위 코드의 회로를 생성하면 증명자는 계산이 올바르다는 증명을 생성합니다. 회로 자체가 커밋먼트이므로 모두가 실행 중인 "계산"이 무엇인지 알 수 있습니다. 하지만 입력값을 알 필요가 없다는 점이 뛰어납니다. **f(3,4)**를 실행하면 12와 "증명"이 반환됩니다. 이제 누구나 **12, "증명"**을 가져와 어떤 두 수를 곱해 12를 얻었다는 것을 검증할 수 있습니다. 그 수가 4,3인지 6,2인지, 심지어 12,1인지도 알 수 없습니다. 이 숫자를 숨기면서도 다른 사람이 검증할 수 있다는 점에서 “영지식”이라는 이름이 나왔습니다.
왜 이것을 설명할까요?
이 일반화된 개념은 특정 계산을 수행해 특정 결과를 얻었다는 것을 증명하는 데 매우 강력합니다. 누군가 결과와 증명을 가지고 있다면 계산을 직접 실행하지 않고도 올바르게 수행됐는지 검증할 수 있습니다. 이는 어떤 임의의 계산에도 적용됩니다. 여기서는 두 수를 곱했지만 "이 서명 10개를 검증했고 모두 유효합니다"라고 증명하는 데도 사용할 수 있습니다. 이것이 두 번째 장점이며, 무언가를 “숨길” 필요가 없을 때도 영지식 증명을 사용하는 가장 큰 이유 중 하나입니다. 1,000단계, 심지어 100만 단계의 연산이 필요한 문제를 하나의 증명만 검증하면 계산이 올바르게 수행됐음을 알 수 있는 문제로 바꾸기 때문입니다. 단, 증명을 생성하는 데 시간이 걸린다는 주의점이 있습니다.
ZK Compression은 동일한 기술로 실제 머클 트리 멤버십 로직을 실행합니다. 즉, 계정 데이터와 증명(128바이트)을 받아 데이터가 실제로 체인의 "커밋먼트"에 포함되는지 검증하는 회로를 갖습니다. (실제 증명은 256바이트이지만, 타원 곡선과 점의 편리한 특성상 곡선을 알고 있다면 점 하나만으로 두 번째 점을 구할 수 있습니다.)
주된 목적은 증명 크기를 일정한 128바이트로 줄여 소형 계정 데이터에 비교적 많은 공간을 남기는 것입니다. 일반 머클 증명은 Log2(N)이지만 ZK Compression은 항상 일정하므로 하나의 커밋먼트 아래에 매우 많은 계정을 둘 수 있습니다. (참고로 계정 100,000개의 머클 증명은 약 550바이트로, 트랜잭션 페이로드의 절반에 해당합니다.)
이 증명은 오프체인에서 생성할 수 있지만 검증은 온체인에서 이뤄져야 합니다. 프로그램이 실행을 계속하기 전에 계정에 올바른 데이터를 제공했는지 확인해야 하기 때문입니다. 이를 위해서는 ZK 증명을 검증하는 기본 메커니즘이 필요합니다. ZK-Compression이 사용하는 특정 증명자 시스템은 Groth16이며, 이는 다시 alt_bn128 syscall에 의존합니다. 현재 mainnet에서는 기능 플래그로 제한되어 있으며 테스트 중입니다.
흥미로운 점은 ZK-Compression이 사용하는 메커니즘으로 임의의 계산을 검증할 수 있다는 것입니다("이 리프가 이 루트를 가진 트리에 속하는가?"만 검증하는 것이 아닙니다).
ZK Compression의 주요 장점 중 하나는 개발자가 "ZK" 부분을 전혀 다루지 않아도 되도록 모든 기반을 제공한다는 것입니다. 개발자 관점에서는 이를 동일한 필드 등을 가진 다른 계정처럼 취급하므로 프로그램 내부에서 일반 계정처럼 다룰 수 있습니다. "ZK 마법"의 대부분을 추상화해 개발자가 직접 처리하지 않도록 하는 데 가치가 있습니다.
ZK 롤업
너무 자세히 들어가지는 않겠지만, ZK 롤업은 대체로 ZK-Compression과 동일한 개념을 사용합니다. 가장 큰 유사점은 전체 롤업 상태가 기본 레이어(Ethereum)에서 하나의 루트로 표현된다는 것입니다. 이 때문에 ZK-Compression이 롤업이라는 주장이 일부 나옵니다. 하지만 중요한 차이점이 있습니다.
롤업 트랜잭션 100개를 생각해 보겠습니다.
전체 ZK 롤업은 하나의 회로로 취급됩니다(예시로 사용한 곱셈 프로그램과 같습니다). 100개의 트랜잭션을 모두 검증하고(서명, 컨트랙트 로직, 중복 제거 확인 등), 다음 내용을 위한 하나의 증명을 생성합니다
"100개의 트랜잭션을 적용한 후 상태 루트가 A에서 B로 변경됩니다". 증명이 검증되면 스마트 컨트랙트가 상태 루트를 A에서 B로 업데이트합니다.
반면 ZK-Compression에서는 100개 트랜잭션 각각에 계정 데이터가 올바르다는 사실만 알려주는 증명 하나가 포함됩니다. 하지만 트랜잭션이 생성한 상태 전환은 실제로 SVM 자체의 일부로 온체인에서 실행됩니다. 증명이 검증되면 일반 계정처럼 취급됩니다. 이는 다음에 설명할 조합성 측면에서 매우 중요합니다.
특성 다시 살펴보기
이제 흥미로운 부분입니다. ZK-Compression이 유지하는 Solana의 특성에는 무엇이 있을까요?
동기식 원자적 조합성
트랜잭션 하나가 ZK 압축 계정 2개와 "일반" 계정 10개를 참조하더라도 조합성은 깨지지 않습니다. ZK 압축 계정을 참조하는 명령이 압축되지 않은 "일반" 계정을 참조하는 다른 명령이나 프로그램을 호출할 수 있습니다. 두 계정이 서로 다른 트리 아래에서 압축되어 있어도 이 특성은 완전히 유지됩니다. 명령 하나가 실패하면 전체 트랜잭션이 롤백되며(원자적), 1행에서 호출된 명령의 변경 사항을 2행에서 확인할 수 있습니다(동기식).
ZK 롤업은 서로를 동기식 또는 원자적으로 호출할 수 없으므로 롤업에는 해당하지 않습니다(전역 잠금을 사용하고 롤업 간 롤백을 허용하지 않는 한 불가능합니다).
병렬성
이 기능은 병렬성에 어느 정도 영향을 미치며, 각 사례를 살펴볼 필요가 있습니다.
동일한 트리 아래의 여러 압축 계정에 쓰기
각 트리는 자체적으로 동시성을 지원합니다. 즉, 사용자가 동일한 상태 루트 아래의 압축 계정 두 개를 읽거나 쓸 때 작업을 동시에 실행하고 상태 루트도 동시에 업데이트할 수 있습니다. 여기에는 Solana가 cNFT의 동시 머클 트리 업데이트에 사용하는 것과 동일한 로직이 적용됩니다
동일한 압축 계정에 쓰기
각 압축 계정 자체는 동시성을 지원하지 않습니다. 두 사용자가 동일한 압축 계정에 쓰려고 하면 순서와 관계없이 트랜잭션 하나가 실패합니다. 일반 실행에서는 이전 명령이 계정에 쓴 내용을 다음 명령에서 사용할 수 있습니다. 하지만 ZK 압축 계정에서는 계정 데이터의 증명이 이전 상태에 대한 것이므로 유효하지 않게 됩니다
또 하나 주목할 점은 압축의 높은 컴퓨팅 유닛(CU) 사용량으로 인해 트리당 최대 동시성이 낮아진다는 것입니다. 계정 CU 한도에 따라 각 계정은 블록당 12M 컴퓨팅 유닛만 사용할 수 있기 때문입니다.
동기식 원자적 조합성은 대부분의 롤업에서 문제가 됩니다. 반면 병렬성 특성은 시퀀서 같은 추가 구성 요소 없이도 ZK Compression을 사용할 수 있음을 강조하기 위해 언급했습니다. 시퀀서가 없다는 것은 기본 체인이 순서를 결정한다는 의미입니다. based rollup에도 동일한 특성이 있다고 말할 수 있지만, 대부분의 롤업은 순서 결정에 중앙화된 시퀀서를 사용하므로 해당하지 않습니다.
신뢰 가정
누구나 증명 생성에 필요한 모든 원시 데이터를 저장하고 트랜잭션을 제출할 수 있지만, 이는 압축된 상태의 활성성에 영향을 미치는 추가 신뢰 가정입니다. 어떤 이유로 데이터가 "손실"되거나 지연되면 직접 데이터를 저장해 두지 않은 이상 트랜잭션을 제출할 수 없습니다. 다행히 이는 비잔틴 장애 허용이 필요한 3f+1 문제가 아니라 f+1 문제로 알려져 있습니다. f+1 문제에서는 정직한 노드 하나만 데이터를 제공하면 됩니다. 증명은 "자체 검증"이 가능하므로 "안전성" 문제는 없습니다. 주로 "활성성" 문제이자 검열 경로입니다.
일반 롤업과 ZK-Compression 모두 유효성 증명을 제공해야 합니다. 하지만 롤업은 전체 상태 전환 함수를 유효성 증명 안에 인코딩하는 반면, ZK-Compression은 "계정 데이터가 올바른가?"만 인코딩합니다. 따라서 신뢰 가정이 조금 다릅니다. 압축의 경우 신뢰 가정은 주로 상태 접근에 적용됩니다(상태 전환은 전체가 수행됩니다). 롤업의 경우 신뢰 가정은 기본 레이어의 관점에서 전체 상태 전환 함수에 적용됩니다. 비트 수나 기반 문제의 난이도 및 계산 불가능성에 관한 보안 가정은 동일하지만(Bilinear Diffie-Hellman Assumption), 해당 보안 모델을 신뢰하는 대상이 다릅니다. 상태 접근과 실행의 차이입니다. 이 점을 언급하는 이유는 추가 신뢰 가정이 어디에 더해지고 어디에는 더해지지 않는지 아는 것이 중요하기 때문입니다.
현재 ZK 압축 계정을 검증하는 프로그램은 업그레이드할 수 있습니다. 하지만 매우 구체적인 작업(머클 증명 열기)만 수행하고 지속적인 업그레이드가 필요하지 않으므로 향후 변경 불가능하게 만들거나 동결할 수 있습니다.
또한 상태 압축은 두 가지 방법으로도 구현할 수 있습니다.
- 트랜잭션 크기를 늘리는 제안(Solana Discord의 proj-3x-tx 채널)이 개발 중입니다. 적용된 후 크기가 허용된다면 일반 머클 증명을 사용할 수 있습니다
- alt_bn128 syscall이 적용되면 증명 크기가 일정한 일반 벡터 커밋먼트에도 사용할 수 있습니다(KZG는 alt_bn128을 포함한 모든 페어링 친화적 곡선에서 작동합니다). 이 방식에는 ZK 증명자 회로가 필요하지 않습니다
무엇이라고 불러야 할까요?
안타깝게도 롤업, L2, Validium 같은 용어는 지나치게 느슨하게 사용되어 일부 롤업은 롤업조차 아닙니다. 기본 레이어의 활성성, 안전성 또는 검열 저항성을 상속하지 않습니다. Helius는 "마케팅 용어"를 사용한다는 비판을 받았지만, 같은 비판을 하는 사람들도 동일한 이유, 즉 마케팅을 위해 자신이 투자한 프로젝트를 "롤업"이라고 느슨하게 불러왔습니다. 실제로 롤업이 아닌 프로젝트에도 여러 단계를 붙여 계속 롤업이라고 부를 수 있게 합니다.
모두가 그런 것은 아닙니다. 일부는 정확한 용어를 사용하는 데 매우 솔직했으며, 부정확한 용어로 사용자를 오도하는 사람들과 오랜 기간 논쟁해 왔습니다(일관되게 모두에게 정확한 용어 사용을 요구해 온 Toghrul에게 찬사를 보냅니다).
롤업과 다른 특성과 신뢰 가정이 있으므로 이를 롤업이라고 부르면 사용자가 혼동할 수 있습니다. Validium이라고 부르기에도 너무 포괄적입니다. 동기식 원자적 조합성이나 병렬성이 깨지지 않고 데이터 가용성(DA)이 온체인에 있으며, 무엇보다 상태 전환 함수 자체가 무신뢰라는 사실을 무시하기 때문입니다(풀 노드는 실행 자체의 유효성 증명만 검증하는 것이 아니라 실제 프로그램 전체를 실행합니다). 일부는 ZK 증명이 무신뢰라고 주장할 수 있지만, 이는 사실이 아닙니다. 신뢰를 크게 최소화하기는 하지만 수학적으로 보안 가정이 같지는 않습니다. 사용 사례의 99%에는 충분할 수 있지만 풀 노드보다 추가적인 신뢰 가정을 부과합니다. 예를 들어 페어링 곡선 기반 zk-SNARK의 경우 Bilinear Diffie Hellman Assumption이 있습니다. 물론 ZK-Compression은 snark를 사용해 계정 자체의 유효성을 확인하므로 ZK-Compression이 무신뢰가 아니라고 말하는 것도 타당합니다. ZK 압축 계정에는 "일반" 계정에 없는 신뢰 가정이 있습니다. 따라서 무신뢰와 완전한 ZK 롤업 사이 어딘가에 있습니다.
이름으로 특성을 유추한다면 이를 "롤업"이라고 부르는 것은 해당 특성이나 신뢰 가정의 존재를 전달하지 못한다고 생각합니다. 새로운 이름을 만들어야 할까요? 신뢰 가정이 명확하기만 하다면 ZK-Compression도 충분히 좋은 이름입니다.
관련 아티클
Helius 구독하기
최신 Solana 개발 소식을 확인하고 새 게시물 알림을 받아보세요


