작업 중

작업 중: MainNet에 앞서 이 사이트를 구축하고 있습니다. 세부 내용은 변경될 수 있습니다.

이 사이트는 아직 구축 중입니다

ZooBC는 공개적으로 개발되고 있습니다. 여기서 보시는 내용은 최신이며 정직하지만, 완성된 것은 아닙니다. 최종 입장이 아니라 현재의 상태로 읽어 주세요.

MainNet까지 문구, 구조, 이미지, 수치 등 많은 것이 바뀔 것입니다. 일부 페이지는 임시로 채워 둔 상태입니다.

더 넓은 ZooBC 생태계는 단계적으로 도입됩니다. 지갑, 익스플로러, 커뮤니티 채널은 MainNet이 다가오면서 하나씩 열리며, 이 사이트도 함께 성장합니다.

내용이 잘못되었거나, 깨져 보이거나, 오해의 소지가 있는 부분이 있으면 알려 주세요. 지금의 피드백이 나중의 매끄러운 출시보다 저희에게 더 큰 가치가 있습니다.

ZOOBC / 매뉴얼

ZooBC 온체인 앱

앱 매뉴얼

트랜잭션 유형 24, 25, 26, 27, 28, 39. 바디, 앱 레지스트리, 지급, 그리고 결과를 직접 검증하는 방법을 다룹니다. 노드 소스에서 그대로 옮겼습니다.

ZooBC의 앱은 규칙이 합의 안에서 실행되는 게임이나 내기입니다. 모든 수는 하나의 트랜잭션이며,

게임판은 체인 상태에 있고, 지급은 프로토콜이 합니다. 신뢰해야 할 서버도,

지급을 거부할 수 있는 운영자도, 누군가 믿고 받아들여야 하는 결과도 없습니다. 전체 과정은

누구나 언제까지나 체인 기록으로 재현할 수 있습니다.

이 매뉴얼은 통합 개발자를 위한 참조 문서입니다. 여섯 가지 트랜잭션 유형, 정확한 바디 구조, 각 앱의

수 인코딩을 담은 앱 레지스트리, 자금 이동 방식, 그리고 무작위성을 도출하고 검증하는 방법을 다룹니다.

이 문서의 모든 내용은 다음 노드 소스에서 옮겨 적었습니다: include/zoobc/common/types.h,

src/transaction/app_rules.cpp, src/transaction/transaction_executor.cpp. 설계 노트를 옮긴 것이 아닙니다.

설계 노트는 구현보다 먼저 작성되었고 곳곳에서 구현과 다릅니다.

1. 세 가지 카테고리

카테고리좌석상대방무작위성유형
솔로 (하우스 상대)1프로토콜의 앱 풀있음, 블록 시드16–21
1대1 대전2다른 플레이어앱이 사용하는 경우에만1–8
파티3–4다른 플레이어들블록 시드에서 나온 주사위32–35

세 가지 모두 하나의 엔진을 공유합니다. 같은 트랜잭션 유형, 같은 스테이크 에스크로,

같은 수별 마감 시한, 그리고 한 수는 하나의 트랜잭션이라는 같은 규칙을 씁니다.

seats 는 카테고리를 결정하며 앱 유형과 대조해 검사됩니다. 솔로 앱은 seats == 1

이어야 하고 유형이 16–31이어야 합니다. 멀티플레이어 앱은 seats가 2–4이고 유형이 그 범위 밖이어야 합니다. 이를

잘못 지정하면 실행 단계가 아니라 멤풀 진입 단계에서 거부됩니다.

2. 트랜잭션 유형

여섯 가지 유형. 모든 바디는 리틀 엔디언이며, 모든 금액은 아토믹 단위입니다(ZBC로 환산하려면 1e8로 나누세요).

유형이름바디
24CreateAppapp_type(1) · stake_token_id(8) · stake_amount(8) · seats(1) · params_len(2) · params · [opponent(36)] · [channel(1)]
25JoinAppapp_id(8)
26AppMoveapp_id(8) · move_len(2) · move_bytes
27ResignAppapp_id(8)
28ClaimAppTimeoutapp_id(8)
39SettleAppapp_id(8) · final_seq(4) · move_count(4) · [seat(1) · move_len(2) · move · signature(64)]*

