Skip to main content
멤풀은 서명된 트랜잭션과 커밋된 블록 사이에 서 있는 구성 요소입니다. 무엇을 들고 있을 값어치가 있는지, 한 발신자의 트랜잭션이 어떤 순서로 실행 가능해지는지, 어떤 피어가 그 트랜잭션을 전해 듣는지, 그리고 수요가 용량을 넘길 때 무엇을 버릴지를 결정합니다. 거래 네트워크에서 이것은 부수적인 요소가 아니라 하중을 받는 구조물입니다. 주문과 취소 트래픽은 폭발적이고, 소수 발신자에 몰려 있으며, 지연에 대해 비대칭적으로 민감합니다. 늦게 도착한 취소는 늦게 도착한 주문보다 나쁩니다. 아래 구조가 존재하는 이유는 단일 FIFO 큐로는 그 어느 것도 제대로 처리할 수 없기 때문입니다.

들어오는 경로

서명된 트랜잭션
검증서명 · 형식 · 계정 상태 · 발신자의 지불 능력
사유와 함께 폐기조용히 사라지지 않음 — 제출자에게 사유 전달
트랜잭션 저장소
피어 브로드캐스트
배치 구성 후 합의
검증은 값싸고 국소적이므로, 하위 단계의 비싼 자원은 실제로 실행될 수 있는 트랜잭션에만 쓰입니다.
거부
수락
트랜잭션은 저장되기 전에 먼저 검증됩니다. 검증은 값싸고 국소적입니다. 서명, 형식, 계정 상태, 그리고 발신자가 요청한 것에 대해 비용을 낼 수 있는지를 봅니다. 이 검증이 존재하는 이유는 하위 단계의 비싼 자원을 실제로 실행될 수 있는 트랜잭션에만 쓰기 위해서입니다. 여기서의 거부는 조용히 사라지는 대신 제출자에게 사유를 돌려줍니다.

트랜잭션을 보관하는 방식

수락된 트랜잭션은 하나의 평평한 큐로 관리되지 않습니다. 저장소는 같은 집합 위에 여러 뷰를 유지하며, 각 뷰는 서로 다른 질문에 답합니다.
수락된 트랜잭션 단일 집합다섯 개의 큐가 아니라 그 위의 다섯 뷰
계정별 순서이 발신자에게 다음 트랜잭션은 무엇인가?
우선순위 인덱스모든 발신자를 통틀어 무엇을 합의에 먼저 내놓아야 하는가?
만료 인덱스무엇이 기한을 넘겼는가?
타임라인 인덱스이 피어가 아직 전해 듣지 못한 것은 무엇인가?
보류함형식은 온전하지만 아직 실행 가능하지 않은 것은?
보류함은 연동 버그가 드러나는 자리입니다. 유효하지만 아직 그 발신자의 다음 차례가 아닌 트랜잭션은 거부되는 대신 보류되고, 앞의 빈자리가 메워지는 순간 실행 가능해집니다.
보류함이 가장 주목할 만합니다. 한 부류의 연동 버그가 드러나는 자리이기 때문입니다. 트랜잭션은 완벽하게 유효하면서도 그 발신자의 다음 차례가 아닐 수 있습니다. 같은 계정의 앞선 트랜잭션이 아직 도착하지 않았거나 커밋되지 않은 경우가 가장 흔합니다. 그런 트랜잭션은 거부되는 대신 보류됩니다. 계속 남아 있다가 앞의 빈자리가 메워지는 순간 실행 가능해집니다. 따라서 순서를 어긋나게 제출하는 클라이언트는 실패가 아니라 지연을 겪지만, 빈자리를 끝내 메우지 않는 클라이언트는 만료될 때까지 작업을 보류함에 남겨 두게 됩니다. 타임라인 인덱스는 피어 전파를 증분 방식으로 만듭니다. 각 피어가 타임라인의 어디까지 전달받았는지를 추적하므로, 브로드캐스트는 풀 전체를 다시 보내는 대신 그 피어에게 빠진 것만 보냅니다. 타임라인은 한 줄이 아니라 버킷으로 나뉘어 있어, 트래픽이 많은 발신자 하나가 모든 브로드캐스트 슬롯을 독점하지 못합니다.

