Private Channels chưa được kiểm toán bảo mật và không được khuyến nghị sử dụng trong môi trường production với tài sản thực mà không có đánh giá bảo mật kỹ lưỡng.
Bạn đang triển khai một instance? Hãy xem hướng dẫn cho Operators. Bạn đang tích hợp với một instance có sẵn? Hãy xem Quickstart. Trang này là tài liệu tham khảo kiến trúc dành cho cả hai đối tượng.
Kiến trúc
Private Channels được cấu thành từ bốn thành phần: hai chương trình Solana on-chain (Escrow và Withdraw) và hai dịch vụ off-chain (Gateway và Auth Service). Cùng nhau, chúng tạo thành một giao thức state channel, trong đó tài sản tồn tại trên Mainnet nhưng các giao dịch chuyển tiền được thanh toán off-chain.
Chương trình Escrow
Chương trình Escrow là một chương trình Solana on-chain lưu giữ các token SPL đã được nạp vào. Đây là điểm neo tin cậy của hệ thống: toàn bộ tài sản cuối cùng đều nằm trong escrow cho đến khi operator cung cấp bằng chứng loại trừ Sparse Merkle Tree hợp lệ để giải phóng chúng.
- Program ID:
9tgHa1DcnaSSUtmMsst8ovKTe1Gfxzezn27KnH9xXYeU - ID này được biên dịch vào nhị phân của chương trình thông qua
declare_id!(). Các dịch vụ off-chain đọc cùng ID này tại thời điểm biên dịch từ crate client được tạo ra, không phải từ biến môi trường. - Quản lý các PDA
Instance,AllowedMintvàOperator - Các lệnh:
CreateInstance,AllowMint,BlockMint,AddOperator,RemoveOperator,SetNewAdmin,Deposit,ReleaseFunds,ResetSmtRoot
Chương trình Withdraw
Chương trình Withdraw chạy trên mạng private channel, không phải trên Solana Mainnet.
Người dùng gọi WithdrawFunds để đốt số dư token phía channel của họ. Việc đốt này
không tự động giải phóng tài sản; nó báo hiệu cho operator rằng một
yêu cầu rút tiền đang chờ xử lý. Operator sau đó gọi ReleaseFunds trên Chương trình Escrow
với bằng chứng SMT hợp lệ để hoàn tất thanh toán.
- Program ID:
J231K9UEpS4y4KAPwGc4gsMNCjKFRMYcQBcjVW7vBhVi - ID này được biên dịch vào nhị phân của chương trình. Các dịch vụ off-chain đọc cùng ID này tại thời điểm biên dịch từ crate client được tạo ra, không phải từ biến môi trường.
Gateway
Gateway là một proxy tương thích Solana JSON-RPC, định tuyến các yêu cầu từ client đến
nút ghi của mạng channel (để gửi giao dịch) và nút đọc (để
truy vấn). Nó được cấu hình qua các biến môi trường: GATEWAY_PORT,
GATEWAY_WRITE_URL, GATEWAY_READ_URL.
Các endpoint kiểm tra sức khỏe (không yêu cầu xác thực):
GET /health- kiểm tra liveness; trả về200 {"status":"ok"}GET /ready- kiểm tra readiness sâu, thăm dò cả nút ghi + nút đọc; trả về200 {"status":"ready"}hoặc503 {"status":"degraded"}
Định tuyến và Kiểm soát Truy cập Phương thức RPC
Gateway định tuyến sendTransaction đến nút ghi và tất cả các phương thức khác đến
nút đọc. Các yêu cầu lớn hơn 64 KB sẽ bị từ chối với HTTP 413. Khi
xác thực được bật, quyền truy cập phương thức được kiểm soát bởi vai trò JWT. Xem
Authentication & Roles để biết
ma trận phương thức đầy đủ.
Auth Service
Auth Service là một thành phần tùy chọn phát hành JWT HS256 (hết hạn sau 24 giờ)
cho kiểm soát truy cập gateway. Nó được kích hoạt khi biến môi trường JWT_SECRET
được đặt. Nếu không có nó, gateway chấp nhận tất cả các kết nối.
Các claim JWT: sub (UUID người dùng), role ("user" hoặc "operator"), iss
("private-channel-auth"), aud ("private-channel-gateway"), exp (Unix
timestamp). iss và aud được xác thực bởi cấu hình JWT của gateway,
không được deserialize vào struct claim của ứng dụng: chỉ có sub, role và
exp là khả dụng cho code ở tầng ứng dụng.
Các vai trò:
user- truy cập bị giới hạn trong các ví đã xác minh của chính họ; không thể gọigetBlock,getTransactionhoặcsimulateTransactionoperator- bỏ qua tất cả kiểm tra quyền sở hữu; toàn quyền truy cập phương thức RPC; phải được cấp phép trong cơ sở dữ liệu (không có cơ chế tự nâng cấp quyền)
Streamer
Streamer là một máy chủ WebSocket đẩy các cập nhật trạng thái channel đến các client đang kết nối theo thời gian thực, loại bỏ nhu cầu polling RPC. Nó thăm dò PostgreSQL để lấy các thay đổi trạng thái. Đây là một phần của stack Docker Compose cơ sở, không phải stack devnet mà hướng dẫn này triển khai; xem tài liệu tham khảo Cấu hình.
- Cổng:
8902, có thể cấu hình quaSTREAMER_PORT - Kết nối:
ws://localhost:8902 - Endpoint kiểm tra sức khỏe:
GET /health- trả về503nếu bất kỳ vòng lặp poll nội bộ nào bị đình trệ quá 30 giây
Schema sự kiện WebSocket chưa được tài liệu hóa công khai. Hãy tham khảo
core/src/bin/streamer.rs
để biết chi tiết triển khai cho đến khi có tài liệu chính thức.
Pipeline Giao dịch
Transaction -> [1:Dedup] -> [2:SigVerify] -> [3:Sequencer] -> [4:Executor] -> [5:Settler] -> Database
Các giao dịch được gửi đến Gateway sẽ đi qua một pipeline năm giai đoạn trước khi trạng thái của chúng được cam kết:
- Dedup - lọc các giao dịch trùng lặp trước khi chúng vào pipeline
- SigVerify - xác thực chữ ký giao dịch đối chiếu với khóa công khai của người ký
- Sequencer - sắp xếp các giao dịch hợp lệ theo thứ tự xác định để thiết lập lịch sử chính tắc
- Executor - thực thi các giao dịch đối với lớp tài khoản của channel (BOB Cache + AccountsDB), cập nhật số dư off-chain
- Settler - cam kết kết quả giao dịch tích lũy vào PostgreSQL và
cập nhật cache Redis; tạo blockhash mới cho chu kỳ block tiếp theo.
Việc thanh toán trên Mainnet (gọi
ReleaseFunds) được xử lý riêng bởi dịch vụoperator-private-channel
Tính năng Nổi bật
Quyền riêng tư
Các giao dịch chuyển tiền giữa các thành viên channel không được ghi lại trên Solana Mainnet. Chỉ có các lệnh nạp tiền (vào channel) và rút tiền cuối cùng (rời channel) mới xuất hiện on-chain. Danh tính đối tác và số tiền chuyển không hiển thị với người quan sát bên ngoài trong quá trình vận hành channel.
Hiệu năng
Pipeline off-chain loại bỏ thời gian block của Solana khỏi đường dẫn quan trọng. Các giao dịch chuyển tiền được xác nhận khi sequencer xử lý chúng, không phải khi một block Solana được xác nhận. Điều này cho phép tính chung cuộc dưới một giây và thông lượng vượt qua TPS native của Solana cho các giao dịch ở tầng ứng dụng.
Thanh toán
Mọi lệnh rút tiền đều được bảo vệ bởi một bằng chứng Sparse Merkle Tree on-chain. Root SMT
được lưu trữ trong Instance.withdrawal_transactions_root trên Chương trình Escrow.
Khi ReleaseFunds được gọi, chương trình trước tiên xác minh bằng chứng loại trừ cho
một nonce chưa được thấy đối chiếu với root on-chain hiện tại, sau đó xác minh một
bằng chứng bao gồm riêng biệt cho nonce đó đối chiếu với root mới do người gọi cung cấp. Chỉ sau khi
cả hai kiểm tra vượt qua thì root mới được lưu trữ, khiến việc chi tiêu gấp đôi là không thể ngay cả khi
khóa operator bị xâm phạm.
Mô hình Bảo mật
Khóa Admin - kiểm soát việc tạo instance (CreateInstance) và cấp phép operator
(AddOperator / RemoveOperator). Việc xâm phạm khóa admin
cho phép cấp phép operator tùy ý. SetNewAdmin chuyển quyền admin
không thể đảo ngược trong một bước duy nhất; hãy bảo vệ khóa admin tương ứng.
Khóa Operator - có thể gọi ReleaseFunds và ResetSmtRoot. Chúng không thể
giải phóng tài sản mà không có bằng chứng loại trừ SMT hợp lệ đối chiếu với root on-chain
hiện tại. Kiểm tra verify_smt_exclusion_proof on-chain là hàng rào bảo vệ cuối cùng
chống lại các lệnh rút tiền trái phép: một khóa operator bị xâm phạm đơn lẻ là
không đủ để rút cạn escrow.
SMT root - được lưu trữ on-chain trong Instance.withdrawal_transactions_root.
Được cập nhật nguyên tử với mỗi lần gọi ReleaseFunds. Vì mỗi bằng chứng phải
tham chiếu một nonce chưa được thấy, việc chi tiêu gấp đôi cùng một số dư channel là
không thể ngay cả khi khóa operator bị xâm phạm.
Luân chuyển Tree - Instance.current_tree_index theo dõi các epoch của tree. Khi
ResetSmtRoot được gọi, nó tăng chỉ số tree và vô hiệu hóa tất cả
các nonce từ epoch tree trước đó, tạo ra một khởi đầu sạch sẽ cho các chu kỳ thanh toán mới.
Bảo mật Khóa Vận hành
Các dịch vụ off-chain sử dụng bộ từ vựng ký riêng của chúng, không liên quan đến
các quyền admin/operator on-chain được mô tả trong Mô hình Bảo mật ở trên.
ADMIN_PRIVATE_KEY là bắt buộc đối với mọi dịch vụ operator và thanh toán
phí giao dịch; một OPERATOR_PRIVATE_KEY tùy chọn riêng biệt cung cấp
chữ ký Operator on-chain cho ReleaseFunds và ResetSmtRoot, và sẽ
dùng giá trị của ADMIN_PRIVATE_KEY khi không được đặt. Không bao giờ đặt khóa admin
instance ở cấp giao thức (dùng cho CreateInstance / AddOperator / SetNewAdmin)
vào bất kỳ biến nào hoặc để lộ nó lúc runtime; hãy giữ khóa đó lạnh và offline.
ReleaseFunds và ResetSmtRoot yêu cầu hai chữ ký on-chain: người trả phí
(từ ADMIN_PRIVATE_KEY) và quyền của Operator PDA (từ
OPERATOR_PRIVATE_KEY, hoặc ADMIN_PRIVATE_KEY nếu biến đó không được đặt). Hướng dẫn
triển khai này trong phần devnet walkthrough đặt keypair operator được tạo ra vào
ADMIN_PRIVATE_KEY và để OPERATOR_PRIVATE_KEY không được đặt, do đó cùng một keypair
đóng vai trò cả hai signer. Hãy áp dụng các biện pháp kiểm soát tương tự như khóa riêng ví nóng
cho bất kỳ khóa nào cuối cùng được đặt vào ADMIN_PRIVATE_KEY:
- Chỉ lưu trữ nó trong tệp
.envđược thêm vào gitignore, không bao giờ trong.env.devnethay bất kỳ config đã được commit nào - Đối với các triển khai production, hãy cân nhắc sử dụng secrets manager (AWS Secrets Manager, HashiCorp Vault) thay vì biến môi trường dạng plaintext
- keypair admin instance ở cấp giao thức (dùng để gọi
AddOperator/SetNewAdmin) nên được giữ lạnh; nó chỉ cần thiết trong quá trình thiết lập instance và cấp phép operator, không phải trong lúc runtime
SetNewAdmin chuyển quyền admin không thể đảo ngược trong một giao dịch duy nhất:
admin hiện tại không có đường phục hồi nếu không có sự hợp tác của admin mới. Không
gọi lệnh này mà không xác minh địa chỉ đích.
Các Bước Tiếp theo
Is this page helpful?