主内
ー。。ー。

네트워크 피어 프로토콜

1.개요

EOS 블록체인의 노드는 트랜잭션 중계, 블록 푸시, 피어 간 상태 동기화를 위해 서로 통신할 수 있어야 합니다.피어투피어 (p2p) 프로토콜의 일부인 nodeos 모든 노드에서 실행되는 서비스는 이러한 목적에 부합합니다.상태 동기화 기능은 각 블록이 결국 블록체인의 글로벌 상태 내에서 최종성에 도달하고 각 노드가 마지막 돌이킬 수 없는 블록 (LIB) 을 진행할 수 있도록 하는 데 매우 중요합니다.이와 관련하여 p2p 프로토콜의 기본 목표는 블록을 동기화하고 노드 간에 트랜잭션을 전파하여 합의에 도달하고 블록체인 상태를 발전시키는 것입니다.

1.1.목표

블록에 여러 트랜잭션을 추가하고 지정된 생산 시간인 0.5초 내에 맞추려면 p2p 프로토콜을 속도와 효율성을 염두에 두고 설계해야 합니다.이 두 가지 목표는 유효 대역폭 내에서 트랜잭션 처리량을 극대화하고 네트워크 및 운영 대기 시간을 줄이는 것으로 해석됩니다.이를 달성하기 위한 몇 가지 전략은 다음과 같습니다.

  • 더 많은 트랜잭션을 블록 내에 배치하여 규모의 경제를 개선합니다.
  • 블록과 트랜잭션 간의 중복 정보를 최소화합니다.
  • 노드 상태를 보다 효율적으로 브로드캐스팅하고 동기화할 수 있습니다.
  • 데이터 압축 및 바이너리 인코딩으로 페이로드 풋프린트를 최소화합니다.

이러한 전략의 대부분은 EOS 소프트웨어에서 전부 또는 부분적으로 구현됩니다.선택 사항인 데이터 압축은 트랜잭션 수준에서 구현됩니다.이진 인코딩은 네트워크를 통해 오브젝트 인스턴스와 프로토콜 메시지를 보낼 때 net serializer에 의해 구현됩니다.

2.아키텍처

P2P 프로토콜의 주요 목표는 노드를 안전하고 효율적으로 동기화하는 것입니다.이 중요한 목표를 달성하기 위해 시스템은 기능을 네 가지 주요 구성 요소로 위임합니다.

*Net Plugin: 블록을 동기화하고 피어 간에 트랜잭션을 전달하는 프로토콜을 정의합니다. *체인 컨트롤러: 수신된 블록과 트랜잭션을 노드 내에서 디스패치/관리합니다. *Net Serializer: 네트워크 전송을 위해 메시지, 블록 및 트랜잭션을 직렬화합니다. *로컬 체인: 리버서블 블록을 포함한 블록체인의 노드의 로컬 사본을 보관합니다.

위 구성 요소 간의 상호 작용은 아래 다이어그램에 나와 있습니다.

가장 높은 레벨에는 Net Plugin이 있습니다. Net Plugin은 노드와 피어 간에 메시지를 교환하여 블록과 트랜잭션을 동기화합니다.일반적인 메시지 흐름은 다음과 같습니다.

1.노드 A는 Net 플러그인을 통해 노드 B에 메시지를 보냅니다 (위 다이어그램 참조). 1.노드 A의 Net 시리얼라이저는 메시지를 패킹하여 노드 B로 보냅니다. 2.노드 B의 Net Serializer는 메시지의 압축을 풀고 Net 플러그인에 전달합니다. 2.메시지는 노드 B의 Net Plugin에 의해 처리되어 적절한 액션을 전달합니다. 3.Net Plugin은 필요한 경우 체인 컨트롤러를 통해 로컬 체인에 액세스하여 블록을 푸시하거나 가져옵니다.

2.1.로컬 체인

로컬 체인은 노드의 블록체인 로컬 사본입니다.노드가 수신한 되돌릴 수 없는 블록과 되돌릴 수 없는 블록으로 구성되며, 각 블록은 이전 블록에 암호적으로 연결됩니다.되돌릴 수 없는 블록 목록에는 불변의 블록체인의 실제 사본이 포함되어 있습니다.리버서블 블록 목록은 일반적으로 길이가 짧으며 체인 컨트롤러가 블록을 푸시할 때 포크 데이터베이스에서 관리합니다.로컬 체인은 아래와 같습니다.

