
Celestia 스크립트 작성 후 느낀 점: 코스모스는 많은 작업들이 제대로 이루어지지 않았다
작성자: 안개달, 지크 Web3
지난 12월 17일, 나는 Celestia에서 CIAS 명문이 출시된다는 것을 알게 되었고, 일시적으로 명문을 긁어모으는 스크립트를 작성하려 했다. 지금 이 시점에서 Celestia와 그가 속한 Cosmos 생태계, 그리고 CIAS 자체에 대해서도 할 말이 많다.
사실상 명문 긁기 스크립트를 작성하는 것은 어렵지 않으며, 크게 세 가지 모듈로 나뉜다: 지갑 생성, 노드 연결, 트랜잭션 범람(flooding) 처리. 앞의 두 단계는 목표 체인의 개발자 문서만 잘 살펴보면 빠르게 구현할 수 있다.
나는 먼저 Celestia 공식 홈페이지와 Github를 확인했지만, 개발자가 사용자 시나리오를 기반으로 빌드할 수 있는 사례는 거의 없었고, 주로 노드 운영과 관련된 문서들뿐이었다. 물론 이해는 가는 부분이다. Celestia는 일반 소비자를 타깃으로 한 블록체인이 아니기 때문이다. 다만 한쪽 구석에 가서야 'Cosmos 기반'이며 'CosmJS로 메인넷과 상호작용 가능하다'는 설명이 나온다.
그래서 바로 CosmJS로 넘어갔다. 하지만 Cosmos는 어쩌면 좋게 말해도 문서조차 제대로 못 만들었다고밖에 볼 수 없다. 보통 JS 라이브러리는 Github에 사용 예제가 있지만, 이곳의 튜토리얼은 하위 페이지 어딘가에 숨어 있었고, 거기에 따라 설정을 해도 결국 오류가 발생했다.
이 오류는 환경 문제도 아니며, 튜토리얼이 해당 버전 업데이트를 따르지 않았기 때문이었다. 클래스 이름이 바뀌었는데도 튜토리얼은 그대로라 호출이 안 되는 등의 문제가 반복됐다. npm 라이브러리 버전을 낮춰봤지만 일부 예제는 여전히 작동하지 않아 결국 포기하고 말았다.
결국 다시 구글 검색을 했고, 정확한 문서가 오히려 Github가 아닌 공식 웹사이트에 있다는 사실을 발견했는데, 이는 상식에 어긋나는 상황이었다. 차라리 Github의 README에 공식 문서 링크를 걸어두는 게 더 낫지 않은가?
올바른 튜토리얼을 확보한 후, 나는 지갑 생성과 노드 연결이라는 두 단계를 빠르게 완료했고, 범람 트랜잭션 모듈 구축에 착수했다. 이 모듈은 간단히 말해 트랜잭션 서명 처리 + 네트워크 요청을 for 루프로 돌리는 것이다. 그러나 여기서 또 문제에 부딪혔다:
CosmJS 라이브러리 내 모든 트랜잭션 메서드는 트랜잭션 자체의 파라미터만 노출시켜 놓았고, sequence 값은 외부에 노출되지 않았다. (sequence는 이더리움의 nonce와 유사하며, 리플레이 공격 방지를 위한 트랜잭션 카운터로, 트랜잭션이 발행될 때마다 nonce와 sequence는 자동으로 +1된다.)

sequence 값은 sign 서명 과정에서 네트워크를 통해 가져오도록 되어 있으며 (chainId 등도 마찬가지), sendTokens() → signAndBroadcast → sign() 순서로 진행된다. 매번 트랜잭션 제출 시 네트워크 요청 후 응답 대기를 해야 하므로 긁기 속도가 느려지고 불필요한 네트워크 요청이 늘어나며, 범람 처리에는 불리할 뿐 아니라 특정 트랜잭션의 가속화 혹은 취소에도 악영향을 준다.

이더리움 Web3JS의 트랜잭션 전송 메서드를 떠올려보자. 여기서는 직접 nonce 값을 지정할 수 있다. 하지만 CosmJS에서는 불가능하다. 나는 여전히 이더리움의 설계가 훨씬 합리적이라고 본다. 직접 nonce를 지정함으로써 트랜잭션 가속이나 취소가 가능하기 때문이다. 만약 어떤 트랜잭션이 막혔다면, 동일한 nonce 값을 가진 새로운 트랜잭션을 보내 막힌 트랜잭션을 대체할 수 있으며, 이는 동시에 범람 공격에도 활용할 수 있다.

