Phần mở rộng tin nhắn một phần của Gossipsub và sự lan truyền ở cấp độ tế bào
hoặc làm thế nào để làm cho sự lan truyền blob nhanh hơn và hiệu quả hơn
Cảm ơn Raúl Kripalani, Alex Stokes và Csaba Kiraly đã phản hồi về bản thảo đầu tiên.
Tổng quan
Tiện ích mở rộng tin nhắn cục bộ mới của Gossipsub cho phép các nút nâng cấp lên mức phân phối cấp độ tế bào mà không cần Hard fork. Tăng tính hữu ích của dữ liệu từ mempool cục bộ (getBlobs).
Có một bản thảo PR nêu rõ cách Consensus Clients sử dụng Tiện ích mở rộng tin nhắn một phần tại đây: Thêm tính năng phát tán tế bào thông qua Thông số kỹ thuật tin nhắn một phần của MarcoPolo · Yêu cầu kéo #4558 · ethereum/consensus-specs · GitHub .
Giới thiệu
Fusaka giới thiệu PeerDAS với Đề xuất cải tiến Ethereum (EIP)-7594 . Như đã giải thích trong Đề xuất cải tiến Ethereum (EIP), các blob được mã hóa xóa được phân phối dưới dạng các cột ô. Các cột được định kiểu là DataColumnSidecar . Các cột này được lan truyền đến mạng thông qua gossipsub. Nếu một nút đã có tất cả các blob được tham chiếu trong một cột từ bộ nhớ cục bộ của nó, nó có thể tự mình lấy DataColumnSidecar mà không cần chờ Gossipsub lan truyền. Sau đó, nó cũng lan truyền cột để hỗ trợ việc lan truyền nhanh chóng. Thông điệp IDONTWANT của Gossipsub có tác dụng ngăn chặn các lần đẩy này từ một nút ngang hàng đã có thông điệp IDONTWANT.
Trong trường hợp tất cả các blob được tham chiếu của một Block đều xuất hiện trong mempool của phần lớn các nút, thì việc đạt được yêu cầu lưu giữ sẽ nhanh chóng. Dữ liệu đã mang tính cục bộ. Tuy nhiên, nếu chỉ thiếu một blob, các nút phải đợi toàn bộ các cột được truyền qua mạng trước khi đạt được yêu cầu lưu giữ.
Lý tưởng nhất là chúng ta chỉ phân phối các ô bị thiếu cho một hàng nhất định. Cho phép một nút sử dụng dữ liệu cục bộ mà nó đã có. Đó chính là chức năng của Tiện ích mở rộng Tin nhắn Một phần của Gossipsub.
Phần mở rộng tin nhắn một phần cho phép các nút gửi, yêu cầu và quảng bá các ô một cách ngắn gọn. Đây là một thay đổi trong lớp mạng không yêu cầu thay đổi Consensus , có thể được triển khai theo cách tương thích ngược và không yêu cầu Hard fork.
Phần mở rộng tin nhắn một phần, tổng quan
Bản dự thảo đầy đủ có thể được tìm thấy tại libp2p/specs .
Tin nhắn một phần hoạt động tương tự như tin nhắn Gossipsub thông thường. Điểm khác biệt chính là thay vì được tham chiếu bằng Hash, chúng được tham chiếu bằng ID nhóm. ID nhóm được ứng dụng định nghĩa và có thể được suy ra mà không cần toàn bộ tin nhắn. Với ID nhóm và bitmap, một Node có thể chỉ định hiệu quả những phần nào còn thiếu và những phần nào có thể cung cấp.
Đối với PeerDAS, ID Nhóm là gốc Block . Nó là duy nhất cho mỗi chủ đề. Một cột đầy đủ là một thông điệp hoàn chỉnh, và ô là phần nhỏ nhất của thông điệp. Một ô được xác định duy nhất và ngắn gọn theo chủ đề mạng con (chỉ mục cột), ID Nhóm (gốc Block ) và vị trí trong bitmap. Một nút có thể bắt đầu quảng bá và yêu cầu các ô ngay khi nhận được Block. Đây là thời điểm sớm nhất có thể vì Block khai báo các blob được bao gồm.
Việc truyền bá ở cấp độ tế bào với các tin nhắn gossipsub thông thường rất phức tạp. Mỗi tế bào phải được tham chiếu bằng ID tin nhắn đầy đủ (20 byte) của nó, và các nút không thể yêu cầu các tế bào bị thiếu trước; trước tiên chúng phải biết cách một tế bào ánh xạ đến ID tin nhắn tương ứng của nó. Ngược lại, với các tin nhắn một phần, các nút tham chiếu mỗi tế bào bằng một Bit trong bitmap, và có thể trao đổi thông tin về những gì chúng có thể cung cấp và những gì chúng cần bằng các IHAVE
một phần và IWANT
một phần.
Các tin nhắn riêng lẻ có thể được gửi nhanh đến một đối tác mà không cần chờ đối tác yêu cầu các phần tin nhắn hoặc có thể được cung cấp theo yêu cầu.
Tin nhắn một phần của Gossipsub yêu cầu sự hợp tác của ứng dụng, vì ứng dụng biết cách soạn thảo và phân tách tin nhắn. Ứng dụng chịu trách nhiệm: - Mã hóa các phần có sẵn và bị thiếu (ví dụ: ảnh bitmap). - Giải mã yêu cầu các phần và phản hồi bằng tin nhắn một phần đã mã hóa. - Xác thực tin nhắn một phần đã mã hóa. - Hợp nhất tin nhắn một phần đã mã hóa.
Dòng chảy ví dụ giả định
Để giúp hình dung trực giác về cách thức hoạt động của các tin nhắn cục bộ trong thực tế, hãy xem xét hai ví dụ sau. Ví dụ đầu tiên sử dụng cơ chế "engage-push" để giảm độ trễ, ví dụ thứ hai chờ một yêu cầu ngang hàng, điều này có thể giảm số lượng bản sao nhưng độ trễ sẽ giảm (trong ví dụ này là 1/2 RTT).
Đối với cả hai ví dụ, hãy giả sử:
- Peer P là người đề xuất một Block. Nó biết về tất cả các blob trong một Block.
- Người đồng cấp A và B là người xác thực.
- Blob đầu tiên trong Block không được chia sẻ công khai với A và B trước đó, do đó cả hai đều thiếu blob duy nhất này khỏi mempool cục bộ của họ.
- P được kết nối với A được kết nối với B. P <=> A <=> B
Đẩy hăng hái
┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐│ P │ │ A │ │ B │└──────────────────┘ └──────────────────┘ └──────────────────┘┌────────────────┐ │ ││Proposes Block B│ │ │└───────┬────────┘ │ ││ ┌──────────────┐ │ │├───│Forwards block│──▶│ ┌──────────────┐ ││ └──────────────┘ ├───│Forwards block│──▶││ ┌──────────────┐ │ └──────────────┘ ││ │ Eager push │ │ ┌──────────────┐ │├───│cell at idx=0 │──▶│ │ Eager push │ ││ └──────────────┘ ├──│cell at idx=0 │──▶ ││ │ └──────────────┘ ││ │ ││ │ ││ │ │▼ ▼ ▼
Yêu cầu/Phản hồi
┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐│ P │ │ A │ │ B │└──────────────────┘ └──────────────────┘ └──────────────────┘│ │ │┌───────┴────────┐ │ ││Proposes Block B│ │ │└───────┬────────┘ │ ││ ┌──────────────┐ │ │├───│Forwards block│──▶│ ┌──────────────┐ ││ └──────────────┘ ├───│Forwards block│──▶││ ┌──────────────┐ │ └──────────────┘ ││ │ IWANT │ │ ┌──────────────┐ ││◀──│ idx=0 │───│ │ IWANT │ ││ └──────────────┘ │◀──│ idx=0 │───││ ┌──────────────┐ │ └──────────────┘ ││ │ Respond with │ │ ┌──────────────┐ │├───│ cell@idx=0 │──▶│ │ Respond with │ ││ └──────────────┘ ├───│ cell@idx=0 │──▶││ │ └──────────────┘ │▼ ▼ ▼
Lưu ý rằng các peer yêu cầu dữ liệu trước khi biết peer kia có gì. Yêu cầu này là một phần của bitmap IWANT của peer, được gửi cùng với bitmap IHAVE của nó. Điều này có nghĩa là dữ liệu có thể được nhận trong một RTT duy nhất khi peer kia có thể cung cấp dữ liệu. Ngược lại, luồng thông báo, yêu cầu, phản hồi yêu cầu 1,5 RTT.
Chiến lược xuất bản
Đẩy nhanh hơn yêu cầu/phản hồi, nhưng có nguy cơ gửi thông tin trùng lặp.
Do đó, chiến lược xuất bản phải là:
Đẩy mạnh khi có sự tin tưởng rằng đây sẽ là lần đầu tiên gửi đi thông điệp một phần này.
Trong trường hợp có các blob riêng tư, một nút sẽ chuyển tiếp lệnh đẩy háo hức khi nhận được một blob riêng tư.
Trong trường hợp có các nhóm mempool được phân mảnh, một nút có thể chủ động đẩy các ô mà nó biết rằng một nút ngang hàng sẽ không làm như vậy do chiến lược phân mảnh của nó.
Một số thông tin trùng lặp được mong đợi và yêu cầu như một hình thức phục hồi. Lượng thông tin trùng lặp có thể được điều chỉnh bằng cách điều chỉnh xác suất đẩy háo hức và xác suất yêu cầu từ một đối tác ngang hàng.
Tuy nhiên, ngay cả một chiến lược đơn giản, ngây thơ cũng có thể vượt trội hơn đáng kể so với phương pháp cột đầy đủ hiện tại của chúng ta bằng cách tận dụng dữ liệu cục bộ từ mempool. Việc sao chép một phần thông điệp sẽ dẫn đến việc tạo ra các ô trùng lặp thay vì các cột đầy đủ trùng lặp.
Bằng chứng khái niệm DevNet
Có một bản triển khai Go đang được hoàn thiện cho Phần mở rộng Tin nhắn Một phần . Ngoài ra còn có một bản vá cho Prysm sử dụng tin nhắn một phần.
Để chứng minh khái niệm, chúng tôi đã tạo một DevNet Kurtosis sử dụng các máy khách Prysm đã vá được kết nối với các máy khách geth đã vá (để trả về các blob cục bộ trong lệnh gọi getBlobs). Một số nút sẽ xây dựng các khối với các blob "riêng tư". Khi điều này xảy ra, các nút khác sẽ chỉ yêu cầu các ô "riêng tư" bị thiếu và điền phần còn lại của cột bằng các blob từ mempool cục bộ của chúng.
Để có được cái nhìn tổng quan về mức tiết kiệm băng thông, chúng tôi cũng đã tạo một mạng lưới kurtosis nhỏ hơn chỉ gồm hai nút "siêu", các nút nhận và gửi tất cả các cột. Một trong các nút đề xuất các blob riêng tư. Điều này có nghĩa là getBlobs sẽ không trả về một cột đầy đủ cho nút kia khi nút nói trên đề xuất.
Chúng tôi đã đo lường dữ liệu được gửi cho các tin nhắn DataColumnSidecar
khi không có và có Tin nhắn Một phần. Kết quả cho thấy khi sử dụng Tin nhắn Một phần, các nút gửi ít dữ liệu hơn 10 lần. Có hai lý do cho điều này:
- Việc triển khai Tin nhắn Một phần (Partial Messages) hiện tại của Prysm không bao giờ đẩy nhanh. Các nút chờ xem yêu cầu trước khi phản hồi bằng dữ liệu.
- Chỉ những phần được yêu cầu mới được gửi. Nếu một cột có một blob riêng tư duy nhất, chúng tôi chỉ gửi blob đó.
Trong môi trường độ trễ thấp này (chạy cục bộ với độ nhọn), IDONTWANT không hiệu quả. Do đó, chúng tôi thấy lợi ích lớn khi không cần đẩy dữ liệu một cách vội vã.
Tuy nhiên, trong trường hợp có các blob riêng tư, IDONTWANT sẽ không áp dụng được, do đó lợi ích về hiệu suất ở đây vẫn đại diện cho môi trường thực tế hơn với độ trễ cao hơn.
Đồ thị:
Đây là một thử nghiệm chỉ với hai đối tác, nhưng mỗi tương tác theo cặp trong một lưới với nhiều đối tác hơn sẽ hoạt động giống nhau. Đây là băng thông được sử dụng để phân phối các cột dữ liệu.
Phân mảnh Mempool
Các hướng phát triển trong tương lai của phân mảnh mempool sẽ chỉ làm tăng khả năng các nút bị thiếu một số ô và do đó cần một số hình thức phân tán ở cấp độ ô.
Phát tán theo kiểu “hàng”
Lưu ý rằng nếu một nút bị thiếu một ô tại một chỉ mục nào đó trong một cột, thì rất có thể nó cũng bị thiếu các ô ở cùng vị trí đó trong tất cả các cột khác. Một cải tiến trong tương lai có thể là cho phép các nút thông báo các hàng đầy đủ cho các nút ngang hàng trong lưới của nó. Lợi ích là một nút sẽ lấp đầy tất cả các ô bị thiếu của một hàng cùng một lúc. Nhược điểm là nguy cơ xuất hiện các thông báo trùng lặp lớn hơn.
Các bước tiếp theo
- Chỉ định api getBlobs V3 hỗ trợ trả về các blob một phần.
- Triển khai Phần mở rộng tin nhắn một phần trong Rust libp2p. (đang tiến hành)
- Chỉ định mã hóa tin nhắn một phần của DataColumnSidecars. Đang tiến hành
- Tích hợp vào máy khách CL.
- Triển khai trên mạng thử nghiệm
- Triển khai trên mạng chính
- số lượng blob quy mô