![](/images/protocol-p2p_local_chain.png "Local Chain (before pruning)“)

각 노드는 블록과 트랜잭션을 수신하고 상태를 다른 피어와 동기화하면서 블록체인의 자체 로컬 사본을 구성합니다.되돌릴 수 있는 블록은 수신된 새 블록 중 아직 최종 단계에 도달하지 못한 블록입니다.따라서 그들은 주요 공통 조상인 LIB (마지막 비가역 블록) 에서 유래한 가지를 형성할 가능성이 높습니다.LIB와 다른 다른 공통 조상도 가역적 블록에 사용할 수 있습니다.사실, 두 형제 지부에는 항상 가장 가까운 공통 조상이 있습니다.예를 들어, 위 다이어그램에서 블록 52b는 LIB와 다른 블록 53a 및 53b에서 시작하는 분기의 가장 가까운 공통 조상입니다.로컬 체인의 모든 활성 지점은 블록체인의 일부가 될 가능성이 있습니다.

2.1.1.LIB 블록

노드에 구성된 모든 비가역 블록은 각 노드의 마지막 비가역 블록 (LIB) 까지 다른 노드의 블록과 일치해야 합니다.이것이 블록체인의 분산적 특성입니다.결국 LIB 블록을 따르는 블록이 최종 단계에 도달하면 LIB 블록은 헤드 블록 (HB) 을 따라잡으면서 분기 중 하나를 통해 체인 위로 이동합니다.LIB 블록이 발전하면 불변의 블록체인이 효과적으로 성장합니다.이 프로세스에서 헤드 블록은 수신된 잠재적 헤드 블록 번호와 타임스탬프에 따라 여러 번 브랜치를 전환할 수 있으며, 이는 궁극적으로 타이브레이커로 사용됩니다.

2.2.체인 컨트롤러

체인 컨트롤러는 로컬 체인 상태를 변경하는 블록 및 트랜잭션에 대한 기본 작업 (예: 트랜잭션 검증 및 실행, 블록 푸시 등) 을 관리합니다. 체인 컨트롤러는 Net Plugin으로부터 명령을 받고 Net Plugin에서 수신한 네트워크 메시지를 기반으로 블록 또는 트랜잭션에 대한 적절한 작업을 디스패치합니다.네트워크 메시지는 블록과 트랜잭션의 상태를 동기화하기 위해 서로 통신하면서 EOS 노드 간에 지속적으로 교환됩니다.

2.2.1.시그널의 프로듀서 및 소비자

정상 작동, 포크 및 재생 중 컨트롤러에 정의된 신호의 생성자 및 소비자와 수명 주기는 다음과 같습니다.

사전 승인된 블록 (서명된 블록_ptr 캐리)
  • 제작자
모듈함수조건
컨트롤러푸시_블록포크 DB에 블록이 추가되기 전
replay_push_block리플레이된 블록이 포크 db에 추가되기 전 (리플레이 중에 포크 db에 비가역 블록이 추가되지 않아 리플레이된 블록이 되돌릴 수 없는 경우가 아닌 경우에만 해당)
  • 소비 주체
모듈사용법
체인_플러그인체크포인트 검증
사전 승인된 블록 채널로 데이터 전달
수락블록헤더 (캐리 블록_상태_ptr)
  • 제작자
모듈함수조건
컨트롤러푸시_블록블록을 포크 DB에 추가한 후
commit_block포크 db에 블록을 추가한 후 (블록을 생성한 사람이 자신일 경우에만, 다른 사람으로부터 받은 블록에는 해당되지 않음)
replay_push_block리플레이된 블록이 포크 db에 추가된 후
  • 소비 주체
모듈사용법
체인_플러그인승인된블록헤더_채널로 데이터 전달
허용블록 (캐리 블록상태_ptr)
  • 제작자
모듈함수조건
컨트롤러커밋_블록블록이 마무리되면
  • 소비 주체
모듈사용법
net_plugin블록을 다른 동료에게 브로드캐스트
불가역적블록 (캐리 블록상태_ptr)
  • 제작자
모듈함수조건
컨트롤러log_irreversible블록 로그에 추가되기 전과 체인베이스 DB가 커밋되기 전
리플레이푸시블록되돌릴 수 없는 블록을 다시 플레이하는 경우
  • 소비 주체
모듈사용법
컨트롤러wasm_interface 의 현재 라이브러리 설정
체인_플러그인데이터를 되돌릴 수 없는블록채널로 전달
수락된 트랜잭션 (캐리 트랜잭션_메타데이터_ptr)
  • 제작자
모듈함수조건
컨트롤러push_transaction트랜잭션이 성공적으로 실행될 때 (단 한 번만, 즉 적용되지 않았다가 다시 적용되면 신호가 방출되지 않음)
푸시스케줄링트랜잭션스케줄링된 트랜잭션이 성공적으로 실행될 때
예정된 거래가 실패하는 경우 (주관적/소프트/하드)
예정된 거래가 만료되는 경우
오류 시 신청 후
  • 소비 주체
모듈사용법
체인_플러그인승인된 거래 채널로 데이터 전달
적용_트랜잭션 (캐리 표준: :tuple<const transaction_trace_ptr&, const signned_transaction&>)
  • 제작자
모듈함수조건
컨트롤러푸시_트랜잭션트랜잭션이 성공적으로 실행될 때
푸시스케줄링트랜잭션스케줄링된 트랜잭션이 성공적으로 실행될 때
예정된 거래가 실패하는 경우 (주관적/소프트/하드)
예정된 거래가 만료되는 경우
오류 시 신청 후
  • 소비 주체
모듈사용법
체인_플러그인적용된 트랜잭션 채널로 데이터 전달
배드_얼록

미사용.

2.2.2.시그널의 라이프 사이클

A. 블록과 트랜잭션이 입력되는 정상 작동

1.트랜잭션이 블록체인에 푸시되는 경우 (RPC를 통해 또는 피어에 의해 브로드캐스트됨) 1.트랜잭션이 성공적으로 실행됨/검증에 실패함 -> accepted_transaction 컨트롤러에서 방출됩니다. 2. chainplugin은 신호에 반응하여 트랜잭션메타데이터를 수락트랜잭션채널로 전달합니다. 2.예정된 거래가 블록체인에 푸시되는 경우 1.트랜잭션이 성공적으로 실행됨/주관적으로 실패함/소프트 페일/하드 페일 중 하나 -> accepted_transaction 컨트롤러에서 방출됩니다. 2. chainplugin은 신호에 반응하여 트랜잭션메타데이터를 수락트랜잭션채널로 전달합니다. 3.블록이 블록체인에 푸시되는 경우 (RPC를 통해 또는 피어에 의해 브로드캐스트됨) 1.블록이 포크 db에 추가되기 전 -> pre_accepted_block 컨트롤러에서 방출됩니다. 2. chainplugin은 신호에 반응하여 블록 검증을 수행하고 블록 상태를 accepted_block_header_channel 로 전달하고 체크포인트로 유효성을 검사합니다. 3.포크 db에 블록을 추가한 후 -> accepted_block_header 컨트롤러에서 방출됩니다. 4. chain_plugin은 신호에 반응하여 블록상태를 수락블록헤더채널로 전달합니다. 5.그러면 블록이 적용되고, 이때 블록 내의 모든 트랜잭션과 scheduled_transactions 가 푸시됩니다.푸시트랜잭션 및 푸시스케줄링트랜잭션 (A.1 및 A.2 지점 참조) 과 관련된 모든 신호가 방출됩니다. 6.블록을 커밋할 때 -> accepted_block 컨트롤러에서 방출됩니다. 7. netplugin은 신호에 반응하여 블록을 피어에게 브로드 캐스트합니다. 8.새 블록이 되돌릴 수 없게 되면 돌이킬 수 없는 블록과 관련된 신호가 방출됩니다 (A.5 지점 참조). 4.블록이 생성될 때 1.사용자가 생성한 블록의 경우 블록이 커밋될 때 fork_db에 블록이 추가됩니다 -> accepted_block_header 컨트롤러에서 방출됩니다. 2. chain_plugin은 신호에 반응하여 블록상태를 수락블록헤더채널로 전달하고 체크포인트로 유효성을 검사합니다. 3.그 직후 (블록 커밋 중) -> accepted_block 컨트롤러에서 방출됩니다. 4. net_plugin은 신호에 반응하여 블록을 피어에게 브로드 캐스트합니다. 5.새 블록이 되돌릴 수 없게 되면 돌이킬 수 없는 블록과 관련된 신호가 방출됩니다 (A.5 지점 참조). 5.블록이 되돌릴 수 없게 되는 경우 1.블록이 되돌릴 수 없는 것으로 간주되면 -> irreversible_block 블록이 블록 로그에 추가되고 chainbase db가 커밋되기 전에 컨트롤러가 내보냅니다. 2. chain_plugin은 신호에 반응하여 블록상태를 되돌릴 수 없는블록채널로 전달하고 wasm_interface 라이브러리도 설정합니다.

B. 포크를 제시하고 해결하는 작업

1.포크가 제시되면 블록체인은 기존의 모든 블록을 분기점까지 끌어 올린 다음 모든 새 블록을 포크에 적용합니다. 2.새 블록을 적용하면 블록 내의 모든 트랜잭션과 scheduledtransactions 가 푸시됩니다.푸시트랜잭션 및 푸시스케줄링트랜잭션 (A.1 및 A.2 지점 참조) 과 관련된 모든 신호가 방출됩니다. 3.그리고 새 블록을 커밋할 때 -> accepted_block 컨트롤러에서 방출됩니다. 4. net_plugin은 신호에 반응하여 블록을 피어에게 브로드 캐스트합니다. 5.새 블록이 되돌릴 수 없게 되면 돌이킬 수 없는 블록과 관련된 신호가 방출됩니다 (A.5 지점 참조).

C. 일반 리플레이 (리플레이 최적화 포함 또는 미포함)

1.돌이킬 수 없는 블록을 재생하는 경우 -> irreversible_block 컨트롤러에서 방출됩니다. 2.방법을 보려면 A.5를 참조하십시오. irreversible_block 신호가 응답됨 3.리버서블 블록을 재생할 때 fork_db에 블록이 추가되기 전 -> pre_accepted_block 컨트롤러에서 방출됩니다. 4.리버서블 블록을 재생할 때, 포크 db에 블록을 추가한 후 -> accepted_block_header 컨트롤러에서 방출됩니다. 5.리버서블 블록을 재생할 때, 블록이 커밋되면 -> accepted_block 컨트롤러에서 방출됩니다. 6.방법을 보려면 A.3을 참조하십시오. pre_accepted_block, accepted_block_headeraccepted_block 신호가 응답함

2.2.3.포크 데이터베이스

포크 데이터베이스 (Fork DB) 는 체인 컨트롤러가 노드의 로컬 체인에서 작업을 수행할 수 있는 내부 인터페이스를 제공합니다.다른 피어로부터 새 블록이 수신되면 체인 컨트롤러는 이러한 블록을 포크 DB로 푸시합니다.그러면 각 블록이 이전 블록에 암호학적으로 연결됩니다.이전 블록이 두 개 이상 있을 수 있으므로 이 프로세스에서 미니 포크라고 하는 임시 분기가 생성될 가능성이 높습니다.따라서 포크 DB는 세 가지 주요 용도로 사용됩니다.

  • 푸시된 블록 (새 헤드 블록) 이 어느 브랜치에서 생성될지 확인하십시오.
  • 헤드 블록, 루트 블록 및 LIB 블록을 전진시키십시오.
  • 유효하지 않은 가지를 잘라내고 고립된 블록을 제거하세요.

기본적으로 포크 DB에는 블록체인을 계속 성장시키는 실제 브랜치가 될 수 있는 노드 내의 모든 후보 블록 브랜치가 포함됩니다.루트 블록은 항상 되돌릴 수 있는 블록 트리의 시작을 표시하며 LIB 블록과 일치합니다. 단, LIB가 전진하는 경우에는 루트 블록이 이를 따라잡아야 합니다.LIB 블록이 Fork DB 내의 새 블록을 통과하면서 계산하면 궁극적으로 어떤 브랜치를 선택할지가 결정됩니다.LIB 블록이 발전함에 따라 루트 블록이 새 LIB를 따라잡으며 상위 노드가 LIB 뒤에 있는 모든 후보 분기가 제거됩니다.이것은 아래에 묘사되어 있습니다.

![](/images/protocol-p2p_local_chain_prunning.png "Local Chain (after pruning)“)

위 다이어그램에서 블록 52b에서 시작하는 분기는 LIB가 노드 51에서 블록 52c, 53c로 이동한 후 정리됩니다 (블록 52b, 53a, 53b는 유효하지 않음).LIB가 리버서블 블록을 통해 이동하면서 이제는 불변의 블록체인의 일부가 되어 포크 DB에서 로컬 체인으로 이동합니다.마지막으로, 블록 54d는 포크 DB에 보관됩니다. 새 블록이 여전히 포크 DB에서 생성될 수 있기 때문입니다.

2.3.넷 플러그인

Net 플러그인은 EOS 노드 간의 실제 P2P 통신 메시지를 정의합니다.Net Plugin의 주요 목표는 요청 시 유효한 블록을 동기화하고 유효한 트랜잭션을 변함없이 전달하는 것입니다.이를 위해 Net Plugin은 다음 구성 요소에 기능을 위임합니다.

*Sync Manager: 피어에 대한 노드의 블록 동기화 상태를 유지합니다. *디스패치 관리자: 노드가 보낸 블록 및 트랜잭션 목록을 관리합니다. *연결 목록: 노드가 현재 연결되어 있는 활성 피어 목록입니다. *메시지 핸들러: 프로토콜 메시지를 해당 핸들러에 전달합니다.(참조 4.2.프로토콜 메시지).

2.3.1.동기화 관리자

Sync Manager는 노드와 해당 피어 간에 블록 상태를 동기화하는 기능을 구현합니다.각 피어가 보낸 메시지를 처리하고 해당 피어에 대한 노드의 LIB 또는 헤드 블록 상태를 기반으로 블록의 실제 동기화를 수행합니다.언제든지 노드는 다음과 같은 동기화 상태에 있을 수 있습니다.

  • LIB 캐치업: 노드가 다른 피어의 LIB 블록과 동기화하려고 합니다.
  • 헤드 캐치업: 노드가 다른 피어의 HEAD 블록과 동기화하려고 합니다. *In-Sync: LIB 블록과 HEAD 블록 모두 다른 피어와 동기화됩니다.

노드의 LIB 또는 헤드 블록이 뒤에 있는 경우 노드는 동기화 요청 메시지를 생성하여 연결된 피어에서 누락된 블록을 검색합니다.마찬가지로 연결된 피어의 LIB 또는 헤드 블록이 뒤에 있는 경우 노드는 동기화가 필요한 블록을 노드에 알리는 알림 메시지를 보냅니다.동기화 모드에 대한 자세한 내용은 을 참조하십시오. 3.작동 모드.

2.3.2.디스패치 매니저

디스패치 관리자는 노드가 수신한 블록 및 루즈 트랜잭션의 상태를 유지합니다.상태는 블록 또는 트랜잭션을 식별하는 기본 정보를 포함하며 블록 상태 및 트랜잭션 상태의 인덱싱된 두 목록 내에서 유지됩니다.

*블록 상태 목록: 수신된 모든 블록에 대해 노드가 관리하는 블록 상태 목록입니다. *트랜잭션 상태 목록: 수신된 모든 트랜잭션에 대해 노드에서 관리하는 트랜잭션 상태 목록입니다.

이를 통해 어떤 피어가 특정 블록이나 트랜잭션을 가지고 있는지 매우 빠르게 찾을 수 있습니다.

2.3.2.1.블록 상태

블록 상태는 블록과 해당 블록의 출처인 피어를 식별합니다.이는 일시적인 특성이므로 노드가 활성 상태일 때만 유효합니다.블록 상태에는 다음 필드가 포함됩니다.

블록 상태 필드설명
id256비트 블록 식별자.블록 내용과 블록 번호의 함수입니다.
block_num생성 이후 블록을 순차적으로 식별하는 32비트 부호 없는 카운터 값입니다.
connection_id블록이 생성된 연결된 피어를 식별하는 32비트 부호 없는 정수
have_block노드가 실제 블록을 수신했는지 여부를 나타내는 부울 값.

블록 상태 목록은 더 빠르게 조회할 수 있도록 블록 ID, 블록 번호 및 연결 ID별로 인덱싱됩니다.이렇게 하면 인덱싱된 속성 중 하나 이상이 지정된 블록에 대한 목록을 쿼리할 수 있습니다.

2.3.2.2.트랜잭션 상태

트랜잭션 상태는 루즈 트랜잭션과 해당 트랜잭션의 출처인 피어를 식별합니다.또한 일시적인 특성이기도 하므로 노드가 활성 상태일 때만 유효합니다.트랜잭션 상태에는 다음 필드가 포함됩니다.

트랜잭션 상태 필드설명
id트랜잭션 식별자로 사용되는 트랜잭션 인스턴스의 256비트 해시
expiresEOS 블록 타임스탬프 시대 (2000년 1월 1일) 이후의 만료 시간
block_num현재 헤드 블록 번호.LIB가 이를 따라잡으면 트랜잭션이 중단됩니다.
connection_id트랜잭션이 발생한 연결된 피어를 식별하는 32비트 정수

block_num 트랜잭션이 수신될 때 노드의 헤드 블록 번호를 저장합니다.LIB 블록 번호가 만료 여부에 관계없이 헤드 블록 번호를 따라잡을 때 트랜잭션을 삭제하는 백업 메커니즘으로 사용됩니다.

거래 상태 목록은 더 빠른 조회를 위해 거래 ID, 만료 시간, 블록 번호 및 연결 ID를 기준으로 인덱싱됩니다.이렇게 하면 인덱싱된 속성 중 하나 이상이 지정된 트랜잭션의 목록을 쿼리할 수 있습니다.

2.3.2.3.주정부 재활용

LIB 블록이 발전함에 따라 (참조 3.3.1.LIB 캐치업 모드) 에서 새 LIB 블록 이전의 모든 블록은 완료된 것으로 간주되므로 해당 상태는 로컬 블록 상태 목록에서 제거됩니다. 여기에는 노드가 유지 관리하는 연결 목록에서 각 피어가 소유한 블록 상태 목록이 포함됩니다.마찬가지로, 거래 상태는 만료 시간을 기준으로 거래 목록에서 제거됩니다.따라서 트랜잭션이 만료되면 해당 상태가 모든 트랜잭션 상태 목록에서 제거됩니다.

블록 상태 및 트랜잭션 상태 목록은 설치 공간이 적고 회전 속도가 빠르기 때문에 더 빠르게 액세스할 수 있도록 메모리에 보관됩니다.노드가 수신한 블록 및 트랜잭션의 실제 내용은 각각 적용된 트랜잭션과 적용되지 않은 트랜잭션에 대해 포크 데이터베이스 및 다양한 수신 대기열에 임시로 저장됩니다.

2.3.3.연결 목록

연결 목록에는 각 피어의 연결 상태가 포함됩니다.p2p 프로토콜 버전, 노드가 알고 있는 피어로부터의 블록 및 트랜잭션 상태, 해당 피어와의 현재 동기화 여부, 송수신 마지막 핸드셰이크 메시지, 피어가 노드에 정보를 요청했는지 여부, 소켓 상태, 노드 ID 등에 대한 정보를 보관합니다. 연결 상태에는 다음과 같은 관련 필드가 포함됩니다.

*정보 요청됨: 피어가 노드에 정보를 요청했는지 여부. *소켓 상태: TCP 연결 상태를 유지하는 소켓 구조에 대한 포인터. *노드 ID: 피어의 노드를 다른 피어와 구별하는 실제 노드 ID입니다.

  • 마지막 핸드셰이크 수신됨: 피어로부터 받은 마지막 핸드셰이크 메시지 인스턴스입니다.
  • 마지막 핸드셰이크 전송: 피어에 전송된 마지막 핸드셰이크 메시지 인스턴스입니다.
  • 핸드셰이크 전송 수: 피어에 전송된 핸드셰이크 메시지 수입니다. *동기화: 노드가 피어와 동기화되는지 여부입니다. *프로토콜 버전: 피어의 Net 플러그인에 의해 구현된 내부 프로토콜 버전입니다.

블록 상태는 다음 필드로 구성됩니다.

*블록 ID: 블록의 직렬화된 내용의 해시입니다. *블록 번호: 생성 이후 실제 블록 번호입니다.

트랜잭션 상태는 다음 필드로 구성됩니다.

*거래 ID: 거래의 직렬화된 내용의 해시입니다. *블록 번호: 거래가 포함된 실제 블록 번호입니다. *만료 시간: 거래가 만료되는 시간 (초) 입니다.

2.4.Net 시리얼라이저

Net 시리얼라이저에는 두 가지 주요 역할이 있습니다.

  • 네트워크를 통해 전송해야 하는 객체 및 메시지를 직렬화합니다.
  • 암호화 해싱이 필요한 객체와 메시지를 직렬화합니다.

첫 번째 경우, 직렬화된 각 객체 또는 메시지는 추가 처리를 위해 네트워크로부터 수신되는 즉시 다른 쪽 끝에서 역직렬화되어야 합니다.후자의 경우, 해당 콘텐츠의 암호화 해시를 생성하려면 객체 인스턴스 내의 특정 필드를 직렬화해야 합니다.지정된 객체 유형 (액션, 트랜잭션, 블록 등) 에 대해 생성되는 대부분의 ID는 객체 인스턴스의 관련 필드에 대한 암호화 해시로 구성됩니다.

3.작동 모드

운영 관점에서 노드는 연결된 피어와 관련하여 다음 세 가지 상태 중 하나에 속할 수 있습니다.

  • In-Sync 모드: 노드가 피어와 동기화되어 있으므로 해당 피어에서 블록이 필요하지 않습니다.
  • LIB 캐치업 모드: LIB 블록이 해당 피어의 LIB 뒤에 있기 때문에 노드에는 블록이 필요합니다.
  • HEAD 캐치업 모드: HEAD 블록이 해당 피어의 헤드 뒤에 있기 때문에 노드에는 블록이 필요합니다.

각 노드의 작동 모드는 nodeos 서비스의 Net Plugin 내 동기화 관리자 컨텍스트에 저장됩니다.따라서 노드는 연결된 피어에 대해 항상 in-sync 모드 또는 일부 변형 캐치업 모드에 있습니다.이를 통해 LIB 및 헤드 블록이 업데이트되고 다른 피어로부터 새로운 블록이 수신됨에 따라 노드가 캐치업 모드와 인싱크 모드 사이를 오갈 수 있습니다.

3.1.블록 ID

EOS 소프트웨어는 블록 ID를 비교하여 두 블록이 일치하는지 또는 동일한 콘텐츠를 보유하고 있는지 확인합니다.블록 ID는 블록 헤더의 내용과 블록 번호에 따라 달라지는 함수입니다 (참조). 컨센서스 프로토콜: 5.1.블록 구조).노드의 로컬 체인을 피어의 로컬 체인과 동기화하려면 두 블록이 같은지 확인하는 것이 중요합니다.블록 내용에서 블록 ID를 생성하기 위해 블록 헤더를 직렬화하고 SHA-256 다이제스트를 생성합니다.가장 중요한 32비트에는 블록 번호가 할당되고 해시의 최하위 224비트는 유지됩니다.블록 헤더에는 트랜잭션 머클 트리와 액션 머클 트리 모두의 루트 해시가 포함된다는 점에 유의하십시오.따라서 블록 ID는 블록에 포함된 모든 트랜잭션과 각 트랜잭션에 포함된 모든 작업에 따라 달라집니다.

3.2.인싱크 모드

인싱크 모드에서는 노드의 헤드 블록이 피어의 헤드 블록과 맞물려 노드가 블록 단위로 동기화됩니다.노드가 동기화 모드일 때는 피어로부터 추가 블록을 요청하지 않지만 다른 기능은 계속 수행합니다.

*거래 검증, 유효하지 않은 경우 삭제하고, 유효하면 다른 동료에게 전달하십시오. *블록 검증, 유효하지 않은 경우 삭제하고, 유효한 경우 요청 시 다른 피어에 전달합니다.

따라서 이 모드는 대기 시간에 유리하게 대역폭을 거래하며, 처리 오버헤드가 낮아 TAPO (지분 증명으로서의 트랜잭션) 에 의존하는 트랜잭션을 검증하는 데 특히 유용합니다.

참고로, 느슨한 거래는 유효하고 만료되지 않은 경우 항상 전달됩니다.반면 블록은 유효하고 피어가 명시적으로 요청한 경우에만 전달됩니다.이렇게 하면 네트워크 오버헤드가 줄어듭니다.

3.3.캐치업 모드

헤드 블록이 피어의 LIB 또는 피어의 헤드 블록 뒤에 있을 때 노드는 캐치업 모드에 있습니다.동기화가 필요한 경우 다음 두 단계로 순차적으로 수행됩니다.

1.가장 가까운 공통 조상 + 1에서 피어의 LIB까지 노드의 LIB를 동기화합니다. 2.가장 가까운 공통 조상 + 1의 노드 헤드를 피어의 헤드와 동기화합니다.

따라서 노드의 LIB 블록이 먼저 업데이트되고 그 다음에 노드의 헤드 블록이 업데이트됩니다.

3.3.1.LIB 캐치업 모드

노드의 LIB 블록이 피어의 LIB 블록을 따라잡아야 하는 위의 사례 1은 동기화 전후의 아래 다이어그램에 나와 있습니다 (참고: 명확성을 위해 적용할 수 없는 분기는 제거됨).

위 다이어그램에서 노드의 로컬 체인은 최종 블록 91과 92 (피어의 LIB) 를 노드의 LIB (블록 90) 에 추가하여 피어의 로컬 체인과 동기화됩니다.이렇게 하면 블록 91n, 92n, 93n으로 구성된 임시 포크가 삭제된다는 점에 유의하세요.또한 이러한 노드에는 “n” 접미사 (노드의 줄임말) 가 붙어 있으므로 피어의 블록과 다를 수 있습니다. 이는 피어의 미완성 블록에도 동일하게 적용되며 끝이 “p" (peer의 줄임말) 로 끝납니다.동기화 후에는 LIB (lib) 와 헤드 블록 (hb) 모두 노드에서 동일한 블록 번호를 갖는다는 점에 유의하십시오.

3.3.2.헤드 캐치업 모드

노드의 LIB 블록이 피어의 블록과 동기화되면 새 블록이 어느 체인으로든 푸시됩니다.위의 사례 2는 피어의 체인이 노드의 체인보다 긴 경우를 다룹니다.이는 동기화 전후의 노드와 피어의 로컬 체인을 보여주는 다음 다이어그램에 나와 있습니다.

위의 경우 1 또는 2에서 노드의 동기화 프로세스에는 노드의 헤드 블록에서 시작하여 체인을 다시 횡단하고 LIB 블록에서 끝나는 첫 번째 공통 상위 블록을 찾는 작업이 포함되며, 이 블록은 현재 동기화됩니다 (참조). 3.3.1.LIB 캐치업 모드).최악의 시나리오에서는 동기화된 LIB가 가장 가까운 공통 조상입니다.위 다이어그램에서 노드 체인은 헤드 블록 94n, 93n 등에서 순회하여 피어 체인의 블록 94p, 93p 등과 일치시킵니다.일치하는 첫 번째 블록이 가장 가까운 공통 조상입니다 (다이어그램의 블록 93n 및 93p).따라서 다음 블록 94p 및 95p가 검색되어 가장 가까운 공통 조상 (이제 93n, p) 으로 다시 레이블이 지정된 노드 체인에 추가됩니다 (참조). 3.3.3.블록 검색 프로세스).마지막으로 블록 95p는 노드의 헤드 블록이 되며, 노드가 피어와 완전히 동기화되므로 노드는 동기화 모드로 전환됩니다.

