Skip to main content
For the complete documentation index, see llms.txt

DUST architecture

DUST 아키텍처를 이해할 때는 다음 비유가 도움이 됩니다.

  • NIGHT: 태양광 패널에 해당합니다. 사용자가 보유하는 가치 있는 자산입니다.
  • DUST: 전기에 해당합니다. 태양광 패널(NIGHT)이 만들어 내는 컴퓨팅 처리량 또는 가스를 의미합니다.
  • Usage: 네트워크에서 작업을 수행하기 위해 전기(DUST)를 가스로 소비합니다.

"코인 5개를 보유하고 있다"처럼 잔액이 정적인 일반 암호화폐와 달리, DUST 잔액은 시간과 NIGHT 토큰 상태에 따라 동적으로 변합니다.

DUST and network usage​

DUST는 Zswap과 비슷하게 동작하지만 별도로 운영되며, Midnight의 리소스 크레딧 시스템 역할을 합니다. DUST는 다음과 같은 속성을 가집니다:

  • shielded 및 양도 불가: DUST는 가스 전용으로 쓰이는 shielded 용량 리소스입니다. 사용자 간 전송은 불가능합니다.
  • 동적 용량: DUST UTXO에서 사용 가능한 가스는 연관된 NIGHT UTXO를 기반으로 동적으로 계산됩니다.
  • 생성과 소멸: 계산된 값은 NIGHT UTXO에 따른 최댓값까지 시간이 흐르며 증가하고, NIGHT UTXO가 소비되면 0까지 감소합니다.
  • 비영속적: 시스템이 하드포크 시점에 재분배할 수 있습니다.
note

Midnight 프로토콜은 가비지 컬렉션 등을 위해 DUST 할당 규칙을 변경할 권리를 보유합니다.

Design overview​

Zswap과 마찬가지로 DUST는 해시와 commitment/nullifier 패러다임 위에 구축됩니다. 각 DUST UTXO는 생성 시 추가 전용(append-only) 머클 트리에 삽입되는 commitment를 가지며, 소비 시에는 nullifier 집합에 추가되는 nullifier를 가집니다.

DUST의 "소비(spend)"는 1대1 "전송"(자기 전송, Self-Spend)입니다.

  • 입력: DUST UTXO 1개 (nullifier)
  • 출력: DUST UTXO 1개 (commitment)
  • 수수료: 지불된 수수료에 대한 공개 선언

여기에는 다음을 증명하는 영지식 증명이 포함됩니다.

  • 입력이 유효하며 머클 트리에 존재합니다.
  • 출력 값은 업데이트된 입력 값에서 소비된 가스를 뺀 값과 같습니다.
  • 출력 nullifier가 올바르며, 소유자는 동일하게 유지됩니다.

Lifecycle: NIGHT generates DUST​

개념적으로 DUST를 보유한 NIGHT UTXO는 시간이 지남에 따라 DUST를 생성합니다. 백킹 NIGHT UTXO가 소비되지 않는 한, 연관된 DUST UTXO는 N × ρ 상한까지 가치를 생성합니다. 백킹 NIGHT이 소비되면 DUST UTXO는 0으로 "소멸(decay)"됩니다.

다음 다이어그램은 이 라이프사이클을 보여 줍니다.

생성 속도는 보유한 NIGHT 양(N), DUST 상한과 NIGHT 보유량의 비율(ρ), "상한까지 도달하는 시간"(Δ)에 따라 결정됩니다.

Units and denominations​

두 토큰 모두 고정된 원자 단위를 가지며, ledger 소스(ledger/src/structure.rs)에 상수로 정의되어 있습니다:

  • Star: NIGHT의 원자 단위. STARS_PER_NIGHT = 1,000,000이므로 1 NIGHT = 106 Star입니다.
  • Speck: DUST의 원자 단위. SPECKS_PER_DUST = 1,000,000,000,000,000이므로 1 DUST = 1015 Speck입니다.

