Skip to main content

Ledger v8.1.3 release notes

For the complete documentation index, see llms.txt
  • Version: v8.1.3
  • Date: October 2, 2026

High-level summary​

Ledger 8.1.3은 보안 패치입니다. 치명적(critical) 권고 GHSA-wr7g-rr4v-jmj8을 수정합니다. 이 릴리스 이전에는 같은 field 값의 두 인코딩이 동일한 proof input을 만들었지만, ledger는 이를 서로 다른 값으로 비교하고 저장했습니다. 공격자는 이를 악용해 스마트 컨트랙트의 일회성 검사를 우회할 수 있었습니다. 예를 들어 같은 보상을 두 번 이상 청구하는 식입니다. Ledger 8.1.3은 contract call transcript에 포함된 field 값에 대해 정규(canonical) 인코딩을 요구합니다. 또한 transcript에서 관련된 두 형식, 즉 비어 있지 않은 상태로 push된 Merkle tree와 count가 0인 noop도 거부합니다.

노드 운영자는 ledger 8.1.3을 포함한 노드 1.0.400을 실행해야 합니다. Compact 컴파일러와 Midnight.js로 만든 DApp은 변경이 필요 없습니다. 짝이 되는 proof server 이미지 midnightntwrk/proof-server:8.1.3은 8.1.0 이후 Docker Hub에 올라온 첫 8.x proof server 이미지입니다.

Audience​

이번 릴리스 노트는 다음 대상에게 가장 관련이 깊습니다.

  • 노드 운영자 및 validator
  • Set<Field>나 Map<Field, V>처럼 Field를 포함하는 키를 가진 Set 또는 Map을 일회성 가드로 사용하는 스마트 컨트랙트 개발자
  • @midnightntwrk 또는 @midnight-ntwrk 스코프의 ledger-v8이나 onchain-runtime-v3 npm 패키지에 직접 의존하는 DApp 개발자
  • proof server를 운영하는 개발자
  • ledger Rust crate를 사용하거나 자체 도구로 트랜잭션을 구성하는 개발자

Summary of updates​

  • 보안: contract call transcript는 정규 field 값을 사용해야 하며, 이로써 GHSA-wr7g-rr4v-jmj8을 수정합니다.
  • 보안: push나 pushs 연산 안의 Merkle tree는 비어 있어야 합니다.
  • 보안: contract call transcript에는 count가 0인 noop이 포함될 수 없습니다.
  • 호환성: 유효한 트랜잭션과 저장된 상태는 8.1.2와 동일한 바이트로 직렬화되며, TypeScript 선언도 바뀌지 않습니다. 8.1.3 노드는 8.1.2 노드가 받아들이는 일부 contract call을 거부합니다.
  • Rust API: onchain-vm에서 Key::Value는 이제 AlignedValue 대신 AlignedValueChecked를 담고, Op::Push는 StateValue<D, AlignedValueChecked>를 담습니다.
  • Proof server: midnightntwrk/proof-server:8.1.3이 Docker Hub에 올라와 있으며, 서명된 build manifest는 proof-server-8.1.3 GitHub 릴리스에 있습니다.
  • Packages: @midnightntwrk/ledger-v8 8.1.3과 @midnightntwrk/onchain-runtime-v3 3.1.2가 npm에 있으며, 이전 @midnight-ntwrk 스코프로도 제공됩니다. ZKIR은 2.1.1로 유지됩니다.

New features​

Proof server image with a signed build manifest​

proof server 이미지 midnightntwrk/proof-server:8.1.3이 linux/amd64와 linux/arm64용으로 Docker Hub에 올라와 있으며, latest 태그가 이를 가리킵니다. Docker Hub에는 ledger 8.1.1이나 8.1.2용 proof server 이미지가 없으므로, 이 이미지에는 해당 변경 사항도 함께 포함되어 있습니다. API, 포트 6300, 명령줄 옵션은 바뀌지 않으며 GET /version은 8.1.3을 반환합니다.