3.3.3.블록 검색

공통 조상을 찾은 후 동기화 요청 메시지가 전송되어 가장 가까운 공통 조상 다음의 다음 블록에서 시작하여 피어의 헤드 블록에서 끝나는 노드에 필요한 블록을 검색합니다.

대역폭을 효과적으로 사용하기 위해 필요한 블록은 필요한 경우 하나가 아닌 다양한 피어로부터 확보됩니다.필요한 블록 수에 따라 지정된 피어로부터 다운로드할 시작 블록 번호와 종료 블록 번호를 지정하여 블록을 청크 단위로 요청합니다.노드는 블록 상태 목록을 사용하여 각 피어에 있는 블록을 추적하므로, 이 정보는 블록 청크를 요청할 연결된 피어를 결정하는 데 사용됩니다.이 프로세스는 아래 다이어그램에 나와 있습니다.

LIB와 헤드 블록이 모두 피어와 관련되어 있으면 Sync Manager의 작동 모드가 캐치업 모드에서 인싱크 모드로 전환됩니다.

3.4.모드 전환

결국 노드와 해당 피어 모두 다른 피어로부터 새로운 블록을 받게 되고, 이는 다시 해당 블록을 각각의 로컬 체인으로 푸시합니다.이로 인해 각 체인의 헤드 블록이 전진합니다.어떤 체인이 먼저 성장하는지에 따라 다음 작업 중 하나가 발생합니다.

  • 노드는 헤드 블록 정보와 함께 캐치 업 요청 메시지를 피어에게 보냅니다.
  • 노드는 동기화가 필요함을 피어에게 알리기 위해 catch up 알림 메시지를 보냅니다.