CreateApp의 선택적 후행 필드 두 개

opponent 와 channel은 모두 선택 사항이며, 어느 필드가 있는지는 다음 필드 뒤에 남은 바이트 수로 판단합니다.

기준 필드 params:

남은 바이트의미
0공개 앱, 온체인 플레이
1channel 단독
36opponent 단독
37opponent 다음에 channel

opponent를 지정하면 앱이 직접 도전이 되어 그 주소만 참여할 수 있습니다. 생략하면 누구나

그 자리에 앉을 수 있습니다. channel = 1은 상태 채널 앱을 표시하며, 다음 조건에서만 유효합니다: seats == 2.

멀티플레이어 앱은 플레이어를 고정 36바이트 슬롯에 저장하므로, 자리에 앉는 모든 주소는 36바이트 정규 형식(ZBC 주소 또는 순수 32바이트 공개 키)이어야 합니다. 36바이트가 아닌 계정은 생성 시 거부됩니다. 솔로 앱에는 이런 제한이 없습니다. 플레이어가 한 명뿐이기 때문입니다.

3. 앱 레지스트리

app_type 는 단일 바이트입니다. 아래 값만 인정되며, 그 밖의 값은 거부됩니다.

1대1 대전 (2석)

유형앱게임판 / 상태수 바이트
1틱택토9칸[cell 0..8]
2체스64칸[from, to], 완전한 규칙 검사, 체크, 체크메이트, 스테일메이트, 퀸 자동 승진
3Connect-442칸 (7×6)[column 0..6], 중력, 4개 연속
4체커64칸 + 연속 점프 잠금[from, to], 강제 잡기, 연속 점프, 킹
5리버시64칸[cell 0..63], 최소 한 개는 뒤집어야 함, 둘 곳이 없으면 패스, 돌이 많은 쪽이 승리
6오목225칸 (15×15)[x, y], 5개 연속
7배틀십6400 커밋먼트 + 200 공개커밋-공개 방식, 아래 참조
8도트 앤 박스변 24개 + 상자 9개[edge 0..23], 상자를 완성하면 한 번 더 둠

솔로 (하우스 상대)

유형앱params배당
16주사위 두 개[bet_type 0..3, total]7 미만 / 7 초과 2.28×, 럭키 7 5.7×, 정확한 합계 3420/경우의 수 %
17동전 던지기[choice 0/1]1.98×
18룰렛[bet_type, value]단일 숫자 36×, 색상 2×
19슬롯없음같은 그림 3개 15×, 트리플 7 50×, 아무 페어 1.8×
20복권[pick 0..99]90×
21크래시[target ×100, 2 bytes LE]목표 ×, 1.01×에서 10.00×까지

주사위 베팅 유형은 0 7 미만, 1 럭키 7, 2 7 초과, 3 정확한 합계입니다. 정확한 합계의

배수는 100분의 1 단위로 표시한 3420 / ways 값이며, 여기서 ways = 6 - |7 - total|입니다. 따라서 7은 5.70×를, 2나

12는 34.20×를 지급합니다. 룰렛에는 37개의 칸이 있으며, 0은 초록색이라 두 색상 베팅 모두 집니다.

파티 (3–4석)

유형앱상태수 바이트
32루도seats×4 말 위치 + 대기 중인 주사위 값2단계: 주사위를 굴린 뒤 말 선택
33피그seats 점수 + 턴 합계[0 roll, 1 hold]
34레이스 (뱀과 사다리)seats 위치[0], 주사위 굴리기
35모노폴리 라이트자금, 위치, 소유권, 파산, 단계2단계: 주사위를 굴린 뒤 선택적으로 구매

4. 자금

스테이크. CreateApp은 생성자의 스테이크를 에스크로에 넣습니다. 각 JoinApp도 같은 금액의 스테이크를 에스크로에 넣습니다. 팟은

