텐더민트 합의에 락이 필요한 이유

지난 글 “텐더민트 합의에 3단계가 필요한 이유”에서 텐더민트 합의 과정을 Propose-Vote 2단계로 줄일 경우 safety에 문제가 발생함을 확인하였다. 그렇다면 Propose-Prevote-Precommit 3단계로 진행하면 safety 문제가 해결될까? 이번에도 예시를 통해 살펴보자.

이번에도 다음과 같이 N1, N2, N3, N4 4개의 노드가 합의를 하는 상황을 가정해보자. 노드 N1이 라운드 R1에서 블록 B1을 제안하였다.

tendermint_without_lock_1

 

B1 블록이 네트워크에 전파되어 N3, N3, N4 노드도 B1 블록을 알게 되었다.

tendermint_without_lock_2

 

B1 블록은 정상적인 블록이므로 노드 모든 노드가 B1 블록에 대한 Prevote 메시지지를 만들어 보낸다.

tendermint_without_lock_3

 

N2 노드는 네트워크 오류로 다른 노드의 Prevote 메시지를 받지 못하였고, N1, N3, N4는 모든 노드로부터 Prevote 메시지를 받았다.

tendermint_without_lock_4

 

N1, N3, N4 노드는 ⅔ 이상의 Prevote를 모았기 때문에 Precommit 메시지를 만들어 보낸다.

tendermint_without_lock_5

 

N3, N4 노드는 네트워크 오류로 Precommit 메시지를 받지 못하였고, N1 노드만 N1, N3, N4 노드의 Precommit 메시지를 받았다.

tendermint_without_lock_6

 

N1 노드는 ⅔ 이상의 Precommit을 모았기 때문에 B1 블록을 커밋하였다.

tendermint_without_lock_7

 

타임아웃이 발생하여 라운드 R2가 시작되고 N2 노드가 블록 B2를 제안하였다.

tendermint_without_lock_8

 

블록 B2가 네트워크에 전파되어 모든 노드가 B2 블록을 받았다.

tendermint_without_lock_9

 

N3, N3, N4 노드는 N1에 B1 블록에 커밋했다는 사실을 모르므로 B2 노드에 대해 정상적으로 Prevote 메시지를 만들어서 보낸다.

tendermint_without_lock_10

 

N2, N3, N4 노드가 서로 Prevote 메시지를 교환하여 B2 블록에 대해 ⅔ 이상의 Prevote 메시지를 모았다.

tendermint_without_lock_11

 

N2, N3, N4 노드는 ⅔ 이상의 Prevote 메시지를 모았기 때문에 B2 블록에 대한 Precommit 메시지를 보낸다.

tendermint_without_lock_12

 

N2, N3, N4 노드가 서류 Precommit 메시지를 교환하여 B2 블록에 대해 ⅔ 이상의 Precommit 메시지를 모았다.

tendermint_without_lock_13

 

N2, N3, N4 노드는 ⅔ 이상의 Precommit 메시지를 모았기 때문에 B2 블록을 커밋한다.

tendermint_without_lock_14

 

N1 노드는 B1 블록을 커밋하고 N2, N3, N4 노드는 B2 블록을 하였기 때문에 safety가 깨졌다.

tendermint_without_lock_15
위에 예에서 볼 수 있듯이 Propose-Prevote-Precommit 3단계로 합의를 진행해도 여전히 safety가 깨지는 상황이 존재함을 알 수 있다. 이러한 상황이 발생하는 이유는 N3, N4가 이미 라운드 R1에서 B1 블록에 대해 ⅔ 이상의 Prevote를 보고 Precommit을 했음에도 불구하고 R2 라운드에서 마음을 바꿔 B1이 아닌 B2 블록에 대해 Prevote를 했기 때문이다.

노드가 Precommit을 하면 이 Precommit 메시지 때문에 다른 노드가 커밋을 했을 가능성을 생각해야 한다. safety를 보장하려면 노드가 한 번 Precommit을 하고 나면 이후 Precommit한 블록과 같은 블록에 대해서만 Prevote를 해야 하고, 리더가 되었을 때도 Precommit한 블록과 같은 블록을 제안해야 한다. 이러한 규칙을 텐더민트 락(lock)이라고 한다.

텐더민트 락을 적용해서 다시 한 번 합의를 진행해보자.

이전 시나리오와 마찬가지로 N1 노드가 B1에 커밋한 상황에서 N2가 블록 B2를 제안하였다. N2는 B1 블록에 대해 ⅔ 이상의 Prevote를 본 적이 없기 때문에 락을 잡지 않았다.

tendermint_with_lock_1

 

N2, N3, N4 노드에 B2 블록이 전파되었고, 각 노드는 B2 블록에 대한 Prevote 메시지를 만들려고 한다.

tendermint_with_lock_2

 

하지만 N3, N4 노드는 라운드 R1에 이미 B1 블록에 대해 ⅔ 이상의 Prevote를 보고 락을 잡은 상태이기 때문에 B2 블록에 대해서 Prevote 메세지를 보내지 않는다.

tendermint_with_lock_3

 

N2, N3, N4 노드가 B2 블록에 합의하지 못했기 때문에 다시 타임아웃이 발생하고 이번에는 N3 노드가 블록을 제안한다. N3는 R1 라운드에 B1 블록에 락을 잡았기 때문에 리더가 되었을 때도 B1 블록을 제안한다. 이후 N2, N4 노드가 B1 블록에 Prevote 및 Precommit을 하고 B1 블록으로 합의하게 된다. N1, N2, N3, N4가 모두 B1 블록에 커밋하였으므로 safety가 깨지지 않았다.

tendermint_with_lock_4

추가로 ⅔ 이상의 Prevote를 모았을 때 락을 잡기만 하고 풀지 않으면 더 이상 합의가 진행되지 않는 liveness 이슈가 생기게 된다. 따라서 라운드 R에서 ⅔ 이상의 Prevote를 보고 락을 잡았더라도 라운드 R’ (R’>R)에서 또 다시 ⅔ 이상의 Prevote를 보았다면 이전 락을 풀고 새로 락을 잡아야 한다. 이러한 특성 때문에 ⅔ 이상의 Prevote를 PoLC (Proof of Lock Change)라고 부른다.

 

2 thoughts on “텐더민트 합의에 락이 필요한 이유

  1. Pingback: 텐더민트 합의에 3단계가 필요한 이유 | Kwang Yul Seo

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s