첫 번째 경우, 노드는 모드를 인싱크 모드에서 헤드 캐치업 모드로 전환합니다.두 번째 경우에는 피어가 노드로부터 알림 메시지를 받은 후 헤드 캐치업 모드로 전환합니다.실제로 인싱크 모드는 수명이 짧습니다.EOS 블록체인이 매우 바쁠 때 노드는 대부분의 시간을 캐치업 모드에서 트랜잭션을 검증하고 캐치업 메시지가 수신된 후 체인을 동기화하는 데 보냅니다.

4.프로토콜 알고리즘

p2p 프로토콜 알고리즘은 모든 노드에서 실행되며 검증된 트랜잭션과 검증된 블록을 전달합니다.EOS v2.0부터 노드는 수신한 검증되지 않은 블록의 블록 ID도 전달합니다.일반적으로 간소화된 프로세스는 다음과 같습니다.

1.노드는 데이터를 요청하거나 제어 메시지를 피어에 전송합니다. 2.요청을 이행할 수 있는 경우 피어가 요청을 실행합니다. 1을 반복합니다.

데이터 메시지에는 블록 내용 또는 트랜잭션 내용이 포함됩니다.제어 메시지를 통해 노드와 해당 피어 간에 블록과 트랜잭션을 동기화할 수 있습니다 (참조). 프로토콜 메시지).이러한 동기화를 허용하려면 각 노드가 자체 블록 및 트랜잭션 상태와 피어 상태에 대한 정보를 검색할 수 있어야 합니다.