전파와 공정성

각 노드가 저마다 독립적으로 트랜잭션을 알게 되는 것은 아닙니다. 트랜잭션을 수락한 노드는 이를 피어에게 브로드캐스트하는데, 모든 피어를 똑같이 대하지는 않습니다. 상류 피어를 우선하므로, 트랜잭션은 네트워크 전체로 고르게 번지기보다 그 트랜잭션을 처리할 수 있는 검증자 쪽으로 이동합니다. 공정성은 메시지 단위로 강제되는 대신 최근 이력을 기준으로 추적됩니다. 멤풀은 어떤 발신자와 어떤 종류의 트래픽이 최근에 용량을 소비했는지를 롤링 기록으로 유지하고, 이 기록으로 다음에 무엇을 처리할지 조절합니다. 이것이 한 계정의 주문·취소 폭주가 네트워크의 나머지를 밀어내지 못하게 하는 장치이며, 정상적인 마켓 메이킹까지 벌하게 될 계정별 고정 요청 속도 제한을 두지 않아도 됩니다.

합의로의 인계

합의는 멤풀에서 트랜잭션을 하나씩 가져가지 않습니다. 트랜잭션은 배치로 모이고, 배치는 배경에서 검증자에게 전파되며, 각 배치는 원 발신자가 네트워크의 충분한 몫이 그 배치를 들고 있음을 증명할 수 있을 때까지 확인을 받습니다. 그 뒤에야 블록 제안이 배치를 참조할 수 있습니다. 그 결과 블록 제안은 트랜잭션 본문이 아니라 배치 다이제스트를 싣고 다니므로, 처리량이 올라가도 합의 메시지 크기는 늘지 않습니다. 그리고 커밋된 블록은 언제나 재실행할 수 있습니다. 참조되기 전에 그 뒤의 데이터가 가용하다는 것이 이미 증명되었기 때문입니다. 그 증명이 어떻게 만들어지고 어떻게 쓰이는지는 IntentionBFT에서 다룹니다.
이것이 멤풀 수락과 블록 포함이 같은 말이 아닌 이유이기도 합니다. 수락되고 저장되고 브로드캐스트된 트랜잭션은 줄에 들어선 것이지, 순서가 정해진 것이 아닙니다. 그 트랜잭션을 담은 블록을 합의가 커밋하기 전까지는 트랜잭션의 운명 가운데 확정된 것이 하나도 없습니다.

클라이언트에게 의미하는 것

  • 제출 단계의 거부는 정보가 됩니다. 트랜잭션이 저장되기 전에 일어난 일이며, 사유는 클라이언트가 고칠 수 있는 무언가를 가리킵니다.
  • 침묵은 거부가 아닙니다. 클라이언트가 스스로 만든 빈자리 뒤에 트랜잭션이 보류되어 있을 수 있습니다. 확인 응답이 없다고 폐기되었다고 단정하지 말고, 무엇을 제출했고 무엇이 커밋되었는지를 추적하십시오.
  • 계정 안의 순서는 중요하고, 계정 사이의 순서는 그렇지 않습니다. 한 발신자의 두 트랜잭션에는 정해진 순서가 있습니다. 서로 다른 발신자의 두 트랜잭션은 누가 먼저 제출했는지가 아니라 합의가 순서를 정합니다.
  • 멤풀에서 취소는 특권을 갖지 않습니다. 취소 우선순위는 큐잉의 성질이 아니라 커널 실행의 성질이며, 거기서 취소는 같은 블록의 공격적 주문 제출보다 먼저 실행됩니다.