p2p.Server 아키텍처, 피어 라이프사이클 관리, 연결 타입, 프로토콜 멀티플렉싱에 대한 세부사항을 제공합니다.피어 발견 메커니즘에 대한 정보는 발견 메커니즘을 참조하세요.
블록체인 동기화 프로토콜에 대한 세부사항은 체인 동기화을 참조하세요.
프로토콜 핸들러 구현은 프로토콜 핸들러을 참조하세요.
서버 아키텍처
P2P 레이어는 모든 피어 연결을 관리하고 StableNet 노드의 핵심 네트워킹 기능을 구현하는p2p.Server 구조체를 중심으로 구성됩니다.이 서버는 인바운드 및 아웃바운드 연결을 통합 관리하며, 발견 프로토콜과 프로토콜 핸들러 사이의 중재자 역할을 수행합니다.
서버 구조
Server 구조체는 다음과 같은 주요 구성 요소를 유지합니다:
| Component | Type | Purpose |
|---|---|---|
Config | p2p.Config | 최대 피어 수, 리슨 주소, 활성 프로토콜 등 네트워크 구성 |
localnode | *enode.LocalNode | 로컬 노드의 신원 정보 및 ENR 관리 |
listener | net.Listener | 인바운드 TCP 연결 수신 |
dialsched | *dialScheduler | 아웃바운드 연결 시도 스케줄링 |
discmix | *enode.FairMix | 여러 발견 소스를 집계 |
ntab | *discover.UDPv4 | Discovery v4 프로토콜 핸들러 |
DiscV5 | *discover.UDPv5 | Discovery v5 프로토콜 핸들러 |
nodedb | *enode.DB | 영속 노드 데이터베이스 |
서버 구성 및 초기화
서버 초기화 시퀀스는 다음과 같은 단계로 진행됩니다:setupLocalNode()
개인 키를 기반으로 로컬 노드 ID와 ENR을 생성하고 노드 데이터베이스를 초기화합니다.setupListening()
구성된 네트워크 주소에서 TCP 리스너를 시작합니다.setupDiscovery()
Discovery v4/v5 프로토콜을 초기화하고 발견 믹서를 구성합니다.setupDialScheduler()
정적 노드 및 발견 노드를 대상으로 하는 다이얼 스케줄러를 생성합니다.run()
피어 이벤트를 처리하는 서버 메인 이벤트 루프를 시작합니다.listenLoop()
인바운드 연결을 지속적으로 수락합니다.
서버 메인 루프
서버의 메인 이벤트 루프는 다음과 같은 역할을 수행합니다:- 피어 추가 및 제거 이벤트 처리
- 다이얼 스케줄러로부터의 연결 요청 처리
- 종료 신호 수신 시 모든 피어를 정상 종료
- 이벤트 피드로 피어 상태 변경 알림 전파
피어 라이프사이클
각 연결된 피어는 연결 상태, 프로토콜 핸들러, 수명 주기 정보를 캡슐화하는Peer 구조체로 표현됩니다.
연결 설정 흐름
피어 연결은 다음 흐름을 따릅니다:- TCP 연결 수립
- 암호화 핸드셰이크 수행
- 프로토콜 핸드셰이크 및 기능 협상
- 프로토콜 멀티플렉싱 설정
- 피어 등록 및 이벤트 발생
핸드셰이크 프로토콜
연결 설정에는 두 단계의 핸드셰이크가 포함됩니다:- 암호화 핸드셰이크 (
doEncHandshake)
RLPX 기반 암호화 채널을 설정합니다. - 프로토콜 핸드셰이크 (
doProtoHandshake)
지원 프로토콜 및 버전을 협상합니다.
protoHandshake 구조체는 다음 정보를 포함합니다:
| Field | Type | Description |
|---|---|---|
Version | uint64 | P2P 프로토콜 버전 |
Name | string | 클라이언트 식별 문자열 |
Caps | []Cap | 지원 프로토콜 기능 목록 |
ListenPort | uint64 | 리슨 포트 |
ID | []byte | 노드 공개 키 |
프로토콜 멀티플렉싱
핸드셰이크 이후 서버는 공통으로 지원되는 프로토콜을 매칭하고, 각 프로토콜에 메시지 코드 범위를 할당합니다.- 기본 P2P 메시지: 코드 0–15
- 첫 번째 매칭된 서브프로토콜: 코드 16부터 시작
- 이후 프로토콜은 이전 프로토콜 길이만큼 오프셋 증가
연결 타입 및 관리
P2P 서버는connFlag를 사용하여 연결 타입을 구분합니다:
| Flag | Value | Description |
|---|---|---|
dynDialedConn | 1 << 0 | 발견을 통해 생성된 아웃바운드 연결 |
staticDialedConn | 1 << 1 | 정적 노드로의 아웃바운드 연결 |
inboundConn | 1 << 2 | 외부에서 들어온 인바운드 연결 |
trustedConn | 1 << 3 | 신뢰 피어(MaxPeers 제한 초과 가능) |
피어 제한 및 용량
기본적인 피어 용량 제어 정책은 다음과 같습니다:MaxPeers: 전체 피어 수 제한MaxPendingPeers: 연결 대기 피어 수 제한(방향당 기본 50)DialRatio: 아웃바운드 피어 비율(기본 1/3)
다이얼 스케줄러
dialScheduler는 아웃바운드 연결 시도를 관리합니다:
- 최근 다이얼 기록을 유지하여 과도한 재시도를 방지
- 정적 노드를 발견 노드보다 우선 연결
- 최대 다이얼 연결 수 제한 준수
- 지수 백오프를 사용하여 실패한 엔드포인트 재시도 제한
피어 작업 및 라이프사이클
피어 추가 및 제거
서버는 다음 메서드를 통해 피어 집합을 관리합니다:| Method | Purpose |
|---|---|
AddPeer(node) | 정적 피어 추가 및 자동 재연결 |
RemovePeer(node) | 정적 피어 제거 및 연결 해제 |
AddTrustedPeer(node) | 신뢰 피어 추가 |
RemoveTrustedPeer(node) | 신뢰 피어 제거 |
연결 해제 이유
연결 해제 사유는DiscReason 코드로 기록됩니다:
| Reason | Code | Description |
|---|---|---|
DiscRequested | 0x00 | 정상 종료 |
DiscNetworkError | 0x01 | 네트워크 오류 |
DiscProtocolError | 0x02 | 프로토콜 위반 |
DiscUselessPeer | 0x03 | 유효하지 않은 피어 |
DiscTooManyPeers | 0x04 | 피어 수 제한 초과 |
DiscAlreadyConnected | 0x05 | 중복 연결 |
DiscIncompatibleVersion | 0x06 | 버전 불일치 |
DiscInvalidIdentity | 0x07 | 잘못된 노드 ID |
DiscQuitting | 0x08 | 서버 종료 |
DiscSubprotocolError | 0x10 | 서브프로토콜 오류 |
피어 이벤트 피드
서버는 피어 상태 변화를PeerEvent로 외부에 알립니다:
| Event Type | Description |
|---|---|
PeerEventTypeAdd | 피어 연결 및 등록 |
PeerEventTypeDrop | 피어 연결 해제 |
PeerEventTypeMsgSend | 메시지 전송 |
PeerEventTypeMsgRecv | 메시지 수신 |
Ethereum 백엔드와의 통합
Ethereum 백엔드는 프로토콜 등록 과정을 통해 P2P 서버와 통합됩니다. 통합 흐름은 다음과 같습니다:eth.Ethereum.Protocols()– 프로토콜 정의 반환eth.MakeProtocols()– eth 서브프로토콜 핸들러 생성snap.MakeProtocols()– snap 프로토콜 핸들러 생성(활성화 시)node.Stack.RegisterProtocols()– P2P 서버에 등록handler.Start()– 프로토콜 메시지 처리 시작
백엔드의 P2P 서버 참조
백엔드는 RPC 서비스를 위해 P2P 서버 참조를 유지하며, 이는 다음 용도로 사용됩니다:NetAPI– 네트워크 정보 조회AdminAPI– 피어 관리 RPC- ENR 동적 업데이트
구성 플래그
P2P 네트워크 구성에 사용되는 주요 플래그는 다음과 같습니다:| Flag | Type | Default | Description |
|---|---|---|---|
--maxpeers | int | DefaultConfig.P2P.MaxPeers | 최대 피어 수 |
--maxpendpeers | int | 0 | 대기 피어 수 제한 |
--port | int | 30303 | 네트워크 리슨 포트 |
--bootnodes | string | Network-specific | 부트스트랩 노드 |
--nodekey | string | - | P2P 노드 키 경로 |
--nodekeyhex | string | - | 테스트용 노드 키(hex) |
--nodiscover | bool | false | 피어 발견 비활성화 |
--netrestrict | string | - | CIDR 네트워크 제한 |
SetP2PConfig() 및 setNodeKey()를 통해 적용됩니다.