4.1.노드/피어 상태

상태 동기화를 시도하기 전에 각 노드는 자체 블록 및 트랜잭션의 현재 상태를 알아야 합니다.또한 동일한 정보를 얻기 위해 다른 피어를 쿼리할 수 있어야 합니다.특히 노드는 요청 시 다음을 얻을 수 있어야 합니다.

  • 각 노드는 현재 보유하고 있는 블록과 트랜잭션을 확인할 수 있습니다.
  • 모든 노드는 동료가 보유한 블록과 트랜잭션을 확인할 수 있습니다.
  • 각 노드는 자신이 요청한 블록과 트랜잭션을 확인할 수 있습니다.
  • 모든 노드는 각 노드가 언제 특정 트랜잭션을 수신했는지 확인할 수 있습니다.

이러한 쿼리를 수행하고 이후에 상태를 동기화할 때 Net Plugin은 노드 간에 교환할 특정 통신 메시지를 정의합니다.이러한 메시지는 TCP 연결을 통해 전송 및 수신될 때 Net Plugin에 의해 전송됩니다.

4.2.프로토콜 메시지

p2p 프로토콜은 P2P 노드 통신을 위해 다음과 같은 제어 메시지를 정의합니다.

제어 메시지설명
handshake_message다른 피어와의 연결을 시작하고 LIB/HEAD 상태를 전송합니다.
chain_size_message피어에게 LIB/헤드 상태를 요청합니다.현재 구현되지 않았습니다.
go_away_message연결 또는 연결된 피어에게 연결 해제 알림을 보냅니다.
time_message피어 동기화 및 오류 감지를 위한 타임스탬프를 전송합니다.
notice_message현재 어떤 블록과 트랜잭션 노드가 가지고 있는지 피어에게 알려줍니다.
request_message현재 어떤 블록과 트랜잭션 노드가 필요한지 피어에게 알려줍니다.
sync_request_message요청은 시작/종료 블록 번호가 지정된 블록 범위를 피어링합니다.