night_dust_ratio의 초기값은 ledger 소스에서 이 상수들로부터 유도됩니다: 5 × (SPECKS_PER_DUST ÷ STARS_PER_NIGHT) = 5,000,000,000 Specks per Star이며, 이 페이지 전체에서 사용하는 NIGHT당 5 DUST 상한이 바로 이 값입니다.

note

토크노믹스 백서를 포함한 이전 자료에서는 1 DUST가 106 Speck이라고 설명합니다. 위의 ledger 상수가 기준입니다. 올바른 비율은 1015입니다.

Generation rate and capacity​

두 개의 ledger 파라미터가 DUST가 쌓이는 속도와 누적될 수 있는 최대량을 결정합니다(초기값은 아래 Initial DUST parameters에 나옵니다):

  • generation_decay_rate: 백킹 NIGHT 1 Star당, 초당 생성되는 DUST의 Speck 수. 백킹 NIGHT이 소비된 뒤에는 같은 속도가 반대로 적용되며, 이것이 이름에 담긴 "decay(감쇠)"의 의미입니다.
  • night_dust_ratio: 백킹 NIGHT 1 Star당 DUST의 최대 Speck 수.

백킹 NIGHT UTXO가 소비되지 않은 동안, UTXO 생성 시점으로부터 t초가 지난 시점의 연관 DUST 값(Speck 단위)은 N × g × t와 N × ρ 중 더 작은 값입니다. 여기서 N은 UTXO의 Star 단위 값, g는 generation_decay_rate, ρ는 night_dust_ratio입니다.

속도와 상한이 모두 N에 선형 비례하므로, 상한에 도달하는 시간은 NIGHT 양과 무관하게 동일합니다: Δ = ρ ÷ g = 5,000,000,000 ÷ 8,267이며, ledger는 이를 604,815초로 올림합니다. 여기서 "약 일주일"이라는 생성 시간이 나옵니다.

예를 들어, 등록된 DUST 주소를 가진 100 NIGHT(100,000,000 Star)짜리 NIGHT UTXO 하나를 보유한다고 합시다:

  • DUST 잔액은 초당 약 827억 Speck, 대략 초당 0.00083 DUST, 즉 하루 71 DUST씩 증가합니다.
  • 약 일주일 뒤 상한에 도달하며, 총 500 DUST, 즉 NIGHT당 5 DUST가 됩니다.
  • 같은 100 NIGHT을 여러 UTXO로 나눠도 총량은 달라지지 않습니다. 각 UTXO는 자기 값에 비례해 생성되고 상한에 도달합니다.

Spending rules​

소비 규칙은 다음과 같습니다.

  • DUST는 여러 번 소비할 수 있으며, 값이 0이더라도 항상 새 UTXO가 생성됩니다.
  • 소멸 단계에서도 DUST를 소비할 수 있으며, 이 경우 소멸 속도는 변하지 않습니다.
  • 백킹 NIGHT이 소비되면, 아직 생성 단계에 있더라도 DUST는 즉시 소멸을 시작합니다.
  • NIGHT의 일부만 소비되면, 잔돈으로 새 NIGHT UTXO가 만들어져(새로운 DUST 생성을 시작) 기존 DUST UTXO는 소멸됩니다.

Implementation note​

실제 구현에서는 값을 연속적으로 처리하지 않습니다. 대신 메타데이터("generation info")를 사용해 소비 시점에 값을 계산합니다.

  • DUST UTXO의 생성 시각
  • 백킹 NIGHT UTXO의 생성 시각
  • 백킹 NIGHT UTXO의 삭제 시각

DUST와 NIGHT은 서로 다른 키를 사용하므로, **등록 테이블(Registration Table)**이 NIGHT 공개 키와 DUST 공개 키를 연결합니다. NIGHT UTXO가 생성되고 동시에 해당 키가 테이블에 등록되어 있을 때만 새 DUST UTXO가 생성됩니다.

The grace period​

DUST 사용은 shielded 상태이므로, 시스템은 트랜잭션 생성 시점을 기준으로 값을 계산합니다. 네트워크 지연을 고려해 프로토콜은 DUST Grace Period(예: 3시간)를 정의합니다. 트랜잭션의 타임스탬프가 블록 시간 기준으로 이 범위 내에 있으면 수락됩니다.

