ZooBC 위키
앱과 ZooBC 위에서의 개발

HTML 페이지 하나로 앱 만들기

ZooBC 애플리케이션은 뒤에 서버가 없는 HTML 파일 하나일 수 있습니다. 페이지는 노드의 HTTP API에서 체인을 읽고, 사용자의 키로 브라우저 안에서 트랜잭션을 만들고 서명한 뒤, 서명된 바이트를 제출합니다. 사용자는 노드를 운영하지 않으며, 요청할 API 키도 없습니다. 공식 지갑이 그 증거입니다. 지갑 자체가 HTML 파일 하나이며, 모든 노드가 /와 /wallet에서 이를 제공합니다(웹 지갑).

HTML 파일 하나가 GET으로 읽고, 브라우저에서 서명하고, 서명된 바이트를 노드나 게이트웨이에 제출합니다.
HTML 파일 하나가 GET으로 읽고, 브라우저에서 서명하고, 서명된 바이트를 노드나 게이트웨이에 제출합니다.

노드 API

모든 노드는 기본적으로 포트 8080에서 평문 HTTP/1.1 API를 제공하며, /api/v1/ 아래에 블록, 계정, 토큰, 앱, 거래소 등 백 개가 넘는 경로가 있습니다(노드 API). 모든 응답에 다음 헤더가 붙고 OPTIONS 요청에는 즉시 200으로 응답하므로, 어디에 호스팅된 페이지든 어느 노드든 호출할 수 있습니다.

Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS
Access-Control-Allow-Headers: Content-Type, X-Node-Public-Key, X-Timestamp, X-Signature

노드 자체에는 TLS가 없습니다. 공개 도메인에서는 게이트웨이가 TLS를 종단하며 자체 CORS 헤더를 붙입니다. 브라우저는 HTTPS로 불러온 페이지에서 평문 HTTP 호출을 막으므로, 공개 페이지는 게이트웨이와 통신합니다.

여덟 개를 제외한 모든 경로는 인증 없는 읽기이며, 트랜잭션 제출에는 어떤 키도 필요하지 않습니다. 트랜잭션이 자체 서명을 담고 있기 때문입니다. 한도는 클라이언트 주소별로 적용됩니다. 쓰기 요청은 분당 300회이며, 넘으면 Retry-After 헤더와 함께 429가 돌아옵니다. 읽기는 운영자가 한도를 정하지 않는 한 무제한입니다. 그리고 5분 안에 서명 인증이 20회 실패하면 클라이언트는 300초 동안 차단됩니다.

브라우저에서 서명하기

페이지는 트랜잭션을 하나의 체인에 묶는 다이제스트에 서명합니다.

digest = SHA3-256("ZBC-TX" ‖ genesis hash ‖ unsigned transaction bytes)

네이티브 계정은 Ed25519로 서명합니다. 페이지는 GET /api/v1/node/info에서 genesis_hash와 signing_version(2)을 읽으며, 제네시스 해시가 다이제스트 안에 있으므로 한 체인을 위해 만든 서명은 다른 체인에서 쓸모가 없습니다(체인 결속 서명). SDK는 필요하지 않습니다. Ed25519, SHA3-256, 제네시스 해시면 충분하며, 바이트 구조는 트랜잭션 봉투에 설명되어 있습니다. 공개 도구는 script 태그에 바로 넣을 수 있는 의존성 없는 JavaScript 파일을 포함해 미리 만들어진 라이브러리도 제공합니다(명령줄 도구). 키는 결코 페이지를 떠나지 않습니다.

제출과 추적

POST /api/v1/transactions               → 202, with "transaction_hash"
GET  /api/v1/transactions/<hash>/status → staging, mempool, confirmed (with block_height),
                                          rejected (with the reason and stage), or 404 not_found

202는 받아들였다는 뜻이지, 끝났다는 뜻이 아닙니다. 노드는 트랜잭션을 해석하고, 첫 검사를 실행하고, staging에 넣었을 뿐이며, 블록 생산자가 아직 이를 포함해야 합니다. 상태가 confirmed가 될 때까지 어떤 잔액도 바뀌지 않았습니다. 블록이 15초마다 하나이므로 2초 정도마다 폴링하면 충분합니다.

응답을 받지 못했다면 똑같은 서명된 바이트를 다시 보내십시오. 트랜잭션의 해시는 서명되지 않은 바이트와 서명에 대한 SHA3-256이므로, 이미 그 트랜잭션을 가진 노드는 "duplicate": true와 함께 202로 응답하고 블록에 들어간 뒤에는 "state": "confirmed"를 덧붙이며, 트랜잭션은 한 번만 실행됩니다. 새 타임스탬프로 다시 서명하면 다른 트랜잭션이 되며, 이중 지불은 그렇게 일어납니다.

기본적으로 블록은 트랜잭션의 타임스탬프 이후 3,600초까지 이를 포함할 수 있습니다. 버전 3 트랜잭션은 최대 86,400초까지 자체 유효 기간을 명시하며, 3,600초보다 더 미래의 타임스탬프는 거부됩니다(만료와 타임스탬프). 결제를 받고 상품을 내주기 전에는 확정을 기다리고, 그다음 finalized 플래그를 기다리십시오. 이 플래그는 공동 서명된 스파인 블록이 트랜잭션의 블록을 포함하면 붙습니다(최종성과 롤백). API는 또한 finalized_height, 각 블록의 block_seed_proof, 트랜잭션의 expiry, 그리고 /spine/blocks/:height에서 스파인 블록을 알려 줍니다.

202 이후: staging, mempool, confirmed, finalized. 응답을 받지 못하면 같은 바이트를 다시 보냅니다.
202 이후: staging, mempool, confirmed, finalized. 응답을 받지 못하면 같은 바이트를 다시 보냅니다.

앱을 위한 경로

앱 경로는 아카이브 서비스가 아니라 노드 자체가 제공합니다. /apps(필터 status, limit, 그리고 solo, pvp, party 중 하나인 category), /apps/open, /apps/pool, /apps/stats, /apps/:id(정산 내용 포함), /accounts/:a/apps입니다.

점검 목록

  • HTTPS로 게이트웨이를 통해 읽고, 키는 페이지 안에 둔 채 서명된 바이트를 제출하는 방식으로 씁니다.
  • 해시로 추적하고, 다시 서명하지 말고 같은 바이트를 다시 보내는 방식으로 재시도합니다.
  • 429와 Retry-After를 존중합니다.
  • 체인의 텍스트는 textContent로 보여 줍니다(체인 데이터는 신뢰할 수 없는 입력이다).
  • "confirmed"는 받은 것으로, "finalized"는 정산된 것으로 취급합니다.

같이 보기