이 프로토콜은 또한 P2P 네트워크상의 피어 간에 블록의 실제 내용이나 느슨한 트랜잭션을 교환하기 위해 다음과 같은 데이터 메시지를 정의합니다.

데이터 메시지설명
signed_block서명된 블록의 직렬화된 내용.
packed_transaction패키징된 트랜잭션의 직렬화된 콘텐츠.

4.2.1.핸드셰이크 메시지

핸드셰이크 메시지는 다른 피어에 연결할 때 노드에서 전송됩니다.연결 노드가 체인 상태 (LIB 번호/ID 및 헤드 블록 번호/ID) 를 피어에 전달하는 데 사용됩니다.또한 피어는 노드가 처음 연결될 때 노드가 동일한 블록체인에 속하는지 여부, 필드가 범위 내에 있는지 확인, LIB가 헤드 블록보다 앞서는지 여부 등 노드의 일관되지 않은 블록 상태를 감지하는 등 노드에 대한 기본 검증을 수행하는 데 사용됩니다. 핸드셰이크 메시지는 다음 필드로 구성됩니다.

메시지 필드설명
network_version프로토콜 업데이트를 추적하기 위한 내부 넷 플러그인 버전
chain_id제네시스 상태 및 구성 옵션의 해시 값.체인을 식별하는 데 사용됩니다.
node_id피어의 노드를 다른 피어와 구별하는 실제 노드 ID.
key피어가 노드를 검증하기 위한 공개 키. 프로듀서 또는 피어 키이거나 비어 있을 수 있습니다.
time타임스탬프 핸드셰이크 메시지는 에포크 (2000년 1월 1일) 이후 생성되었습니다.
token노드가 위 키의 개인 키를 소유하고 있음을 증명하는 타임스탬프의 SHA-256 다이제스트
sig노드가 위 키의 개인 키로 서명한 후 위 다이제스트에 서명합니다.
p2p_address노드의 IP 주소입니다.
last_irreversible_block_num생성 이후 LIB 블록의 실제 블록 수
last_irreversible_block_idLIB 블록의 직렬화된 내용의 해시입니다.
head_num창세 이후 헤드 블록의 실제 블록 수
head_id헤드 블록의 직렬화된 내용의 해시입니다.
os노드가 실행되는 운영 체제.이는 자동으로 감지됩니다.
agent다른 노드에서 자신을 식별하기 위해 노드에서 제공하는 이름입니다.
generation개수 handshake_message 호출, 검증을 위한 첫 번째 호출을 감지합니다.