그 합계입니다. stake_token_id가 0이면 ZBC를 뜻하며, 다른 값이면 해당 컬러드 토큰을 스테이크로 걸고,

앱 전체(팟, 레이크, 지급금)가 그 토큰으로 정산됩니다.

레이크. 승패가 갈리면 팟의 1%가 앱 풀로 가고, 승자는

나머지를 받습니다. 무승부이거나 앱이 취소되면 모든 스테이크가 환불되고 레이크는 떼지 않습니다.

앱 풀은 토큰별로 잔액을 하나씩 가진 프로토콜 계정입니다. 이 풀은 그 1% 레이크와

솔로 앱의 하우스 엣지로 불어납니다. 모든 솔로 베팅의 상대방이므로, 이 풀의 잔액이 있어야

솔로 플레이가 가능합니다. 잔액은 언제든 조회할 수 있습니다:


GET https://zoobc.network/api/v1/apps/pool

뱅크롤 상한. 솔로 베팅 하나의 최대 가능 지급액은 해당 토큰 풀의 5%를

넘을 수 없습니다. 이 검사는 평균이 아니라 하우스 입장에서 본 그 베팅의 최악의 경우를 기준으로 하므로,

한 번의 당첨으로 풀이 바닥날 수 없습니다. 상한을 넘는 베팅은 거부됩니다. 큰 베팅이 거부되었다면

대개 이 때문입니다.

5. 무작위성과 그 확인 방법

솔로 앱은 블록 시드로 결과가 정해집니다. ZooBC에서 블록 시드는

block_seed = blocksmith_signature(SHA3(previous_block.block_seed))이며, 결정론적이고 누구나

블록스미스의 공개 키로 검증할 수 있으며, 블록이 생기기 전에는 알 수 없습니다.

높이 H의 블록에 들어간 베팅의 결과가 정해지는 높이는 H + 2:


r = SHA3-256( block_seed[H+2] ‖ app_id )   →   the low 8 bytes, little-endian, as a uint64

플레이어는 결과를 정할 시드가 존재하기 두 블록 전에 베팅을 확정하므로,

그 시드를 예측하거나 고를 수 없습니다. 누구나 나중에 블록 시드와 앱 id로 r을 다시 계산할 수 있고,

따라서 결과도 다시 계산할 수 있습니다. 결과는 체인에 없는 데이터에 전혀 의존하지 않습니다.

크래시는 크래시 지점을 도출할 때도 같은 값을 사용합니다. 해당 값 r:


u = r mod 1e6
C = 99_000_000 / (1_000_000 - u)      clamped to [100, 1000], i.e. 1.00× .. 10.00×

C >= target이면 베팅은 stake × target / 100을 받습니다. 분자의 99가 하우스

엣지, 즉 1%입니다. 10.00× 제한이 상한이므로, 크래시에서 가능한 최대 당첨금은 베팅액의 10배입니다.

멀티 플레이. 모든 솔로 앱은 베팅 한 번으로 최대 100회까지 플레이할 수 있습니다. 횟수를 나타내는

후행 바이트 N을 params의 해당 앱 선택 바이트 뒤에 덧붙이세요. 스테이크는 N회의 플레이에 균등하게 나뉘고

지급액은 합산되므로, 트랜잭션 하나와 공개 한 번으로 N개의 독립적인 결과가 나오며

결과마다 블록을 기다릴 필요가 없습니다. N을 생략하면 단일 플레이를 뜻하며, 단일 플레이는

멀티 플레이가 생기기 전과 비트 단위까지 동일합니다. N은 1–100이어야 하며, 스테이크는 각 플레이에

최소 1단위 이상이 걸리도록 나누어떨어져야 합니다.

6. 차례, 마감 시한, 종료

앱은 마지막 자리가 채워지면 활성화됩니다. 그 후로는 수가 승인될 때마다 다음 값이 설정됩니다:


deadline_height = current_height + 240        (~1 hour at 15 s per block)

수는 차례인 플레이어가, 앱이 활성 상태일 때, 그리고

