Skip to main content

비공개 게스트 리스트 컨트랙트

이 Compact 컨트랙트는 비공개 게스트 리스트가 있는 파티를 구현합니다. 다음 기능을 시연합니다:

  • 공개 ledger에서 정보 숨기기
  • 숨겨진 ledger 정보 검증
  • circuit 접근 제어
  • Set 연산
  • witness 함수 소개
pragma language_version 0.22;
import CompactStandardLibrary;

export enum PartyState {
NOT_READY,
READY
}

export ledger organizers: Set<Bytes<32>>;// 주최자는 공개입니다
export ledger hashedPartyGoers: Set<Bytes<32>>;// 참가자는 도착할 때까지 해시 처리됩니다
export ledger checkedInParty: Set<Bytes<32>>;
export ledger partyState: PartyState;
export sealed ledger maxListSize: Uint<8>;

witness localStartParty(): PartyState;
witness localSk(): Bytes<32>;

constructor(){
const _sk = localSk();
const pubKey = publicKey(_sk);
organizers.insert(disclose(pubKey));

partyState = PartyState.NOT_READY;
maxListSize = 99;
}

export circuit addOrganizer(_organizerSk: Bytes<32>): [] {
const _sk = localSk();
const pubKey = publicKey(_sk);
assert(organizers.member(disclose(pubKey)), "You are not an organizer");

const newOrgPubKey = publicKey(_organizerSk);
assert(!organizers.member(disclose(newOrgPubKey)), "You are already in the organizer list");
assert(partyState == PartyState.NOT_READY, "The party has already started");

organizers.insert(disclose(newOrgPubKey));
}

export circuit addParticipant(_participantPk: Bytes<32>): [] {
// 주최자만 파티 참가자를 추가할 수 있습니다
const _sk = localSk();
const pubKey = publicKey(_sk);
assert(organizers.member(disclose(pubKey)), "You are not an organizer");

assert(partyState == PartyState.NOT_READY, "The party has already started");
assert(hashedPartyGoers.size() < maxListSize, "The list is full");

const participant = commitWithSk(_participantPk, _sk);
assert(!hashedPartyGoers.member(disclose(participant)), "You are already in the list");
hashedPartyGoers.insert(disclose(participant));

if (hashedPartyGoers.size() == maxListSize) {
const localPartyState = localStartParty();
// 신뢰하지 말고 검증하세요
assert(localPartyState == PartyState.READY, "Please start the party, the list is full");
partyState = PartyState.READY;
}
}

export circuit checkIn(participantPk: Bytes<32>): [] {
const _sk = localSk();
const pubKey = publicKey(_sk);
assert(organizers.member(disclose(pubKey)), "You are not an organizer");

assert(partyState == PartyState.READY, "The party has not started yet");
assert(checkedInParty.size() < hashedPartyGoers.size(), "All guests have already checked in");
assert(hashedPartyGoers.member(commitWithSk(participantPk, _sk)), "You are not on the list");

checkedInParty.insert(disclose(participantPk));
}

export circuit chainStartParty(): [] {
const _sk = localSk();
const pubKey = publicKey(_sk);
assert(organizers.member(disclose(pubKey)), "Only organizers can start the party");

assert(partyState == PartyState.NOT_READY, "The party has already started");

const localPartyState = disclose(localStartParty());
assert(localPartyState == PartyState.READY, "Please start the party locally");
partyState = localPartyState;
}

circuit commitWithSk(_participantPk: Bytes<32>, _sk: Bytes<32>): Bytes<32> {
const hash = persistentHash<Vector<2, Bytes<32>>>([_participantPk, _sk]);
return disclose(hash);
}

// 사용자가 추적될 수 없도록 이 DApp에 특화된 publicKey를 해시합니다
export circuit publicKey(_sk: Bytes<32>): Bytes<32> {
return persistentHash<Vector<2, Bytes<32>>>([pad(32, "guest-list:pk:"), _sk]);
}