Quantum Cats는 시간이 지남에 따라 진화하여 다양한 예술 작품을 드러내는 3333개의 오르디널 인스크립션 컬렉션입니다. 이는 시간이 지남에 따라 진화하는 인스크립션의 첫 번째 컬렉션으로, 높은 수수료와 예측할 수 없는 미래 수수료 시장의 시기에 만들어졌습니다. 이 글은 예술 작품의 미적 가치나 시장 참여 이유에 대한 글이 아니라, Quantum Cats의 기술적 구현에 대한 글입니다. 우리가 직면한 엔지니어링 도전과 그 도전에 대응하기 위해 구현한 기술은 흥미롭고 미래의 오르디널 제작자와 다른 비트코인 애플리케이션 개발자에게 유용할 수 있다고 생각합니다.
Quantum Cats의 기술적 세부 사항에 들어가기 전에 우리가 만들고자 했던 경험을 이해하는 것이 유용할 것입니다. 오르디널 사용자들은 특정 오르디널의 전송을 허용하는 코인 제어 및 거래 구성 기능이 있는 자기 보관 비트코인 지갑에서 인스크립션(오르디널 프로토콜에 구현된 디지털 수집품)을 보유하고 있습니다. 우리는 시간이 지남에 따라 진화하는 인스크립션 컬렉션을 만들고자 했습니다. 즉, 고양이의 속성이나 특성을 추가하거나 변경하는 것입니다.
인스크립션의 예술 작품은 Taproot 거래의 증인에 온체인으로 게시됩니다(특별 인코딩인 Envelope에서 – 오르디널 인식 소프트웨어는 인스크립션을 찾기 위해 이 Envelope를 찾습니다). 이는 특정 인스크립션 데이터가 불변하며 한 번 게시되면 변경할 수 없음을 의미합니다(재조직을 제외하고). 그러나 우리는 예술 작품이 실제로 변경되지 않더라도 변경된 예술 작품의 경험을 제공할 수 있는 몇 가지 방법이 있습니다(사실, 이전 예술 작품에 접근할 수 있는 것은 더 마음에 드는 경우 좋습니다!).
재귀는 하나의 인스크립션이 다른 인스크립션의 내용을 참조할 수 있는 오르디널 기능입니다. 예를 들어, HTML 페이지를 인스크립션하고 다른 인스크립션에 있는 이미지를 포함할 수 있습니다. 오르디널 소프트웨어는 HTML 페이지를 iframe으로 렌더링하므로, 클라이언트 측에서 여러 인스크립션으로부터 오르디널의 콘텐츠를 구성할 수 있습니다. HTML 인스크립션은 더 넓은 웹의 콘텐츠를 포함할 수 없으며, 오르디널 소프트웨어에서 제공하는 다른 인스크립션이나 소수의 다른 엔드포인트에서만 콘텐츠를 포함할 수 있습니다(예: 현재 비트코인 블록 높이를 가져오는 엔드포인트가 있습니다). 이는 재귀 인스크립션이 모두 여전히 온체인에 있으며, 분해되어 공통 구성 요소의 조합성과 재사용을 허용함을 의미합니다. 예를 들어, 모든 Quantum Cats는 빨간 배경을 가진 단일 인스크립션을 참조할 수 있으며, 모든 고양이가 동일한 데이터를 온체인에 올릴 필요가 없습니다.
하나의 인스크립션이 다른 인스크립션을 참조할 때, 그것은 인스크립션 ID로 참조합니다. 인스크립션 ID는 인스크립션 데이터가 드러나는 비트코인 거래 ID, 문자 i, 그리고 생성된 인스크립션의 출력 인덱스로 구성됩니다. 예를 들어, 인스크립션 4b31771df21656d2a77e6fa18720a6dd94b04510b9065a7c67250d5c89ad2079i0는 비트코인 거래 4b31771df21656d2a77e6fa18720a6dd94b04510b9065a7c67250d5c89ad2079에서 생성된 첫 번째 인스크립션입니다. 이는 이미지(예: png)를 인스크립션하고 그 이미지의 인스크립션 ID를 img 태그에 포함하는 HTML 페이지를 인스크립션하면, HTML 인스크립션이 이미지 인스크립션의 내용을 렌더링할 수 있음을 의미합니다. HTML 인스크립션이 실제로 온체인에 없는 이미지 인스크립션을 참조하면, 오르디널 서버는 404(찾을 수 없음) 오류를 반환하며, HTML 인스크립션은 이를 조용히 무시할 수 있습니다. 우리가 이미지 인스크립션을 미리 서명하되 비트코인 네트워크에 방송하지 않으면, 그들의 미래 인스크립션 ID를 얻을 수 있으며(그들은 단지 거래 ID와 인덱스입니다), 우리가 방송하는 HTML 인스크립션에 이러한 인스크립션 ID를 포함할 수 있습니다. 누군가 HTML 인스크립션을 볼 때, 온체인에 있는 참조의 내용을 렌더링할 수 있지만, 방송되지 않은 미리 서명된 구성 요소는 렌더링할 수 없습니다. 더 많은 구성 요소가 게시되면, HTML 인스크립션은 자동으로 이를 렌더링할 수 있습니다. 이것이 Quantum Cats 컬렉션이 예술 작품을 진화시키는 핵심 메커니즘입니다 – 시간이 지남에 따라 점진적으로 드러나는 특성에 대한 미리 서명된 거래입니다. 수수료 관리 및 시장 역학이 복잡성을 도입했지만, 미리 서명된 거래와 미리 계산된 거래 ID는 이 컬렉션을 가능하게 한 비트코인의 핵심 기능입니다.
미리 서명된 그러나 공개되지 않은 인스크립션의 내용은 거래가 방송되기 전까지는 알 수 없지만, 동일한 인스크립션 ID는 동일한 내용을 가집니다. 이는 문제를 일으켰습니다: 사람들이 미래의 특성이 무엇일지(예: 배경이나 몸 특성)를 알 수 없지만, 특정 인스크립션 ID가 발생한 횟수를 셀 수 있어 어떤 미래 특성이 더 희귀한지 알 수 있으며, 고양이를 미래의 진화에 따라 거래할 수 있습니다. 우리는 진화가 놀랍고 재미있기를 원했으며, 미래의 진화가 서로 다른 고양이의 상대적 희귀성에 어떤 영향을 미칠지 미리 알지 못하는 것이 매우 재미있습니다. 그래서 우리는 간접 참조의 레이어를 도입했습니다: 모든 고양이는 고유 ID로 고양이를 미리 서명된 예술 작품에 매핑하는 미리 서명된(그러나 공개되지 않은) “레이어 커넥터”를 참조합니다. 이는 예를 들어 모든 고양이가 초기 배경 이미지에 대해 동일한 레이어 커넥터를 참조하도록 합니다. 이 레이어 커넥터가 네트워크에 방송되기 전까지는 사람들이 어떤 배경이 더 일반적인지 알 수 없습니다. 이 기술은 공간 절약도 가능하게 했습니다: 모든 고양이가 동일한 레이어 커넥터를 참조하므로, 고양이가 레이어 커넥터를 가져오기 위해 가져올 HTML은 한 번 인스크립션되고 각 3333 고양이 인스크립션이 이를 참조할 수 있습니다. 사실, 각 고양이 인스크립션은 109바이트로 줄어들었습니다: 고유 고양이 ID와 공통 레이어 커넥터를 가져오고 렌더링하는 로직을 가져오는 스크립트 태그만 포함되어 있습니다. 각 고양이를 예술 작품에 매핑하는 것을 개별 고양이 인스크립션에서 공통 인스크립션으로 이동시키고 미리 서명된 간접 참조의 레이어를 추가함으로써, 특성의 상대적 희귀성에 대한 정보 유출 문제를 해결할 수 있었을 뿐만 아니라, 약 5 BTC의 인스크립션 비용도 절약할 수 있었습니다!
레이어 커넥터 인스크립션의 도입과 렌더링 로직을 공통 구성 요소로 분리함에 따라, 이제 4가지 종류의 자산이 인스크립션되고 있습니다:
- 고양이의 각 특성에 대한 실제 예술 작품(배경 이미지, 몸, 눈 등)
- 고양이를 특정 예술 자산에 매핑하는 레이어 커넥터. 이 매핑은 “레이어”당 한 번 발생합니다(배경, 몸, 눈, 입 등)
- 핵심 디스패치 및 렌더링 로직. 우리는 이를 “디스패처”라고 부릅니다. 이는 레이어 커넥터를 가져오고, 레이어 커넥터에서 고양이에 대한 예술 작품을 조회하고, 해당 예술 자산을 가져와서 순서대로 캔버스에 렌더링하는 책임이 있습니다. 이러한 순차적 렌더링이 우리가 예술 작품을 레이어로 모델링하는 이유입니다.
- 수집가에게 배포되는 개별 고양이. 이는 109바이트이며 고유 ID와 모든 렌더링 코드를 포함하는 디스패처에 대한 참조를 포함합니다.
Quantum Cats에는 수백 개의 예술 자산, 40개의 레이어(즉, 40개의 레이어 커넥터), 1개의 디스패처, 3333개의 고양이가 있습니다. 3333 고양이 인스크립션은 디스패처의 인스크립션 ID를 참조하며, 이는 40개의 레이어 커넥터의 인스크립션 ID를 참조하고, 각 레이어 커넥터는 하나 이상의 예술 자산의 인스크립션 ID를 참조합니다. 우리는 이러한 자산을 역순으로 미리 서명했습니다: 먼저 예술 작품의 인스크립션 ID를 얻기 위해 예술 작품을 미리 서명한 다음, 이를 레이어 커넥터로 렌더링하고 미리 서명하여 인스크립션 ID를 얻고, 디스패처를 렌더링하고 미리 서명한 다음, 개별 고양이 인스크립션을 조립했습니다.
인스크립션 ID는 비트코인 거래 ID를 포함합니다. 비트코인 거래 ID는 입력, 출력, 버전 및 잠금 시간의 함수입니다. 이는 미리 서명된 거래를 다른 거래에서 사용하는 UTXO를 지출하면, 동일한 거래 ID를 다시 생성할 수 없으며, 미리 서명된 인스크립션 참조가 깨질 것임을 의미합니다! 이를 피하기 위해 우리는 모든 미리 서명된 거래를 자금을 지원하는 UTXO를 생성하고, 어떤 UTXO가 어떤 미리 서명된 거래를 지원하는지 추적하는 데이터베이스를 유지했습니다. 또한, 두 개의 인스크립션이 동일한 UTXO를 지출하지 않도록, 각 인스크립션 커밋 거래가 할당된 UTXO만 지출하도록, 모든 거래(수수료 포함)의 총 입력 및 출력을 예상한 대로 유지하는 자동화된 무결성 검사를 수행했습니다. 이러한 검사는 시스템이 지갑이나 키에 접근할 때마다 실행되었으며, 서명되어서는 안 되는 것이 서명되지 않도록 확신을 주었습니다. 또한, 서로 다른 자산 인스크립션 유형에 대해 분리된 지갑을 사용하여 UTXO가 이중 할당되는 버그에 대한 추가 보호를 추가했습니다. 우리는 또한 모든 미리 서명된 인스크립션의 발행을 regtest에서 실행하고, 온체인에 남은 데이터가 우리의 제어-plane 데이터베이스와 일치하는지 검증하는 테스트 하네스를 구축했습니다.
이러한 방식으로 거래를 미리 서명하는 것은 각 인스크립션이 지불할 수수료에 미리 약속해야 함을 의미했습니다. 우리는 이러한 진화를 공개할 때 수수료율이 어떻게 될지 알 수 없으므로, 합리적인 수수료율로 거래를 미리 서명한 다음, 미리 서명한 수수료가 너무 낮은 경우 미래에 수수료를 높일 수 있는 도구를 구축하기로 결정했습니다(필요 이상으로 높은 수수료로 미리 서명한 경우, 우리는 그냥 그것을 감수해야 하므로, 여기서의 분석의 일부는 우리가 과지불할 경우에도 편안하게 느낄 수 있는 수수료율을 선택하는 것이었습니다). 거래 가속기 서비스를 사용하는 것 외에도(수수료가 시장 이하일지라도 거래를 블록에 포함시키기 위해 채굴자에게 비공식적으로 지불하는 것), 거래의 유효 수수료율을 높이는 두 가지 기술이 있습니다: Replace-by-fee (RBF)와 Child-Pays-For-Parent (CPFP)입니다. RBF는 더 높은 수수료를 지불하는 새로운 거래에서 거래의 입력을 다시 사용하는 것입니다. 우리의 애플리케이션이 미리 약속된 거래 ID에 의존하기 때문에, 이는 옵션이 아니었습니다. CPFP는 거래의 미확인 출력을 더 높은 수수료를 지불하는 새로운 거래에서 사용하는 것입니다. 채굴자가 이 “자식” 거래에서 수수료를 수취하려면, 부모와 자식을 패키지로 포함해야 합니다. 유효 수수료율은 최종적으로 지불된 총 수수료를 패키지의 총 가상 크기(모든 거래를 합친 것)로 나눈 값입니다. 부모 거래가 변경되지 않기 때문에, 이는 우리가 필요로 하는 수수료 증가 메커니즘이었습니다.
하나의 남은 문제는 수수료를 높여야 할 수백 개의 거래가 있을 수 있다는 것입니다. 수십 개 또는 수백 개의 미확인 거래를 수동으로 정확하게 수수료를 높이는 것의 어려움 외에도, 네트워크를 통해 101 KvB(가상 킬로바이트) 이상의 패키지나 25개 이상의 거래를 릴레이하는 것을 방지하는 릴레이 정책이 있습니다. 이는 우리가 50개의 거래를 CPFP해야 할 경우, 직렬로 처리하는 것보다 모두 병렬로 처리하는 것이 좋다는 것을 의미합니다. 이를 달성하기 위해, 우리는 다음과 같은 도구를 구축했습니다:
- 미확인 거래 목록을 보고 각 거래에 대해 해당 거래를 목표 수수료율로 CPFP 높이기 위한 비용을 계산합니다.
- 병렬로 목표 거래를 높이기 위해 필요한 모든 UTXO에서 단일 입력으로 지출하는 새로운 거래에서 이러한 금액을 출력으로 집계합니다.
- 운영자에게 필요한 비트코인의 총 금액(분할 거래에 대한 수수료도 계산했습니다)을 단일 주소로 보내도록 요청합니다.
- 입금이 수령되면, 입금을 각 거래에 대해 하나의 UTXO로 분할하는 거래를 방송합니다.
- 그런 다음, 막힌 각 거래에 대해 CPFP 거래를 구성하고 방송합니다.
우리는 이 시스템을 Regtest에서 한 번에 최대 300개의 거래를 높이는 테스트를 진행했습니다. 또한, 메인넷에서 여러 레이어 커넥터 공개 거래의 수수료를 높여야 할 때 이를 사용할 기회도 있었습니다! 여기에서 “분할” 거래를 확인할 수 있습니다: https://mempool.space/tx/2ec4a8708524faf9901c69da8518b632ec31762730218d3b38ff40954cee882f 각 출력은 인스크립션 공개 거래의 수수료를 65에서 150 sat/vb로 높이는 CPFP를 자금 지원합니다.
예술 자산은 프로젝트의 총 데이터의 약 90%를 차지했습니다. 우리가 하고자 했던 것은 수수료가 낮을 때 가능한 한 모든 예술을 기회적으로 게시하는 것이었습니다. 그러나 고양이가 진화할 준비가 되기 전에 사람들이 예술을 보는 것을 원하지 않았습니다. 그래서 우리는 예술 작품을 암호화한 다음, 레이어 커넥터와 함께 예술 작품의 복호화 키를 게시하기로 결정했습니다(이는 고양이가 특성을 가져오는 데 필요한 매핑을 포함합니다). 이를 통해 데이터 게시 단계를 특성 공개와 분리할 수 있었습니다. 이는 수수료가 낮은 시점을 활용하여 대량 데이터 게시를 수행하면서, 컬렉션에 적합한 시점에 세계에 예술 작품을 보여줄 수 있게 해주었습니다. 여기에서의 메커니즘은 간단합니다: 특정 레이어(다시 말해 배경, 눈, 입 등)에 대한 모든 예술 작품을 각 레이어 암호화 키로 암호화합니다. 그 암호화된 예술 작품은 미리 서명된 인스크립션에서 바이트 스트림으로 사용됩니다. 그런 다음 암호화 키가 레이어 커넥터에 렌더링됩니다(다시 말해 미리 서명됨). 디스패처가 레이어 커넥터를 가져오면, 고양이 ID -> 예술 자산의 매핑과 해당 레이어의 복호화 키를 읽습니다. 예술 자산을 가져올 때, 바이트 배열로 가져오고, 브라우저 암호화 라이브러리를 사용하여 예술 작품을 png로 복호화한 다음, 최종적으로 캔버스에 씁니다.
이 모든 것을 종합하면, 각 Quantum Cat은 공통 인스크립션을 가져와 디스패치, 복호화 및 렌더링 코드를 포함하는 작은 인스크립션입니다. 이 코드는 온체인에서 사용 가능한 만큼의 레이어 커넥터를 가져옵니다(일부는 미리 서명되었지만 방송되지 않기 때문에 없을 수 있습니다). 그런 다음 이 레이어 커넥터의 인스크립션 ID와 복호화 키를 사용하여 다른 인스크립션에서 암호화된 예술 작품을 가져오고, 이를 복호화한 다음 캔버스에 렌더링합니다. 이러한 미리 서명된 인스크립션을 방송해야 할 때, 우리는 대량 병렬 CPFP 거래를 사용하여 너무 높은 수수료에 미리 약속하지 않고도 올바른 수수료율로 높입니다. 이 모든 것의 최종 결과는 사용자가 지갑에 Quantum Cat을 보유하고 있으며, 시간이 지남에 따라 새로운 특성과 속성이 진화하는 동시에 모든 자산이 비트코인에서 불변성을 유지한다는 것입니다.
여기에서 다루지 않은 프로젝트의 다른 측면도 있습니다 – 브라우저 코드가 이러한 자산을 가져올 때 간헐적인 실패를 관리하는 방법, 진화하는 컬렉션의 큐레이션을 처리하는 방법, 모든 미리 서명된 자산의 UTXO 생성 프로세스를 어떻게 관리했는지(이는 쉽습니다: 위에서 설명한 CPFP UTXO 자금을 지원하기 위한 동일한 팬 아웃 UTXO 분할 코드입니다). 하지만 위의 논의가 인스크립션 프로젝트나 미리 서명된 거래와 관련된 다른 프로젝트에 흥미롭고 유용하길 바랍니다.
이 글은 Rijndael의 게스트 포스트입니다. 표현된 의견은 전적으로 그들의 것이며, BTC Inc 또는 Bitcoin Magazine의 의견을 반드시 반영하지는 않습니다.