마감 시한이 지나기 전에 둔 경우에만 승인됩니다. 앱이 끝나는 방법은 네 가지입니다:

  • 규칙상 승리 또는 무승부. 즉시 정산되어 승자에게 지급되거나, 무승부라면 모든 스테이크가 환불됩니다.
  • ResignApp. 기권합니다. 여러분의 팟 몫은 상대에게 갑니다.
  • ClaimAppTimeout. 상대가 240블록 마감 시한을 넘겼습니다. 여러분이 청구하면 팟을 가져갑니다.

청구는 여러분이 직접 해야 합니다. 마감 시한이 지났다는 이유만으로 자동으로 일어나는 일은 없습니다.

  • 아무도 참여하지 않음. 아무도 받아들이지 않은 공개 앱은 취소되고 스테이크가 환불됩니다.

7. 상태 채널과 SettleApp

1대1 대전 앱에서 모든 수를 온체인으로 두면 수마다 트랜잭션 하나와 블록 하나가 듭니다.

상태 채널은 이를 한 번의 정산으로 바꿉니다. channel = 1, seats = 2로 앱을 생성하고,

양쪽이 모든 수에 서명하며 오프체인으로 플레이한 뒤, 게임 전체를 SettleApp(유형 39)로 한 번에 제출합니다.

체인은 서명된 수들을 앱의 초기 상태부터 순서대로 같은 규칙

엔진으로 재생하고, 각 서명과 각 차례를 검증한 뒤 승자에게 지급합니다. 정산이 반영된 후

240블록 동안은 final_seq 값이 더 높은 정산이 이를 덮어쓸 수 있으며, 이 이의 제기 기간이

지나면 정산이 확정됩니다.

바디에는 세 가지 제한이 적용되며, 통합 개발자는 세 가지 모두를 지켜야 합니다:

  • final_seq 는 반드시 다음과 같아야 합니다: move_count.
  • move_count 는 1024개 항목을 넘을 수 없습니다.
  • move_count 는 남은 바디가 물리적으로 담을 수 있는 양을 넘을 수 없습니다. 각 항목은 최소 67

바이트(seat(1) + move_len(2) + signature(64))이므로, remaining / 67보다 큰 개수는

단 1바이트도 할당되기 전에 거부됩니다.

1024개 항목은 수 쌍 단위가 아니라 플라이(한쪽이 두는 한 수) 단위의 제한입니다. 항목 하나가 1플라이이므로, 1024개 항목의 정산은 512수짜리 게임을 담을 수 있습니다. 역사상 기록된 가장 긴 체스 게임은 269수, 538플라이였으므로, 이 상한은 실제로 플레이된 가장 긴 게임의 약 두 배입니다.

8. 배틀십 (유형 7)

배틀십은 숨겨진 정보가 필요한 유일한 1대1 대전 앱이므로 커밋-공개 방식을 사용합니다.

게임판은 10×10입니다. 플레이어는 100개 칸마다 무작위 32바이트 솔트를 고르고 다음 값을 커밋합니다:

SHA3(is_ship ‖ salt); 커밋먼트는 이 100개 해시를 이어 붙인 3200바이트이며, 생성 시

params 로 전달됩니다. seats는 2여야 하고 커밋먼트는 정확히 3200바이트여야 하며, 그렇지 않으면 생성이

거부됩니다.

플레이는 두 가지 수 형식을 번갈아 사용합니다:

  • 발사 [0, cell]: 상대 게임판의 한 칸을 향해 쏩니다. 차례가 상대에게 넘어가고, 상대가 공개합니다.
  • 공개 [1, cell, is_ship, salt(32)]: 상대는 그 칸 하나의

커밋먼트를 열어 그곳에 무엇이 있었는지 증명합니다. 각 칸이 따로 커밋되므로 플레이어는 어느 한 칸에 대해서도 거짓말을 할 수 없습니다.

명중 또는 빗나감이 기록되고, 공개한 쪽이 다음에 발사합니다.

