용어집 / 개발자 참고 자료
MSG_CMPCT_BLOCK
- MSG_CMPCT_BLOCK란 무엇입니까?
- MSG_CMPCT_BLOCK는 인벤토리 유형 4로서, 요청 전용 코드입니다. 이 코드는 공지 메시지에 절대 나타나지 않으며, 먼저 이를 수락한 상대방에게 보내는 getdata 메시지 안에서만 유효합니다.
BIP-152에 명시되어 있습니다.
컴팩트 블록은 공지되는 것이 아니라 협상되는 것입니다. 한 상대방이 sendcmpct 메시지를 한 번 보내 이를 수락하겠다고 알린 뒤에야 상대편은 새 블록에 대해 유형 2 대신 유형 4로 응답할 수 있습니다. BIP152는 Bitcoin Core 0.13.0과 함께 2016년 8월에 등장했으며, 절약이 바로 핵심입니다. 수신자가 이미 보유한 트랜잭션을 지칭하는 데 6바이트면 되지만, 이를 두 번 전송하는 데는 200바이트 이상이 듭니다.
작동 방식
MSG_CMPCT_BLOCK는 블록 자체 대신 블록의 설명을 요청하며, 그 설명은 두 노드가 유사한 멤풀을 보유할 때만 가치가 있습니다.
협상이 먼저입니다. sendcmpct 메시지에는 플래그와 버전 번호가 담깁니다. 버전 1은 트랜잭션을 txid로 식별하고, 버전 2는 위트니스 txid로 식별하며, 세그윗 이후 사용되는 유일한 버전입니다. 노드는 sendcmpct를 보내지 않은 상대방에게 보내는 getdata에 유형 4를 절대 넣어서는 안 되는데, 그 상대방은 이를 이해할 의무가 전혀 없기 때문입니다.
응답은 cmpctblock 메시지로, 80바이트 헤더, 8바이트 논스, 트랜잭션당 6바이트의 짧은 식별자 하나, 그리고 전체가 그대로 담기는 몇 개의 트랜잭션으로 구성되며, 여기에는 수신자가 이미 보았을 수 없는 코인베이스가 항상 포함됩니다. 짧은 식별자는 헤더와 그 논스로부터 도출한 키로 SipHash를 사용해 생성되므로, 블록마다 그리고 요청마다 달라집니다. 이 무작위화는 방어책입니다. 고정된 방식이라면 공격자가 충돌하는 트랜잭션 두 개를 미리 계산해 두고 네트워크 전체의 재구성을 한꺼번에 방해할 수 있기 때문입니다.
수신자는 식별자를 자신의 멤풀과 대조하고, 빠진 것이 있으면 getblocktxn으로 요청한 뒤 블록을 로컬에서 재구성합니다. 이후의 검증은 평범하며, 합의 규칙은 전혀 건드리지 않습니다.
깊이는 제한됩니다. Bitcoin Core는 가장 최근의 블록 5개에 대해서만 컴팩트 블록을 제공하고, 그보다 오래된 블록에 대한 요청에는 전체 블록으로 응답합니다. 그만큼 뒤처진 수신자는 유용한 멤풀을 갖지 못해 결국 블록의 모든 트랜잭션을 요청하게 되기 때문입니다.
확인할 수 있는 곳
MSG_CMPCT_BLOCK를 가장 분명하게 볼 수 있는 곳은 Bitcoin Core 자체의 로그이며, 각 재구성이 얼마나 잘 되었는지를 보고합니다.
노드를 -debug=cmpctblock으로 시작하면 새 블록마다 미리 채워진 트랜잭션이 몇 개였는지, 멤풀에서 발견된 것이 몇 개였는지, 가져와야 했던 것이 몇 개였는지를 알려주는 줄이 생성됩니다. 몇 시간 동안 실행된 머신에서는 가져온 개수가 보통 0이며, 블록은 한 메가바이트 반이 아니라 수십 킬로바이트로 도착합니다. 3,000개의 트랜잭션을 담은 블록에는 짧은 식별자용 18,000바이트에 헤더와 코인베이스가 더해집니다.
그 산수는 갓 시작한 노드에서 무너집니다. 멤풀이 비어 있으면 모든 식별자가 일치하지 않고, 후속 요청이 블록 전체를 요구하며, 추가 왕복 때문에 컴팩트 경로가 블록을 그냥 요청하는 것보다 느려집니다. 이것이 이 코드가 체인의 최신 지점에 있는 노드의 것이며 초기 동기화 중에는 절대 나타나지 않는 이유입니다.
집에서 노드를 운영하는 사람에게 이 기능은 평범한 연결이 네트워크와 보조를 맞출지, 아니면 블록이 발견될 때마다 뒤처질지를 결정합니다.