시간이 촉박했고, 수정해야 할 다른 라이브러리 함수들도 있었지만, Proxy를 이용해 hook하여 재작성하는 방식은 포기하고 CosmJS 라이브러리 자체를 직접 수정하기로 결정했다.
범람 트랜잭션을 유도하는 로직은 다음과 같다. for 루프를 통해 계속해서 트랜잭션을 생성하고 서명을 만들어 RPC 노드로 전송한다. 트랜잭션 하나를 보낼 때마다 sequence/nonce 값이 +1되며, 20건의 트랜잭션을 보낸 후 다시 주기를 반복한다.
sequence 값은 각 범람 주기 시작 전에 한 번만 로컬로 가져오며, CosmJS 라이브러리 기본 설정처럼 매 트랜잭션 후마다 노드에 sequence를 다시 요청할 필요가 없다. 또한 chainId는 고정값으로 설정하여 반복적인 노드 요청을 피한다. (편집자 주: 여기서 루프 횟수는 비교적 적게 설정되어 있어, 저자가 그리 극단적이진 않았음을 알 수 있다. Conflux 명문을 긁을 당시 어떤 사람은 주기당 루프를 1000회로 설정해 분당 약 200건의 서로 다른 트랜잭션을 보낸 바 있다.)

최종적으로 나는 초라하지만 동작하는 Celestia 스크립트를 얻었고, 12월 17일 밤 CIAS가 네트워크를 끊은 후 간단히 테스트하여 수백 건의 트랜잭션을 보냈다. 12월 19일 새벽 CIAS가 다시 시작되었을 때, 실제로 몇 개의 CIAS를 획득했다(약 1800개). 하지만 여전히 불만족스러운 점들이 있다:
-
12월 17일, Celestia의 RPC 노드는 심각한 데이터 비동기화 문제를 겪었다. 서로 다른 RPC 노드의 블록 높이 차이가 크고, 계정의 sequence 값을 요청해도 반환되는 결과가 거의 일치하지 않아 매우 고통스러웠다. Celestia 블록 탐색기 역시 사용 불가 상태였다. 사실상 눈 감고 하는 상황이었다. 즉, Celestia 네트워크는 다운되진 않았지만 블록은 생산되고 있었으나, 이미 한계 직전까지 몰렸다고 볼 수 있다.
-
당일 CIAS 명문 공식팀은 Celestia가 무너질 조짐을 보이자, 48460번 블록 이후 올라간 모든 명문 민팅 트랜잭션을 무효화한다고 급작스럽게 발표했다. 이는 마치 '거래소가 네트워크를 끊는' 행위와 흡사했다. 게다가 CIAS 자체 웹사이트도 다운됐다.

-
일부 사람들은 Cosmos 체인의 원시 합의 프로토콜이 블록 합의 처리에서 성능이 낮다고 주장하지만, 이에 대해선 판단을 유보한다. 다만 CIAS가 네트워크를 끊은 의도는 묘하게 느껴진다.
-
12월 17일 당시 가장 빠르게 동기화되는 노드를 고르는 것도 어려웠다. 거의 모든 RPC 노드가 폭주 상태였고, 응답이 없는 경우가 대부분이었기 때문이다. 이후 나는 자동으로 노드를 전환하는 코드를 작성해보기도 했다.
-
CIAS 자체의 명문 형식은 다른 명문들과 달랐다. 예를 들어 brc-20의 json에서는 모든 숫자가 문자열(string) 형태이지만, cia-20에서는 숫자(number) 그대로였다.

-
CIAS 명문 비용은 그날 밤 최고치로 1.5~2U까지 치솟았고, 어떤 사람은 80U를 지불하고 단 한 장의 명문을 민팅하기도 했다. 이처럼 높은 수수료는 TPS가 제한적임을 반영하는 것이며, Celestia 창립자가 주장한 초당 1만 건 처리 능력은 명백한 과장이다.

종합하면, 12월 17일 밤의 경험을 한마디로 요약하자면: Celestia는 대규모 트래픽에 대응할 준비가 전혀 되어 있지 않았으며, RPC 노드 구성도 매우 대충이었다. (몇십 개의 RPC 노드가 1시간 만에 줄줄이 다운되는 상황을 어떻게 상상할 수 있겠는가?)
19일 밤에는 이런 상황이 많이 개선되었고, 가스비가 치솟은 것을 제외하면 큰 문제는 없었다. Celestia가 가볍게 데이터를 분배하는 DA 네트워크로서 일시적으로는 시험대를 견뎠다고 볼 수 있지만, 앞으로 또 어떤 함정이 도사리고 있을지는 알 수 없다.
TechFlow 공식 커뮤니티에 오신 것을 환영합니다
Telegram 구독 그룹:https://t.me/TechFlowDaily
트위터 공식 계정:https://x.com/TechFlowPost
트위터 영어 계정:https://x.com/BlockFlow_News