모든 검사가 성공하면 피어는 다음을 기반으로 연결 노드를 인증합니다. --allowed-connection 다음과 같은 경우 해당 피어의 넷 플러그인에 지정된 설정 nodeos 시작:

*모두: 인증 없이 연결이 허용됩니다. *프로듀서: 피어 키는 p2p 프로토콜을 통해 획득됩니다. *지정: 설정을 통해 피어 키가 제공됩니다.

  • 없음: 노드가 연결 요청을 허용하지 않습니다.

피어 키는 피어에 연결하려는 노드의 공개 키에 해당합니다.인증에 성공하면 수신 노드는 핸드셰이크 메시지를 다시 전송하여 연결 노드를 승인합니다. 연결 노드는 위와 같은 방식으로 유효성을 검사합니다.마지막으로 수신 노드는 피어의 헤드 블록 또는 자체 헤드 블록에 동기화가 필요한지 여부를 확인합니다.이는 헤드 블록의 상태와 연결 노드의 LIB 상태를 자체 노드와 대조하여 확인합니다.이러한 검사를 통해 수신 노드는 동기화가 필요한 체인을 결정합니다.

4.2.2.체인 크기 메시지

체인 크기 메시지는 향후 사용을 위해 정의되었지만 현재 구현되지 않았습니다.아이디어는 다른 피어와 성공적으로 연결되면 노드의 체인 상태에 대한 임시 상태 알림을 보내는 것이었습니다.체인 크기 메시지는 다음 필드로 구성됩니다.

메시지 필드설명
last_irreversible_block_num생성 이후 LIB 블록의 실제 블록 수
last_irreversible_block_idLIB 블록의 직렬화된 내용의 해시입니다.
head_num창세 이후 헤드 블록의 실제 블록 수
head_id헤드 블록의 직렬화된 내용의 해시입니다.

체인 크기 메시지는 핸드셰이크 메시지로 대체되며, 이 메시지에는 LIB 및 헤드 블록의 상태도 전송되지만 추가 정보가 포함되므로 더 좋습니다.