proof-server-8.1.3 GitHub 릴리스에는 이미지 digest와 소스 커밋을 기록한 서명된 build-manifest.json이 포함되어 있습니다. manifest를 검증하려면 릴리스에 첨부된 세 파일을 내려받아 다음을 실행하세요.

gpg --import midnight-proof-server-public.asc
gpg --verify build-manifest.json.asc build-manifest.json

gpg가 fingerprint 2D55 ACA7 93E9 495E 4288 9A35 4523 91B0 57AD D8C7인 키로부터 정상 서명(good signature)을 보고하는지 확인하세요. gpg는 해당 키가 신뢰된 서명으로 인증되지 않았다는 경고도 표시합니다. 방금 import한 키라면 예상되는 동작이며, 키를 식별하는 것은 fingerprint입니다.

그다음 manifest의 image_digest가 docker pull midnightntwrk/proof-server:8.1.3이 출력하는 digest와 일치하는지 확인하세요. manifest의 image 필드는 GitHub Container Registry에 있는 이미지 사본을 가리킵니다. 릴리스는 두 사본에 대해 하나의 digest를 명시하므로, Docker Hub pull에서 얻은 digest와 비교하면 됩니다.

New features requiring configuration updates​

이번 릴리스에는 해당 사항이 없습니다.

Deprecations​

이번 릴리스에는 deprecation이 없습니다.


Breaking changes or required actions​

Compact 컴파일러와 Midnight.js로 만드는 트랜잭션에는 바뀌는 점이 없습니다. 유효한 트랜잭션은 8.1.2와 동일한 바이트로 직렬화되며, 8.1.3은 8.1.2가 기록한 상태를 읽습니다. 유효성 규칙이 더 좁아집니다. 8.1.3 노드는 8.1.2 노드가 받아들이는 일부 contract call을 거부하므로, 모든 블록 생산자는 8.1.3을 실행해야 합니다.

  • 노드 운영자 및 validator: ledger 8.1.3을 포함한 노드 1.0.400을 실행하고, 모든 블록 생산자를 함께 전환하세요. 이 업그레이드는 노드 바이너리만 교체하며 resync가 필요 없습니다.
  • Proof server 사용자: midnightntwrk/proof-server:8.1.3을 사용할 수 있으며 설정은 바뀌지 않습니다. 각 네트워크에서 테스트된 proof server 버전은 호환성 매트릭스에 정리되어 있습니다.
  • DApp 개발자: 8.1.3 노드는 프로젝트가 어떤 ledger 버전을 쓰든 새 규칙을 적용하므로, 코드나 의존성을 바꿀 필요가 없습니다. Midnight.js 없이 ledger-v8이나 onchain-runtime-v3을 @midnightntwrk 또는 @midnight-ntwrk 스코프로 사용한다면, 8.1.3과 3.1.2로 업데이트해 Transaction.wellFormed 같은 로컬 검사가 8.1.3 노드와 동일한 규칙을 적용하게 할 수 있습니다. Midnight.js 4.1.1 프로젝트에서는 Midnight.js가 사용하는 사본인 @midnight-ntwrk/ledger-v8 8.1.0을 쓰세요(Known issues 참고).
  • 스마트 컨트랙트 개발자: 스마트 컨트랙트가 보상·출금·발행의 일회성 가드로 Set이나 Map을 사용하고 그 키에 Field가 포함된다면, 권고를 읽고 컨트랙트 상태를 점검하세요. Set<Field>와 Map<Field, V>뿐 아니라 Field 멤버를 가진 tuple·struct 타입의 키, MerkleTreeDigest 키, JubjubPoint 키에도 해당합니다. Ledger 8.1.3은 컨트랙트가 이미 저장한 키를 다시 쓰지 않습니다.
  • 커스텀 트랜잭션 빌더: 자체 도구로 트랜잭션을 구성한다면 on-chain runtime specification의 새 규칙을 따르도록 하세요.