Preliminaries​

DUST는 ZK 친화적 해시를 사용합니다.

type DustSecretKey = Fr;
type DustPublicKey = field::Hash<DustSecretKey>;

DUST UTXO는 소유자, 값, *논스(nonce)*를 가집니다. 논스는 지갑 복구가 가능하도록 결정적인 방식으로 변화합니다.

  • 첫 번째 DUST UTXO: 논스는 원본 NIGHT UTXO의 인텐트 해시에서 파생됩니다.
  • 이후 DUST UTXO: 논스는 이전 시퀀스 번호와 소유자의 비밀 키에서 파생됩니다.
struct DustOutput {
initial_value: u128, // Specks at creation
owner: DustPublicKey,
nonce: field::Hash<(InitialNonce, u32, Fr)>,
seq: u32,
ctime: Timestamp,
}

상태 구성 요소에는 commitment 트리, nullifier 집합, 루트 히스토리가 포함됩니다.

struct DustUtxoState {
commitments: MerkleTree<DustCommitment>,
commitments_first_free: usize,
nullifiers: Set<DustNullifier>,
root_history: TimeFilterMap<MerkleTreeRoot>,
}

Initial DUST parameters​

DUST와 NIGHT은 서로 다른 단위를 사용하며, 위의 Units and denominations에 정의되어 있습니다. 초기 파라미터는 다음과 같습니다:

const INITIAL_DUST_PARAMETERS: DustParameters = {
night_dust_ratio = 5_000_000_000; // 5 DUST per NIGHT
generation_decay_rate = 8_267; // ~1 week generation time
dust_grace_period = Duration::from_hours(3),
};

DUST actions​

사용자는 *인텐트(Intents)*를 통해 DUST 상태에 영향을 줍니다.

struct DustActions<S, P> {
spends: Vec<DustSpend<P>>,
registrations: Vec<DustRegistration>,
ctime: Timestamp,
}

Registrations and fees​

DustRegistration은 NIGHT 키를 DUST 키에 연결합니다. 등록은 순차적으로 처리됩니다.

최초 DustRegistration에는 부트스트랩 문제가 있습니다. 트랜잭션 자체에 DUST가 들지만, 지갑은 NIGHT 키가 등록되기 전까지 DUST를 보유할 수 없습니다. ledger는 이를 *소급 생성(retroactive generation)*으로 해결합니다.

아직 DUST를 생성하지 않는 NIGHT UTXO도 생성 중인 UTXO와 동일한 속도·상한 공식에 따라, 그 UTXO 자신의 생성 시점부터 DUST를 "가상으로" 축적해 온 것으로 봅니다. 등록은 fee allowance(allow_fee_payment)를 선언해 이 소급 DUST를 끌어다 자기 가스 비용을 지불할 수 있습니다. 기존 DUST나 두 번째 지갑이 필요하지 않습니다.

자체 조달 경로에는 두 가지 제한이 적용됩니다:

  • 등록 트랜잭션의 guaranteed section에서 소비된, 아직 생성 중이 아닌 NIGHT UTXO만 소급 allowance에 산입됩니다.
  • 선언한 allowance는 그 입력들이 축적한 양을 초과할 수 없습니다. 더 많이 요청하는 트랜잭션은 InsufficientDustForRegistrationFee로 검증에 실패합니다.

소급 DUST는 각 UTXO의 생성 시점부터 축적되므로, 갓 받은 NIGHT UTXO는 거의 아무것도 축적하지 못한 상태입니다. 소급 DUST가 아직 등록 수수료를 감당하지 못한다면, 더 축적될 때까지 기다리거나 이미 등록된 지갑에서 수수료를 조달하세요.

등록 이후 NIGHT UTXO를 다시 소비하면 새 등록 아래 생성 중인 UTXO로 재생성됩니다. 등록 트랜잭션이 보통 지갑의 NIGHT을 자기 자신에게 소비하는 이유가 이것입니다. 지속적인 DUST 생성은 그 재소비에서 시작됩니다.