4.2.3.고 어웨이 메시지

Go away 메시지는 연결을 닫기 전에 피어에 전송됩니다.일반적으로 오류가 발생하여 노드가 p2p 프로토콜을 계속 사용할 수 없게 됩니다.외출 메시지는 다음 필드로 구성됩니다.

메시지 필드설명
reason피어와의 연결을 끊어야 하는 이유를 나타내는 오류 코드
node_id연결 해제 노드의 노드 ID로, 중복 알림에 사용됩니다.

현재 원인 코드는 다음과 같이 정의됩니다.

*이유 없음: 실제로 오류가 없음을 나타냅니다. 기본값입니다. *Self: 노드가 자체 연결을 시도했습니다. *중복: 피어에서 중복 연결이 감지되었습니다. *잘못된 체인: 피어의 체인 ID가 일치하지 않습니다. *잘못된 버전: 피어의 네트워크 버전이 일치하지 않습니다. *Forked: 피어의 돌이킬 수 없는 블록이 다릅니다 *연결 해제: 피어가 우리가 사용할 수 없는 블록을 전송했습니다. *잘못된 거래: 피어가 트랜잭션을 전송했지만 확인에 실패했습니다. *검증: 피어가 검증에 실패한 블록을 전송했습니다. *양호한 기타: 타임아웃과 같은 이유. 치명적이지는 않지만 재설정이 필요합니다.

  • 치명적 기타: 아직 발견되지 않은 치명적 오류를 모두 찾아냅니다. *인증: 피어 인증 실패.

피어가 go away 메시지를 수신한 후 피어는 연결도 닫아야 합니다.

4.2.4.타임 메시지

시간 메시지는 피어 간의 이벤트를 동기화하고, 시간 간격을 측정하고, 중복 메시지, 잘못된 타임스탬프, 손상된 노드 등과 같은 네트워크 이상을 탐지하는 데 사용됩니다. 시간 메시지는 다음 필드로 구성됩니다.

메시지 필드설명
org오리진 타임스탬프, 시간 간격의 시작을 표시할 때 설정합니다.
rec타임스탬프 수신. 네트워크에서 메시지가 도착하는 시점을 설정합니다.
xmt전송 타임스탬프, 메시지가 전송 대기열에 배치되는 시기를 설정합니다.
dst대상 타임스탬프, 시간 간격의 끝을 표시할 때 설정합니다.

4.2.5.공지 메시지

알림 메시지는 노드가 현재 가지고 있는 블록 트랜잭션과 루즈 트랜잭션을 피어에 알리기 위해 전송됩니다.알림 메시지는 다음 필드로 구성됩니다.

메시지 필드설명
known_trx알려진 거래 ID 노드의 정렬된 목록을 사용할 수 있습니다.
known_blocks알려진 블록 ID 노드의 정렬된 목록을 사용할 수 있습니다.

알림 메시지는 실제 블록이나 거래가 아닌 블록 ID와 거래 ID만 포함하므로 간단합니다.

4.2.6.요청 메시지

요청 메시지는 현재 노드에 필요한 블록 및 루스 트랜잭션을 피어에게 알리기 위해 전송됩니다.요청 메시지는 다음 필드로 구성됩니다.

메시지 필드설명
req_trx노드에 필요한 요청된 트랜잭션 ID의 정렬된 목록.
req_blocks노드에 필요한 요청된 블록 ID의 정렬된 목록.

4.2.7.동기화 요청 메시지

동기화 요청 메시지는 피어로부터 다양한 블록을 요청합니다.동기화 요청 메시지는 다음 필드로 구성됩니다.

메시지 필드설명
start_block피어로부터 수신할 블록 범위의 시작 블록 번호입니다.
end_block피어로부터 수신할 블록 범위의 최종 블록 번호입니다.

동기화 요청 메시지를 수신하면 피어는 지정된 블록 번호 범위에 해당하는 실제 블록을 다시 전송합니다.

4.3.메시지 핸들러

p2p 프로토콜은 이벤트 기반 모델을 사용하여 메시지를 처리하므로 메시지 수신 시 폴링이나 루핑이 필요하지 않습니다.내부적으로 각 메시지는 대기열에 배치되고 행에 있는 다음 메시지는 처리를 위해 해당 메시지 핸들러로 전달됩니다.높은 수준에서 메시지 핸들러는 다음과 같이 정의할 수 있습니다.

   receiver/read handler:
if handshake message:
verify that peer's network protocol is valid
if node's LIB < peer's LIB:
sync LIB with peer's; continue
if node's LIB > peer's LIB:
send LIB catchup notice message; continue
if notice message:
update list of blocks/transactions known by remote peer
if trx message:
insert into global state as unvalidated
validate transaction; drop if invalid, forward if valid
else
close the connection

4.4.전송 대기열

프로토콜 메시지는 버퍼 큐에 배치되고 연결된 적절한 피어로 전송됩니다.상위 수준에서 노드는 연결된 각 피어에 대해 라운드 로빈 방식으로 다음 작업을 수행합니다.

   send/write loop:
if peer knows the LIB:
if peer does not know we have a block or transaction:
next iteration
if peer does not know about a block:
send transactions for block that peer does not know
next iteration
if peer does not know about transactions:
sends oldest transactions unknown to remote peer
next iteration
wait for new validated block, transaction, or peer signal
else:
assume peer is in catchup mode (operating on request/response)
wait for notice of sync from the read loop

#5.프로토콜 개선

p2p 프로토콜에 대한 모든 소프트웨어 업데이트도 모든 노드에서 점진적이고 일관되게 확장되어야 합니다.따라서 업데이트를 설치하여 운영 중단 시간을 줄이고 잠재적으로 완전히 최소화하는 동시에 가능하면 이전 버전과 호환되는 방식으로 새 기능을 배포해야 합니다.반면, 프로토콜 메시지의 데이터 압축 및 이진 인코딩을 사용하는 등 메시지 풋프린트를 최소화하는 조치를 취하면 데이터 처리량을 늘릴 수 있습니다.