Rust API changes​

Rust crate를 직접 사용한다면 onchain-vm의 두 enum variant가 바뀝니다. Key::Value는 이제 AlignedValue 대신 AlignedValueChecked를 담고, Op::Push는 StateValue<D, AlignedValueChecked>를 담습니다. StateValue는 이제 두 번째 타입 파라미터를 받으며 기본값은 AlignedValue입니다. 8.1.3이 patch 릴리스이긴 하지만, 이 값들을 직접 구성하는 Rust 코드는 8.1.3에 대해 컴파일하려면 값을 변환해야 합니다. 값은 AlignedValueChecked::try_from으로, StateValue는 StateValue::try_into_checked로 변환하세요. 이 crate는 try_into_checked가 값을 tree로 순회하므로 critical path에는 적합하지 않다고 명시합니다. 자식을 공유하는 값은 직렬화 크기에 대해 지수 시간이 걸릴 수 있기 때문입니다.

crate 버전은 midnight-ledger와 midnight-zswap이 8.1.3, midnight-onchain-runtime과 midnight-onchain-vm이 3.1.2, midnight-onchain-state가 3.0.2, midnight-base-crypto가 1.0.2입니다.


Bug fixes and quality improvements​

ComponentDescription
onchain-runtimecontract call transcript에 포함된 모든 field 값은 정규여야 하며, 이는 field modulus보다 엄격히 작아야 함을 뜻합니다. push와 pushs 연산의 값(cell과 map 키 포함), 그리고 idx·idxc·idxp·idxpc path의 리터럴 키가 해당합니다. 8.1.3 노드는 트랜잭션을 디코딩할 때 비정규 값을 거부합니다. GHSA-wr7g-rr4v-jmj8을 수정합니다.
onchain-runtimepush나 pushs 연산 안의 Merkle tree는 해당 높이의 빈 tree여야 합니다. proof는 tree의 root를 포함하지 않고, ledger는 트랜잭션을 디코딩할 때 root를 다시 계산하지 않습니다. Compact로 컴파일된 컨트랙트는, 예를 들어 MerkleTree ledger 필드를 리셋할 때처럼 빈 tree만 push합니다.
ledgertranscript에 count가 0인 noop이 포함된 contract call을 거부하고, 해당 트랜잭션이 normal form이 아니라고 보고합니다. 그 연산은 proof의 public input에 아무것도 추가하지 않으면서 branch와 jmp의 대상만 이동시켰습니다.
base-cryptoAlignment::fits_field_check, Alignment::consume_field_check, AlignmentAtom::fits_field_check를 추가합니다. 이들은 Field alignment를 가진 atom에 호출자가 제공한 추가 검사를 적용합니다. 기존 함수는 종전대로 동작합니다.

Known issues​

  • Ledger 8.1.3은 기존 컨트랙트 상태를 복구하지 않으므로, 업그레이드 전에 컨트랙트가 저장한 비정규 키는 그대로 남습니다. 무엇을 점검해야 하는지는 권고의 caveat에 설명되어 있습니다.
  • Midnight.js 4.1.1은 정확 버전 @midnight-ntwrk/ledger-v8 8.1.0과 @midnight-ntwrk/onchain-runtime-v3 3.0.0에 의존하므로, Midnight.js가 사용하는 사본은 해당 버전에 머뭅니다. Midnight.js 4.1.1 프로젝트의 직접 의존성으로 @midnight-ntwrk/ledger-v8 8.1.3을 추가하면 npm이 8.1.0 사본 옆에 설치하며, 두 사본 사이로 전달되는 ledger 객체는 expected instance of 오류로 실패할 수 있습니다.
  • Dependabot, npm audit, cargo audit은 8.1.2 이하의 ledger 패키지나 crate를 플래그하지 않습니다. 이 권고가 해당 도구들의 advisory 데이터베이스에 없기 때문입니다. 버전은 직접 확인하세요.