• IPFS 프로토콜 IPNS 계층 분석 - 인터페이스

    IPFS Name Service-Interface

    IPFS Naming 계층의 구체적인 구현에 대하여 설명하고자 합니다. 먼저 이 계층의 인터페이스를 보면 아래와 같습니다.

    NameService interface code

    ...
    type NameSystem interface {
        Resolver
        Publisher
    }
    
    // Result is the return type for Resolver.ResolveAsync.
    type Result struct {
        Path path.Path
        Err error
    }
    
    // Resolver is an object capable of resolving names.
    type Resolver interface {
        // Resolve performs a recursive lookup, returning the dereferenced
        // path. For example, if ipfs.io has a DNS TXT record pointing to
        // /ipns/QmatmE9msSfkKxoffpHwNLNKgwZG8eT9Bud6YoPab52vpy
        // and there is a DHT IPNS entry for
        // QmatmE9msSfkKxoffpHwNLNKgwZG8eT9Bud6YoPab52vpy
        // -> /ipfs/Qmcqtw8FfrVSBaRmbWwHxt3AuySBhJLcvmFYi3Lbc4xnwj
        // then
        // Resolve(ctx, "/ipns/ipfs.io")
        // will resolve both names, returning
        // /ipfs/Qmcqtw8FfrVSBaRmbWwHxt3AuySBhJLcvmFYi3Lbc4xnwj
        //
        // There is a default depth-limit to avoid infinite recursion. Most
        // users will be fine with this default limit, but if you need to
        // adjust the limit you can specify it as an option.
        Resolve(ctx context.Context, name string, options ...opts.ResolveOpt) (value path.Path, err error)
    
        // ResolveAsync performs recursive name lookup, like Resolve, but it returns
        // entries as they are discovered in the DHT. Each returned result is guaranteed
        // to be "better" (which usually means newer) than the previous one.
        ResolveAsync(ctx context.Context, name string, options ...opts.ResolveOpt) <-chan Result
    }
    
    // Publisher is an object capable of publishing particular names.
    type Publisher interface {
        // Publish establishes a name-value mapping.
        // TODO make this not PrivKey specific.
        Publish(ctx context.Context, name ci.PrivKey, value path.Path) error
    
        // TODO: to be replaced by a more generic 'PublishWithValidity' type
        // call once the records spec is implemented
        PublishWithEOL(ctx context.Context, name ci.PrivKey, value path.Path, eol time.Time) error
    }
    

    인터페이스 정의는 비교적 간단하게 구성되어 있습니다. 하나의 구조 인터페이스와 2개의 배포 인터페이스 (Resolve, Publish) 가 있습니다. 해당 로직의 모습은 다음과 같습니다.

    인터페이스 동작 절차

    응용 계층에서 IPFS 프로토콜에 의한 Hash 값을 네트워크에 Publish 하면 IPFS 노드는 먼저 자신의 ID 를 읽고 ID 에 대한 IPNS 의 매핑 데이터를 Local Storage 에서 검색하고 검색에 성공하면 데이터가 업데이트 됩니다. 그런 다음 Routing 계층의 PutValue 인터페이스를 호출하여 ID 및 최신 IPNS 매핑 데이터를 전체 네트워크에 Publish 합니다. Local Storage 에서 검색하지 못하면 Routing 계층의 GetValue 가 호출되어 전체 네트워크에서 해당 ID에 대한 IPNS 매핑 데이터를 검색하고 검색에 성공하면 데이터의 번호가 업데이트 되어 전체 네트워크에 다시 Publish 합니다. 매핑 데이터를 찾지 못하면 ID와 IPNS 에 대한 새로운 매핑 데이터가 생성되어 전체 네트워크에 Publilsh 됩니다.

    응용 계층이 IPNS 에서 ID 에 해당하는 IPFS Hash 데이터를 구문 분석할 때 Naming 계층은 먼저 로컬 Cache 에서 해당 매핑 데이터를 검색합니다. 상단의 Publish 링크에서 Routing 계층의 PutValue 가 성공하면 Naming 계층은 매핑된 데이터를 로컬 Cache 에 ‘Cache’ 하는 것으로 resolve 를 로컬에서 읽을 때 마다 네트워크 액세스 비용을 줄일 수 있습니다. 로컬 Cache 에서 검색에 실패하면 Naming 계층은 Routing 계층에 대한 GetValue 액세스 요청을 시작하고 액세스가 성공하면 응용 계층은 ID 에 대한 Hash 값을 받고 Hash 값을 통해 특정 데이터에 액세스할 수 있습니다.

    MerkleDAG 및 Routing 계층을 기반으로 데이터 교환 계층의 API 인터페이스는 고정된 Name 과 가변 데이터 Hash 값 및 매핑 데이터 검색 간의 매핑을 할 수 있기 때문에 Naming 계층의 특정 구현은 비교적 간단합니다. 하지만 적용 시나리오는 부족합니다. 아래는 무선 확장 스토리지 마운트를 예로들어 사용 방법을 설명합니다. 분산화된 무한 네트워크 확장은 매우 흥미로울 것 입니다.

    무선 확장 스토리지 예

    위 그림과 같이 Linux 디렉토리 구조를 예를들면 먼저 ‘IPFS Daemon’ 을 시작하고 ipfs mount 명령을 호출하여 전체 IPFS 네트워크를 “/” 디렉토리에 마운트 합니다 (해당 디렉토리에 마운트). “IPFS” 디렉토리가 나타나고 전체 IPFS 네트워크가 스토리지 서비스를 제공합니다. Naming 을 통해 이 디렉토리에 추가된 모든 파일과 디렉토리는 IPFS 에서 인식이 가능한 Hash 값으로 매핑됩니다. 이러한 방식으로 IPFS 네트워크에 추가되는 모든 종류의 저장 장치가 무제한 데이터 저장 서비스를 제공하게 됩니다.

    블록체인 프로젝트의 경우 이 네트워크를 기반으로 인센티브 메커니즘을 높일 수 있다면 유휴 저장 리소스를 사용하여 토큰을 통한 거래가 가능할 수 있습니다. 데이터 저장 및 읽기 서비스를 사용할 수 있는 유연한 방법으로 활용될 수 있습니다. 즉, 중복 저장 공간을 구입할 필요가 없으며 지불 금액을 결정할 수 있습니다.

    기업에서 사용하는 경우 이러한 스토리지 인트라넷을 구축하면 회사의 유휴 IT 장비의 리소스를 최대한 활용할 수 있습니다.

    모든 데이터는 모든 노드에 배포되고 암호화되어 저장되기 때문에 데이터 보안을 충족할 수 있으므로 데이터 유출에 대한 걱정이 줄어들 것 입니다.

    데이터 전송 프로세스에서 패킷 캡처 소프트웨어가 데이터를 캡처하지 못하도록 아래와 같이 데이터 재전송 프로세스를 활용하여 보안 문제를 해결할 수 있습니다.

    보안을 위한 기반 데이터 전송 활용

    • 클라이언트인 IPFS 노드는 콘텐츠 액세스 요청을 시작
    • 서버는 자신의 공개 키를 제공
    • 공개 키를 수신한 클라이언트는 서버에 자신의 공개 키를 보내기 위해 두개의 공개 키 C1C2 를 무작위로 생성하고 생성된 두개의 공개 키가 암호화되어 서버로 전송
    • 서버는 데이터를 수신한 후 공개 키 C1C2 를 자신의 개인 키로 해독하고 랜덤으로 두개의 공개 키 S1S2 를 생성한 후 클라이언트 공개 키로 암호화하여 이를 클라이언트로 전송
    • 암호화된 데이터를 수신한 클라이언트는 자체 개인 키로 해독

    이후 데이터 전송은 다음과 같이 서명됩니다.

    • 클라이언트-서버 데이터: 수식 1에서 사용된 데이터를 활용하여 서명
    • 서버-클라이언트 데이터: 수식 2에서 사용된 데이터를 활용하여 서명 (위험 노드에 의한 데이터 수정 및 제거가 필요하지 않음)
  • IPFS 프로토콜 IPNS 계층 분석 - Overview

    IPFS Name Service

    IPFS에서 MerkleDAG 계층은 콘텐츠의 해시 값을 기반으로 데이터 및 콘텐츠를 정확하게 찾을 수 있으며 중복 데이터를 효과적으로 제거 할 수 있습니다. 각 블록의 링크는 다음 콘텐츠의 해시 값을 유지하기 때문에 콘텐츠가 수정되지 않는 한 링크가 유효하며 데이터 유효성을 확인할 필요가 없습니다. 그러나 아래의 그림과 같이 디렉토리 아래의 파일이 수정되면 전체 경로의 해시 값이 수정되어 트리의 루트가 변경됩니다.

    Content Update 에 따른 root tree 변화

    그림에서 데이터 블록 4를 데이터 블록 5로 수정했습니다. 즉, 오른쪽의 해시 트리가 수정이 로컬에서 발생하며 전체 네트워크에 동기화하는 비용은 매우 높기 때문에 변경을 할 때마다 해시 정보를 동기화해야 합니다. 따라서 IPFS의 Naming 계층에서 파일 시스템 자체 확인 (Self-verifying File System) 개념이 도입되고 로컬 NodeID가 특정 콘텐츠 해시 값에 바인딩되며 네트워크의 다른 사용자가 NodeId에 액세스하여 바인딩 된 콘텐츠에 액세스 할 수 있습니다. 이를 통해 중앙 집중화 된 웹 사이트가 가능합니다.

    아래에서는 특정 시나리오에서 이 계층 프로토콜의 적용을 설명하기 위해 분산 된 웹 사이트의 구성을 예로 들어 설명합니다. 분산 된 웹 사이트를 만들고 우리 웹 사이트의 각 콘텐츠 수정이 IPFS 네트워크의 다른 노드에 투명하다는 가정하에 사용자는 콘텐츠 해시 값을 업데이트하지 않고 최신 콘텐츠에 액세스 할 수 있습니다.

    위의 그림에서 우리는 먼저 html 파일과 그림으로 구성된 웹 사이트를 만듭니다.

    위의 첫 번째 단계에서는 전체 웹 사이트 디렉토리를 IPFS 네트워크에 업로드합니다. 두 번째 단계에서는 루트 디렉토리의 해시 값이 Naming 프로토콜을 통해 NodeId에 매핑합니다. IPFS 노드의 NodeId는 상대적으로 고정되어 있으며 이는 로컬에서 실행중인 IPFS 노드를 나타냅니다. 세 번째 단계는 업로드가 성공한 후 명령을 구문 분석하여 노드를 특정 내용에 매핑 할 수 있습니다. 그림 4에 주목해야 할 필요가 있는데, 이것은 NodeId의 해시 값입니다.

    위의 그림에서 두 가지 프로토콜을 통해 웹 사이트에 액세스합니다. 왼쪽은 ipfs/xxxx입니다. Merkle DAG 프로토콜에 따르면 웹 사이트 루트 디렉토리의 해시 값은 전체 네트워크에서 발견됩니다. 오른쪽에는 Naming 프로토콜을 통해 웹 사이트의 콘텐츠를 찾는 ipns/ 방법이 있습니다. 그림에서 볼 수 있듯이 두 가지 액세스 방법으로 얻은 결과는 완전히 일치합니다.

    웹 사이트의 내용과 구조를 다음과 같이 수정하려고 합니다. cat.jpg를 NBS (Next Blockchain System) 로고로 교체했습니다.

    웹 사이트의 내용은 IPFS 네트워크에 다시 게시됩니다. 그림에서 4는 NodeId 매핑을 구문 분석 할 때 얻은 최신 웹 사이트 루트 디렉토리의 해시 값이며 NodeId가 변경되지 않은 경우 최신 내용의 콘텐츠의 루트 디렉토리의 hash 값을 얻습니다.

    최신 웹 콘텐츠에 액세스 할 수 있는 브라우저를 통해 왼쪽과 같이 MerkleDAG 프로토콜을 통해 최신 콘텐츠의 해시 값에 액세스하고 최신 콘텐츠를 얻을 수 있으며, 오른쪽과 같이 Naming 프로토콜을 통해 NodeId를 사용하여 액세스하고, 최신 웹 사이트 콘텐츠를 동일하게 얻을 수 있습니다. (고양이 그림을 얻은 웹페이지의 주소와 비교하면 IPNS의 경우 동일 주소를 사용함을 알 수 있음)

    위의 예제를 통해 Naming 프로토콜을 통해 웹 사이트 콘텐츠를 유연하게 수정하고 최신 콘텐츠 해시를 브로드 캐스트하지 않고 분산 된 웹 사이트를 실현할 수 있음을 분명히 알 수 있습니다.

  • IPFS 프로토콜 교환 계층 분석 - Receive Blocks

    IPFS 데이터 교환 계층-Receive Blocks

    컨텐츠 공급자는 자체적으로 저장된 컨텐츠를 네트워크 계층으로 보냅니다. 데이터 수신 후 컨텐츠 수신단은 Engine 의 청구 시스템을 통해 노드와 송신 데이터 노드간의 데이터 상호 작용을 계산합니다. Statistics (통계) 를 검색한 다음 Engine 에 캐시된 WantList 정보를 조회합니다. 노드가 방금 수신한 데이터를 요청하는 다른 노드가 있는 경우 데이터를 peerRequestQueue 에 넣는 즉시 컨텐츠 공급자가 됩니다.

    이후 노드는 방문자에 대한 데이터 캐시를 제공하고 데이터에 다시 액세스하며 다른 노드의 데이터 방문자에 대한 스토리지 서비스가 될 수 있는 로컬 스토리지 공간에 데이터를 저장합니다.

    데이터 교환 계층의 첫번째 포스팅에서 데이터에 액세스하는 노드가 key 를 subscribe 한다고 하였는데 이러한 key 는 검색할 데이터에 해당하는 인덱스이기 때문에 데이터를 수신할 때 수신된 데이터를 최신 구독자에게 브로드캐스트 하여야 합니다. 위 그림의 4는 이와 같은 메시지를 publish 하는 것을 나타냅니다.

    위 작업들이 완료되면 노드는 Want Manager 대기열의 데이터를 확인하고 수신된 데이터가 다른 노드에 의해 액세스되는 경우 데이터는 5와 같은 형식으로 프로세스의 다른 노드에 제공됩니다. 데이터를 수신한 후 Want ManagerWant List 에 있는 노드에 대한 요청을 Want List 에서 삭제하여야 합니다. 노드가 원본 데이터 요청 개시자인 경우 반복적으로 여러 노드가 동일한 데이터를 보내지 않도록 하여야 합니다. 즉 다른 노드에 해당 데이터에 대한 전체 네트워크 조회를 수행하지 않도록 알리기 위하여 cancel 명령을 사용합니다. cancelGetBlock 과 유사하게 동작합니다.

    아래의 코드를 활용하면 이에대한 메커니즘을 구현할 수 있습니다.

    IPFS exchange interface (bitswap.go)

    검색 로직외에 데이터 교환 레이어의 Engine 은 노드와 다른 노드간 얼마나 많은 데이터가 교환되는지에 따라 인접 노드에 서비스를 계속 제공할지 여부를 결정하는 기능을 사용할 수 있습니다. 노드가 많은 양의 데이터를 수신하면 데이터는 드물게 악의적인 노드로 간주될 가능성이 있기 때문에 Frozon 계정에 추가됩니다. 이는 이전 포스팅의 peerRequestQueue 에 대한 Map 구조에 대한 내용을 생각하면 되겠습니다. 데이터 선발의 논리적인 공식은 다음 수식에서 확인할 수 있습니다.

    첫번째 수식에서 r 은 전송된 데이터와 수신된 데이터 간의 비례 관계를 나타냅니다.

    두번째 수식에서 P 는 다른 노드로 데이터를 계속 보낼 확률을 나타냅니다.

    다른 노드가 많은 양의 데이터를 보내지만 상대방으로 부터 받은 데이터가 매우 작으면 r 값이 매우 커지고 확률 P 는 작아집니다. 즉, 상대방에게 더 많은 데이터를 제공하고 데이터를 작게 받는다면 상대방이 공격 노드(악의적 노드) 일 수 있다고 생각할 수 있습니다. 반대로 더 높은 확률로 더 많은 서비스를 제공하는 노드에게는 그만큼의 서비스를 상대방에게 제공하여야 합니다. 이러한 내용은 ‘Filecoin’ 에 잘 설명이 되어 있습니다.

    지금까지 데이터 교환 계층에 대하여 GetBlocks 라고 하는 대표 인터페이스에 대한 전체 데이터 동작에 대하여 알아보았습니다. 데이터 교환 계층은 현재에도 매우 많은 문제를 해결하기 위한 시도가 진행되고 있으며 매우 어려운 부분입니다. 분산 스토리지 시스템에서 데이터가 유효한지, 스토리지 장치의 위치가 변경되었는지 같은 내용을 다른 노드에 효과적으로 알리기 위한 IPFS의 주요 과제도 산적해 있습니다.

  • IPFS 프로토콜 교환 계층 분석 - Provide Blocks

    IPFS 데이터 교환 계층-Provide Blocks

    GetBlocks 인터페이스가 동작하면서 Keys 요청을 받은 후 각 모듈에 KEYS에 대한 요청을 캐시하고 라우팅 계층을 통해 해당 데이터를 찾기 시작합니다. KEYS를 WantManager에 등록함과 동시에 WantManager는 이미 설정된 링크의 노드 정보를 Map에 저장하고 GetBlocks 요청이 수신되면 WantManager는 요청을 설정된 노드로 보냅니다. 다음 그림은 노드 정보의 Map 데이터 구조 입니다.

    노드의 Map 데이터 구조

    각 노드의 PeerID가 Message Queue에 해당하는 것을 확인할 수 있습니다. Message Queue는 Want List와 Out Queue의 두 부분으로 구성됩니다. Out Queue는 또 다른 Want List와 Block List가 있으며 Want List는 해당 키에 대한 요청을 저장하고 Block List는 Key에 해당하는 데이터를 저장합니다.

    검색요청 메시지 대기열 구조

    위 그림에서 각 메시지 대기열의 자체 run loop 를 활용하여 신규 검색 명령어가 오면 run loopmsgSender 객체를 통해 검색명령을 실행합니다. 이미 Peers MAP을 사용하고 있기 때문에 알고 있는 수신자 peerID를 Message sender 객체에 전달하여 네트워크 레이어를 통해 링크를 설정하고 검색명령을 수신자에게 전달할 수 있습니다.

    이러한 내용은 노드와 링크를 설정한 노드의 검색명령을 수신하는 로직에 대한 내용입니다. 각 캐시는 명령어를 검색하는 방법과 각 캐시 자체의 run loop 가 데이터 쿼리 명령을 단계적으로 실행하는 방법이 저장됩니다.

    다음은 이러한 쿼리 명령을 받은 후 쿼리된 노드가 어떻게 반응하는지 살펴보겠습니다.

    프로토콜 각 계층에 대한 키 처리 기능

    Want Manager 가 다른 노드 정보를 관리하지 않는 경우 GetBlocks 는 쿼리 개체의 KEY 배열의 첫번째 KEY에서 findkeys() 를 호출할 수 있습니다. 위 그림에서 링크 요청을 수신한 수 다른 노드의 동작을 추가하는 것을 볼 수 있습니다. 먼저 다은 노드가 해당 노드와 데이터 링크를 설정하고 IPFS의 프로토콜 계층은 다른 노드 정보를 Want Manager 의 다른 노드 목록에 추가하여 관리하게 됩니다. 위 그림은 프로토콜의 각 계층에 대한 키 처리를 보여줍니다.

    쿼리 명령을 받은 후 쿼리된 노드의 동작

    다른 노드 정보를 얻은 후 Send Message 요청을 시작하는 Run loop 가 존재하고 있음을 알게되며 해당 노드는 데이터를 찾는데 필요한 KEY 값을 사용 가능한 다른 모든 노드로 보냅니다. 데이터 쿼리 요청을 수신한 다른 노드는 네트워크 계층을 통해 데이터를 수락하고 데이터 교환 계층이 사용하는 BitSwapMessage 형식으로 수락한 데이터를 결합하고 이를 PeerRequestQueue 엔진 모듈의 큐에 배치합니다.

    PeerRequestEngine 데이터 구조

    위 그림은 Engine.peerRequestQueue 의 데이터 구조로 특정 데이터의 목록을 유지하는 것을 보여줍니다. TaskMap 은 요청 작업을 관리하는데 사용되며 허용된 각 데이터는 하나의 작업으로 캡슐화됩니다. 요청을 보내는 피어 정보를 저장하기 위한 두가지 맵도 존재합니다. 하나는 partners Map 이고 다른 하나는 frozon partners Map (고정 파트너 맵) 입니다. IPFS 데이터 교환 프로토콜에서 Engine 은 노드 및 기타 내용을 관리합니다. 악의적인 공격을 막기위한 노드의 데이터 교환노드가 데이터만 수집하고 데이터를 제공하지 않으면 이 노드는 다른 노드에 의해 고정된 목록으로 추가될 수 있습니다.

    작업 여부를 지속적으로 확인하고 처리하는 동작 구조

    데이터 요청 큐에는 task 가 있는지 여부를 지속적으로 확인하고 큐 헤더의 순서대로 pop 하고 요청한 task 를 가지고 온 다음 task 에 저장된 데이터를 로컬 데이터 저장소에 조회하여 저장하는 run loop 가 있습니다. 데이터 요청 키가 검색되고 키에 해당하는 특정 데이터 블록을 찾고 데이터를 가지고 오면 Send ManagersendBlock 인터페이스가 호출되어 데이터를 네트워크로 전송합니다.

  • IPFS 프로토콜 교환 계층 분석 - GetBlocks

    IPFS 데이터 교환 계층-GetBlocks

    데이터 교환 계층이 상위 프로토콜에 대해 제공해야 하는 기본 기능을 알아보고자 합니다. 우선 IPFS의 교환 계층 인터페이스 설계는 다음 위치에서 확인할 수 있습니다.

    IPFS exchange interface (interface.go)

    // Package exchange defines the IPFS exchange interface
    package exchange
    
    import (
    	"context"
    	"io"
    
    	blocks "github.com/ipfs/go-block-format"
    	cid "github.com/ipfs/go-cid"
    )
    
    // Interface defines the functionality of the IPFS block exchange protocol.
    type Interface interface { // type Exchanger interface
    	Fetcher
    
    	// TODO Should callers be concerned with whether the block was made
    	// available on the network?
    	HasBlock(blocks.Block) error
    
    	IsOnline() bool
    
    	io.Closer
    }
    
    // Fetcher is an object that can be used to retrieve blocks
    type Fetcher interface {
    	// GetBlock returns the block associated with a given key.
    	GetBlock(context.Context, cid.Cid) (blocks.Block, error)
    	GetBlocks(context.Context, []cid.Cid) (<-chan blocks.Block, error)
    }
    
    // SessionExchange is an exchange.Interface which supports
    // sessions.
    type SessionExchange interface {
    	Interface
    	NewSession(context.Context) Fetcher
    }
    

    데이터 교환 계층이 상위 계층 프로토콜을 위해 제공해야하는 기본 기능을 결정하는 위 코드는 IPFS의 스위치 계층 인터페이스 설계이며 데이터를 검색하고 데이터를 교환하는 기능을 제공하기 위해 특정 스위치 계층 구현자를 필요로 합니다.

    • GetBlocks: 지정된 키 세트에 해당하는 데이터 인터페이스를 가지고 옵니다.

    GetBlocks interface 단계

    위의 그림은 GetBlocks() 인터페이스의 첫 번째 단계로, 키 집합에 해당하는 데이터 요청을 데이터 교환 계층의 여러 구성 요소로 전송하여 각 모듈에 새 작업이 도착했음을 알립니다.

    먼저 모든 키를 Pub/Sub 모듈에 건네고 모든 키를 알림 대기열(Notification Queue)이라는 구독 큐에 추가합니다. 이 구독 큐는 파이프 그룹이며 파이프 그룹의 길이는 키 수에 의해 결정됩니다. 이 파이프 라인 큐 관리는 순환루틴입니다. 가입 키에 대응하는 데이터 블록이 도착할 때마다, want list로 부터 삭제 요청이 생성되고, 위 그림의 절차 4에 도시 된 바와 같이, 획득 된 데이터에 대응하는 키가 want list로 부터 삭제된다.

    두 번째 단계에서는 그룹 키가 요청 데이터 항목에 패키지화되어 Incoming Queue에 추가됩니다. 이는 고정 크기가 10인 요청 캐시이며 데이터를 가져 오기위한 요청과 데이터 요청 취소 요청을 저장하는 데 사용됩니다. 이 대기열의 사용은 계속해서 다음 섹션에서 설명합니다. 그의 역할은 데이터에 대한 캐시 요청으로 작동하는 것입니다.

    세 번째 단계에서이 키 집합의 0 번째 요소는 findkeys Queue의 요소로 삽입되며 큐의 길이는 32 고정 크기입니다. 이 큐의 상세한 사용은 다음에 상세하게 설명합니다.

    다섯 번째 단계는 Incoming Queue에서 작업을 제거하고 작업 유형을 결정하는 것입니다. 데이터의 ID에 따라 Key-Value 맵이 있습니다. 맵의 각 항목은 메시지 대기열입니다. 작업 유형이 증가하면, 작업 유형으로 전달 된 키를 대기열에 추가하고, 삭제 된 경우 키에 따라 메시지 대기열에서 데이터를 삭제하는 방법은 다음과 같습니다. 이 단계에서 사용 된 실행 루프는 두 가지 유형의 원하는 목록에서 작동해야한다는 점을 지적해야합니다. 하나는 normal want list이고 다른 하나는 broadcast want list입니다. broadcast want list는 질의 노드없이 키 데이터를 저장합니다. normal want list는 이니시에이터가 고정 키 배열을 찾기 위해 지정한 질의 노드 객체를 찾습니다.

    Findkeys Queue 루틴

    normal want list에는 Findkeys Queue에 가입하기 위해 목록에서 임의로 키를 선택하는 동시 루틴 타이밍이 있습니다. Findkeys Queue에는 이 큐를 관리하기 위한 순환이 있습니다. 이 큐는 요소 중 하나를 사용하고 데이터 교환 프로토콜에 액세스합니다. 네트워크 인터페이스는, 어떤 노드가 요소에 대한 데이터 (요소의 데이터에 해당하는 키 값)를 제공 할 수 있는지 쿼리하고, 네트워크 인터페이스는 해당 라우팅 계층을 호출하여 해당 노드를 찾습니다.

    네트워크 인터페이스는 키에 대한 데이터 공급자 목록을 반환합니다. 이 목록에 저장된 요소는 Peer Info입니다. 이 정보는 네트워크 계층 (네트워크 레이어 - 라우팅 레이어 - 파일교환 레이어 순서)에 사용됩니다. 데이터 연결에 대한 기본 정보를 설정합니다. 데이터 교환 층은 데이터 교환 층과 네트워크 층 사이의 네트워크 링크 정보를 관리하는 호스트 객체를 갖는다. 이 개체를 통해 데이터 교환 계층은 반환 된 모든 네트워크 계층 노드와 직접 연결됩니다.

    요약하면이 섹션에서는 주로 GetBlocks() 인터페이스 명령을 받아들이는 노드의 처리 흐름을 분석합니다.이 명령을받은 후에 노드는 명령을 캐시하고 네트워크 전체의 데이터 쿼리를 수행하도록 각 큐에 알리는 것에 중점을 둡니다. 관련 노드는 직접 네트워크 레이어 링크를 설정합니다. 다음 섹션에서는 데이터 수집 프로세스의 전체 과정이 데이터 공급자 또는 데이터 중계자의 관점에서 어떻게 구현되는지 분석합니다.