ConsensusReactor 상세 - planetarium/libplanet GitHub Wiki
이 문서에서는 Libplanet에서 PoS 합의가 진행되는 방식에 대해 설명합니다.
ConsensusReactor
객체는 Swarm
내부에서 처리되지만 Swarm
과 별도의 ITransport
를 가지고 다른 노드와 통신하는 객체로, Swarm
이 처리하는 수많은 기능들 중에서, PBFT로 Validator
들이 합의하기 위해 필요한 기능들만이 모여있는 객체입니다.
Validator
가 아닌 일반 노드(블록 및 트랜잭션의 싱크 및 전파 수행)의 경우,Swarm
만 켜져있다면,ConsensusReactor
은 꺼져있어도 정상적으로 작동합니다.Validator
로서 합의에 참여하려면, 반드시ConsensusReactor
가 켜져있어야 합니다.Swarm
과는 별도의PrivateKey
를 사용합니다. 두 키는 동일하여도 되며, 달라도 됩니다.Swarm
의PrivateKey
는 일반 블록체인 노드로서의 키 입니다. 블록 및 트랜잭션을 동기화하는 과정에서 다양한 메시지들이 발생하는데 이 메시지들을 서명하는데에 사용되며, 이 키값으로 유도되는 어드레스는 블록과 트랜잭션의 전파자로서의 아이덴티티가 됩니다.ConsensusReactor
의PrivateKey
는 밸리데이터로서의 키 입니다. 합의 과정에서 블록 제안, 투표 등의 메시지들이 발생하는데 이 메시지들을 서명하는데에 사용되며, 이 키값으로 유도되는 어드레스는 밸리데이터로서의 아이덴티티가 됩니다. (블록 보상은 이 쪽의 어드레스로 전달되어야 하기 떄문에 중요합니다)
Gossip
Gossip
은ConsensusReactor
들 간에 통신하는 방식이자, 이를 구현한 객체입니다.Gossip
은Swarm
과는 별도의ITransport
를 가지고, 별도의 채널로 통신합니다.Gossip protocol
에 대한 정보는 위키피디아 링크를 통해 확인할 수 있습니다.Gossip
은 '소문' 혹은 '전염(epidemic)' 프로토콜이라는 이름답게, 각 노드가 스스로 가지고 있는 정보를 적극적으로 공유하여, 정보가 없는 노드에게 전달함으로서 모든 노드가 모든 정보를 확보할 수 있도록 하는 것을 목적으로 하는 프로토콜입니다.- 정보를 어느 한 노드만 확보하더라도, 그 노드가 고립되어있지 않다면 중개노드를 통하여 간접적으로라도 연결되어있는 모든 노드들에게 종국에는 그 정보가 전달됩니다.
- 이 가정을 통하여, byzantine 노드가 일부 노드에게만 메시지를 전파하여 공격할 수 있는 가능성을 제거합니다. (byzantine 노드가 단 하나의 honest 노드에게만 정보를 전달한다면, 이 정보는 모든 honest 노드들에게 전달된다는 가정이 가능해지며, 이는 byzantine 노드가 +1/3의 파워를 확보하지 못하였을 경우 예상되는 대부분의 공격벡터를 차단할 수 있는 중요한 가정입니다)
Gossip
의 작동방식Gossip
은heartBeatInterval
마다 자신이 가지고 있는 메시지들의 id들을HaveMessage
에 담아서 브로드캐스트합니다.Gossip
은heartBeatInterval
마다haveDict
를 기준으로 메시지 id들을WantMessage
에 담아서 브로드캐스트합니다.Gossip
은HaveMessage
를 받으면 해당 메시지를 자신이 가지고 있지 않을 경우,haveDict
에 어떤 peer가 어떤 id의 메시지를 가지고 있는지 기록합니다.Gossip
은WantMessage
를 받으면 id들에 대응하는 메시지들을 답장으로 직접 전달합니다.
GossipConsensusMessageCommunicator
Gossip
이ConsensusReactor
에 대하여 agnostic하도록 하기 위해서Gossip
의DenySet
과Cache
및ConsensusReactor
을 중간에서 직접 규칙에 따라 핸들링할 수 있는 래퍼 클래스 입니다. 컨센서스의 보안 강화를 위한 몇 가지 로직이 포함되어 있습니다.
ConsensusContext
- 과거 다양한
height
의Context
들을 동시에 관리하는 형태로 구현되었을 때의 잔재입니다. - 지금은 단 하나의
Context
만이 존재하기 때문에,Context
로 로직을 병합할 수 있습니다.
Context
-
아래의
Tendermint
스타일의PBFT
알고리즘의 코어부가 구현된 클래스입니다. -
매 Round의 시작은 여기서 이뤄집니다.
-
블록은 다음 코드에서 만들어집니다.
private Block? GetValue()
{
try
{
var evidence = _blockChain.GetPendingEvidence();
Block block = _blockChain.ProposeBlock(_privateKey, _lastCommit, evidence);
_blockChain.Store.PutBlock(block);
return block;
}
catch (Exception e)
{
_logger.Error(
e,
"Could not propose a block for height {Height} and round {Round}",
Height,
Round);
ExceptionOccurred?.Invoke(this, e);
return null;
}
}