포크 선택과 누적 난이도
예를 들어 네트워크가 몇 분 동안 갈라지면, 체인의 두 버전이 한동안 경쟁할 때가 있습니다. 그러면 모든 ZooBC 노드는 누적 난이도가 더 큰 분기를 따릅니다. 누적 난이도는 블록 가중치의 누적 합계로, 일찍 추첨된 생산자의 블록이 늦게 추첨된 생산자의 블록보다 무겁습니다. 이 규칙은 모든 노드에서 같은 산술이므로, 누가 승자를 고르지 않아도 네트워크가 하나로 수렴합니다.
더 긴 것이 아니라 더 무거운 것
각 블록은 그 높이의 추첨에서 생산자가 얼마나 뒤에 있었는지에 따라 줄어드는 양을 누적 합계에 더합니다. 가장 단순하게 말하면, 블록은 1,000,000을 추첨에서의 생산자 순위로 나눈 값을 더합니다. 첫 번째로 추첨된 생산자의 블록은 1,000,000을, 세 번째 생산자의 블록은 약 333,333을 더합니다.
따라서 제시간에 만든 블록의 체인은, 생산자들이 계속 차례를 놓친 체인보다 무겁습니다. 두 번째 체인이 더 길더라도 그렇습니다. 1라운드 블록 세 개는 3,000,000이고, 3라운드 블록 네 개는 약 1,333,332입니다.
다른 방법들은 통하지 않습니다. 트랜잭션 수를 세면 생산자가 이기려고 블록을 부풀릴 수 있습니다. "먼저 본 것"은 네트워크 지연 때문에 노드마다 다르므로 노드들이 영원히 갈라진 채로 남을 수 있습니다. 그리고 어느 분기를 공식으로 표시해 줄 권한 기관도 없습니다.
블록의 정확한 가중치
버전 0.5.8부터 블록의 증가분은 다음과 같습니다.
increment = floor(1,000,000 × |S| / (k × |A|))
- S는 이전 블록 시점의 추첨 집합으로, 활성 노드에서 정지된 노드를 뺀 것입니다.
- A는 이전 블록 시점의 활성 레지스트리 전체입니다. 비율 |S| / |A|는 결코 1을 넘지 않습니다.
- k는 블록의 라운드까지의 라운드들에서 생산자가 마지막으로 나타난 곳까지의 추첨 횟수입니다. 첫 번째로 추첨되어 제시간에 타임스탬프를 찍은 생산자는 1, 세 번째 추첨에서 지명된 생산자는 3입니다. (그 범위에서 생산자를 찾지 못하면 2 × n번의 추첨 안에서 처음 나타난 위치를 쓰고(n은 추첨 집합의 노드 수), 그래도 없으면 해시 순서의 위치를 씁니다.)
두 가지 하한이 블록이 받을 만한 것보다 많이 주장하지 못하게 막습니다. k는 블록의 타임스탬프가 속한 라운드보다 작아지지 않으므로, 늦은 타임스탬프로 이른 라운드의 가중치를 유지할 수 없습니다(라운드, 타이밍, 시간 창 참조). 그리고 이전 블록의 생산자에게는 k가 강등된 라운드인 10보다 작아지지 않습니다(우선 라운드, 빈 블록, 이전 생산자 참조).
추첨 집합의 비율은 네트워크가 갈라질 때 중요합니다. 갈라진 양쪽이 각자 소식을 들을 수 없는 노드를 정지시킨다면, 이 비율이 없을 때 양쪽 모두 제시간의 블록마다 1,000,000을 더해 똑같이 무거워 보일 것입니다. 이 비율이 있으면 11개 좌석 중 3개로 운영되는 쪽은 블록마다 최대 272,727을 더하고, 8개를 가진 쪽은 727,272를 더합니다. 블록 대 블록으로 보면 좌석을 더 많이 가진 쪽이 더 무겁습니다.
모든 블록은 자신의 누적 난이도를 10진수 문자열로 담고 있습니다. 모든 검증자가 이를 다시 계산하며, 잘못 기재한 블록은 거부합니다. 두 합계는 먼저 길이로, 그다음 자릿수별로 비교합니다.
참여 점수는 이 중 어디에도 관여하지 않습니다. 가중치는 점수가 아니라 추첨 순위와 추첨 집합을 읽습니다.
정확히 같을 때
정확한 동점은 실제로 일어납니다. 예를 들어 길이가 같은 두 분기가 모두 제시간에 만든 1라운드 블록으로만 이루어진 경우입니다. 버전 0.5.8부터는 두 분기의 최상단 블록 해시를 바이트 단위로 비교하여 더 낮은 해시가 이깁니다. 노드는 가중치가 같은 분기의 최상단 해시가 자신의 것보다 낮으면 그 분기로 전환하고, 그렇지 않으면 자신의 분기를 유지하며, 누구에게도 묻지 않습니다. 모든 노드가 같은 두 해시에 같은 비교를 적용하므로 네트워크 전체가 즉시 수렴합니다.
전환하기 전에 분기의 무게를 잽니다
자기 분기가 더 무겁다는 피어의 주장은 그 자체로는 아무것도 증명하지 않습니다. 노드는 자기 체인에 손대기 전에 경쟁 분기의 무게를 잽니다.
- 두 체인이 공유하는 마지막 블록을 찾습니다.
- 그 블록 이후의 분기를 페이지 단위로 가져오며, 모든 헤더 서명과 블록 간의 연결을 검사합니다.
- 공통 블록부터 그 분기 자체의 레지스트리와 정지 상태를 재생하며 각 블록의 가중치를 다시 계산합니다. 갈라진 반대편에서는 이것들이 다를 수 있기 때문입니다.
- 분기가 자기 체인보다 무거워지는 즉시 멈추고, 그때서야 롤백한 뒤 그 분기를 적용합니다. 결국 더 가벼운 분기나, 정해진 블록 수 안에 앞서지 못하는 분기는 아무것도 롤백하지 않은 채 거부됩니다.
주장한 난이도가 다시 계산한 값과 다른 피어는 거짓말을 한 것으로 기록됩니다.
롤백에는 엄격한 한계가 있습니다. mainnet에서는 결코 720블록(3시간)을 넘지 않으며, 스파인 체인에서 공동 서명된 마지막 체크포인트 아래로도 내려가지 않습니다. 최종성과 롤백을 참조하십시오.
뒤처진 노드와 피어 조회
최상단 블록이 7,200초(2시간)보다 오래된 노드는 자기가 앞서 있다고 주장하는 아무 피어나 믿지 않습니다. 등록된 피어 표본의 3분의 2 이상이 보고하는 최상단 블록을 따릅니다. 노드가 더 무거운 분기를 확인하거나 자기 상태를 점검하려고 실행할 수 있는 다른 피어 조회는 합의가 아니라 로컬 정책입니다.