함선 칸 17개를 모두 맞히면 승리합니다. 공개하지 않는 플레이어도 다른 수와 마찬가지로 마감 시한의 적용을 받으므로,

ClaimAppTimeout 규칙이 적용됩니다.

수수료는 크기에 비례합니다. 3200바이트 생성 트랜잭션은 큰 트랜잭션이며, 최소 수수료는 트랜잭션 크기에 따라 커집니다. 실제 체인에서 0.1 ZBC 수수료는 너무 낮다며 거부되었고 약 5 ZBC는 승인되었습니다. 생성할 때 이 비용을 감안하세요. 발사와 공개 수는 작고 저렴합니다.

9. 앱 상태 읽기

노드 API가 제공하는 다섯 개의 엔드포인트입니다. 아카이브 엔드포인트가 아니라 노드 엔드포인트라는 점에 유의하세요:

기본 URL은 https://zoobc.network/api/v1입니다. 이는 MainNet이 아니라 공개 ZooBC TestNet 게이트웨이입니다.

엔드포인트반환값
GET /api/v1/apps로비. 필터: status=, category=solo|pvp|party, limit=
GET /api/v1/apps/open누구나 참여할 수 있는 공개 1대1 대전 도전
GET /api/v1/apps/:id앱 하나의 전체 상태
GET /api/v1/apps/pool토큰별 앱 풀 잔액
GET /api/v1/apps/stats실시간 집계: 전체, 공개, 활성, 종료, 플레이어, 걸린 팟

앱 행에 담기는 필드: id, app_type, status(0 공개, 1 활성, 2 종료, 3 취소), seats,

creator_address, players, opponent_address, stake_token_id, stake_amount, pot,

state_blob, turn, created_height, last_move_height, deadline_height, resolve_height,

winner_address, persist_height 그리고 channel.

state_blob은 현재 도출된 게임판으로, 노드가 매 블록마다 기록을 재생하지 않아도 되도록 보관됩니다.

이는 편의를 위한 것이지 기록 자체가 아닙니다. 기록은 수 트랜잭션이며, 클라이언트는 감사나

애니메이션을 위해 이를 재생할 수 있습니다. 종료된 앱의 실시간 행은 유예 기간 후 정리되지만, 그 수들은

체인 기록에 영구히 남으므로 앱은 언제든 재구성할 수 있습니다.

10. 명령줄에서

zoobc-cli 는 여섯 가지 유형을 모두 지원합니다. 첫 번째 매개변수는 항상 보내는 사람의 개인 키입니다.

명령유형
app-create24
app-join25
app-move26
app-resign27
app-claim28
app-settle39

# a coin-flip against the house: type 17, 1 ZBC, seats=1, choice 0
zoobc-cli app-create <privkey> 17 0 100000000 1 00 --api $API

# tic-tac-toe, open to anyone, 1 ZBC
zoobc-cli app-create <privkey> 1 0 100000000 2 --api $API

# take the middle square
zoobc-cli app-move <privkey> <app_id> 04 --api $API

zoobc-cli help app-create 로 각 명령의 필드를 확인할 수 있습니다. 전체 명령 목록은 CLI 매뉴얼을,

50가지 트랜잭션 유형 전체의 바이트 레이아웃은 트랜잭션 매뉴얼을 참조하세요.

11. 상수

상수값적용 대상
레이크팟의 1%앱 풀로, 승패가 갈린 경우에만
수 마감 시한240블록약 1시간, 수가 승인될 때마다 재설정
솔로 결과 확정베팅 높이 + 2약 30초
뱅크롤 상한풀의 5%솔로 베팅 1건의 최대 지급액
멀티 플레이 상한100솔로 베팅당 플레이 횟수
정산 수 상한1024SettleApp당 항목 수, 각 67바이트 이상
정산 이의 제기 기간240블록final_seq 값이 더 높은 정산이 우선하는 약 1시간
좌석1 또는 2–41은 솔로, 2–4는 멀티플레이어
배틀십 커밋먼트3200바이트정확히 이 크기여야 하며, 아니면 생성이 거부됨