Generate DUST​

NIGHT 입력/출력은 DUST Generation Tree에 대한 업데이트를 트리거합니다.

  • DustGenerationInfo: NIGHT의 양, 소유자, dtime(삭제 시각)을 저장합니다.
  • Address map: NIGHT 주소와 DUST 주소를 연결합니다.
struct DustGenerationInfo {
value: u128,
owner: DustPublicKey,
nonce: InitialNonce,
dtime: Timestamp, // Set to MAX if Night is unspent
}

DUST value and spends​

DUST UTXO의 값은 네 개의 선형 시간 구간을 기준으로 계산됩니다.

  1. Generating: 생성 시점부터 용량 도달(또는 NIGHT 소비) 시점까지.
  2. Constant (maximum): 용량 도달 후 NIGHT 소비 전까지.
  3. Decaying: NIGHT 소비 시점부터 값이 0에 도달할 때까지.
  4. Constant (zero): 그 이후로 영구히.

The spend transaction​

DustSpend는 UTXO를 소비하고, 업데이트된 값에서 수수료를 차감한 새 UTXO를 만듭니다.

검증 로직(dust_spend_valid)은 다음을 확인합니다.

  • commitment_merkle_tree에 입력이 포함되어 있는지.
  • dust_spend.old_nullifier가 파생된 nullifier와 일치하는지.
  • updated_value가 수수료를 충당하기에 충분한지.
  • new_commitment이 올바르게 구성되었는지.

Wallet recovery​

지갑은 다음 과정으로 자금을 복구합니다.

  • 보유 중인 NIGHT UTXO를 식별합니다(체인의 시작점).
  • 시퀀스 번호(0, 1, 2, ...)에 대응하는 commitment를 선형적으로 탐색합니다.
  • 프라이버시: 지갑은 인덱싱 서비스에 대한 프라이버시를 보호하기 위해, 정확한 조회 대신 비트 접두사 기반(확률적 필터링) 쿼리를 사용해야 합니다.

The implementation​

이 섹션에서는 Cardano NIGHT 토큰을 기반으로 한 DUST 생성 구현을 설명합니다.

DUST generation from Cardano NIGHT token​

Cardano NIGHT 토큰(cNIGHT)으로부터의 DUST 생성은 Midnight 파트너 체인에서 Native 토큰 Observation Pallet(pallet_cnight_observation)이 관리하는 크로스체인 프로세스입니다.

Summary of the full flow​

1/ 사용자가 Cardano에서 보상 주소와 DUST 공개 키를 등록합니다.

2/ 해당 주소에서 cNIGHT UTXO가 생성(수신)되거나 소비(전송)될 때마다 이벤트가 브로드캐스트됩니다.

3–4/ Midnight 팔레트는 정확히 하나의 유효한 등록이 존재하는지 검증한 뒤 cNIGHT 활동을 관찰합니다.

5–6/ 해당 주소가 cNIGHT을 수신했는지 소비했는지 판별하여 그에 해당하는 이벤트를 만듭니다. Create 이벤트는 DUST UTXO를 생성합니다. Destroy 이벤트는 DUST UTXO를 제거하지 않습니다. cNIGHT이 소비된 시각을 기록하고, DUST UTXO는 그 시점부터 소멸합니다.

7–9/ 한 블록 내의 모든 이벤트를 모아 LedgerApi를 통해 단일 시스템 트랜잭션으로 래핑하고, 이를 Midnight ledger에서 실행합니다.

→ 최종 결과: 등록된 주소에서 생성된 각 cNIGHT UTXO는 Midnight에서 DUST UTXO 하나를 받으며, 그 DUST UTXO는 cNIGHT UTXO가 소비될 때 소멸을 시작합니다.

Next steps​

DUST 개요를 살펴봤다면, 이제 GitHub의 DUST 사양도 함께 확인해 보세요.

GitHub의 구현 코드를 살펴보고 직접 기여할 수도 있습니다.