Mới hôm qua, một sự kiện gây sốc đã xảy ra: Linea, giải pháp Ethereum Layer 2 được phát triển bởi Consensys, công ty mẹ của Metamask, đã chủ động ngừng hoạt động. Lý do chính thức được đưa ra là để giảm thiểu tác động của sự cố hack Velocore. Sự cố này chắc chắn gợi nhớ đến một trường hợp trước đó khi chuỗi BSC (BNB Chain) cũng bị đóng cửa dưới sự phối hợp chính thức để giảm thiểu tổn thất hack. Những sự kiện này thường khiến mọi người đặt câu hỏi về các giá trị phi tập trung mà Web3 ủng hộ.
Lý do cốt lõi đằng sau các sự kiện nói trên nằm ở sự không hoàn hảo của cơ sở hạ tầng, đặc biệt là thiếu sự phân cấp. Nếu một blockchain được phân cấp đủ, nó sẽ không thể đóng cửa dễ dàng như vậy. Do cấu trúc độc đáo của Ethereum Layer 2, hầu hết các giải pháp Layer 2 đều dựa vào các bộ giải trình tự tập trung. Mặc dù diễn ngôn ngày càng tăng về các trình tự phi tập trung trong những năm gần đây, với mục đích và cấu trúc của Layer 2, chúng ta có thể giả định rằng các trình tự Layer 2 khó có thể đạt được mức độ phân cấp cao. Trên thực tế, chúng có thể sẽ ít phi tập trung hơn chuỗi BSC. Nếu đây là trường hợp, những gì có thể được thực hiện? Đối với Layer 2, rủi ro trực tiếp nhất của các trình tự không phi tập trung là thiếu kháng kiểm duyệt và sự sống động. Nếu chỉ có một vài thực thể xử lý giao dịch (trình tự chuỗi), họ có quyền lực tuyệt đối đối với việc có phục vụ bạn hay không: họ có thể từ chối giao dịch của bạn theo ý muốn, khiến bạn không có quyền truy đòi. Giải quyết vấn đề kháng kiểm duyệt trong Layer 2 rõ ràng là một chủ đề quan trọng. Trong vài năm qua, các giải pháp Ethereum Layer 2 khác nhau đã đề xuất các cách tiếp cận khác nhau để giải quyết vấn đề này. Ví dụ, Loopring, Degate và StarkEx đã giới thiệu các chức năng rút bắt buộc và thoát nở, trong khi Arbitrum và các Optimistic Rollups khác đã triển khai các tính năng Force Inclusion. Các cơ chế này có thể áp đặt kiểm tra đối với các trình tự để ngăn chặn việc từ chối tùy tiện các giao dịch của người dùng. Trong bài viết hôm nay, NIC Lin từ Hiệp hội Ethereum Đài Bắc chia sẻ kinh nghiệm trực tiếp của mình, thử nghiệm các tính năng giao dịch chống kiểm duyệt của bốn Bản tổng hợp chính và cung cấp phân tích chuyên sâu về cơ chế Bao gồm Lực lượng, tập trung vào quy trình làm việc và phương pháp hoạt động. Phân tích này đặc biệt có giá trị đối với cộng đồng Ethereum và những người nắm giữ tài sản lớn.
duyệt sự kháng cự trong các giao dịch là rất quan trọng đối với bất kỳ blockchain nào. Nếu một blockchain có thể tùy tiện kiểm duyệt và từ chối các giao dịch của người dùng, nó không khác gì một máy chủ Web2. kháng kiểm duyệt giao dịch của Ethereum hiện được đảm bảo bởi nhiều Người xác thực của nó. Nếu ai đó muốn kiểm duyệt giao dịch của Bob và ngăn chặn nó được đưa vào blockchain, họ sẽ phải hối lộ phần lớn Người xác thực của mạng hoặc spam mạng bằng các giao dịch rác có phí cao hơn Bob, do đó chiếm không gian khối. Cả hai phương pháp đều cực kỳ tốn kém.
Lưu ý: Trong kiến trúc Proposer-Builder Separation (PBS) hiện tại của Ethereum, chi phí kiểm duyệt các giao dịch được giảm đáng kể. Ví dụ: bạn có thể xem tỷ lệ các khối tuân thủ kiểm duyệt của OFAC đối với các giao dịch Tornado Cash. Việc kháng kiểm duyệt hiện tại dựa vào các Người xác thực và rơle độc lập nằm ngoài thẩm quyền của OFAC và các tổ chức chính phủ khác.
Nhưng còn Rollups thì sao? Rollups không yêu cầu một số lượng lớn các Người xác thực để đảm bảo an ninh. Ngay cả khi một Rollup chỉ có một thực thể tập trung (Sequencer) tạo ra các khối, nó vẫn an toàn như Lớp 1 (L1). Tuy nhiên, bảo mật và kháng kiểm duyệt là hai vấn đề khác nhau. Một Rollup, trong khi an toàn như Ethereum, vẫn có thể kiểm duyệt bất kỳ giao dịch nào của người dùng nếu nó chỉ có một trình tự tập trung duy nhất.
Sequencer có thể từ chối xử lý giao dịch của người dùng, dẫn đến tiền của người dùng bị khóa và không thể rời khỏi Bản tổng hợp.
Thay vì yêu cầu Rollups phải có một số lượng lớn các trình tự phi tập trung, sẽ hiệu quả hơn khi tận dụng trực tiếp kháng kiểm duyệt của Lớp 1 (L1):
Vì trình sắp xếp chuỗi cần đóng gói dữ liệu giao dịch và gửi nó đến hợp đồng Rollup trên L1, chúng tôi có thể thêm một tính năng trong hợp đồng cho phép người dùng tự chèn các giao dịch của họ vào hợp đồng Rollup. Cơ chế này được gọi là "Bao gồm lực lượng". long như trình sắp xếp không thể kiểm duyệt người dùng ở cấp L1, nó không thể ngăn người dùng buộc chèn các giao dịch tại L1. Bằng cách này, Rollup có thể kế thừa kháng kiểm duyệt của L1.
Sequencer không thể xem xét các giao dịch L1 của người dùng mà không phải trả chi phí cao
Nếu các giao dịch được phép được ghi trực tiếp vào hợp đồng Rollup thông qua Force Inclusion (nghĩa là chúng có hiệu lực ngay lập tức), trạng thái của Rollup sẽ thay đổi ngay lập tức. Ví dụ: nếu Bob sử dụng cơ chế Force Inclusion để chèn một giao dịch chuyển 1000 DAI cho Carol và giao dịch có hiệu lực ngay lập tức, số dư của Bob sẽ giảm 1000 DAI, trong khi số dư của Carol sẽ tăng 1000 DAI ở trạng thái cập nhật.
Nếu Force Inclusion cho phép các giao dịch được ghi trực tiếp vào hợp đồng Rollup và có hiệu lực ngay lập tức, trạng thái của Rollup sẽ thay đổi ngay lập tức. Nếu trình sắp xếp chuỗi đồng thời thu thập các giao dịch off-chain và chuẩn bị gửi lô tiếp theo đến hợp đồng Rollup, nó có thể bị gián đoạn bởi giao dịch buộc phải chèn của Bob có hiệu lực ngay lập tức. Để tránh vấn đề này, Rollups thường không cho phép các giao dịch Force Inclusion có hiệu lực ngay lập tức. Thay vào đó, người dùng ban đầu chèn các giao dịch của họ vào hàng đợi trên L1, nơi họ vào trạng thái "chuẩn bị". Khi trình sắp xếp chuỗi đóng gói off-chain giao dịch để gửi đến hợp đồng Tổng hợp, nó có thể chọn có bao gồm các giao dịch được xếp hàng đợi này hay không. Nếu trình sắp xếp chuỗi liên tục bỏ qua các giao dịch ở trạng thái "chuẩn bị", khi khoảng thời gian cửa sổ kết thúc, người dùng có thể buộc chèn các giao dịch này vào hợp đồng Tổng hợp. Trình tự có thể quyết định khi nào "ngẫu nhiên bao gồm" các giao dịch từ hàng đợi chờ, nhưng nó vẫn có thể từ chối xử lý chúng. Nếu trình sắp xếp chuỗi liên tục từ chối, sau một khoảng thời gian nhất định, bất kỳ ai cũng có thể sử dụng chức năng Force Inclusion để buộc chèn các giao dịch vào hợp đồng Rollup. Tiếp theo, chúng tôi sẽ giới thiệu việc triển khai cơ chế Bao gồm Lực lượng trong bốn Bản tổng hợp nổi bật: Optimism, Arbitrum, StarkNet và zkSync.
Sequencer có thể chọn thời điểm nhận giao dịch từ hàng đợi chờ.
Trình tự vẫn có thể từ chối xử lý các giao dịch trong hàng đợi chờ.
Nếu trình sắp xếp chuỗi liên tục từ chối xử lý các giao dịch, sau một khoảng thời gian nhất định, bất kỳ ai cũng có thể sử dụng chức năng Force Inclusion để buộc chèn các giao dịch vào hợp đồng Rollup. Tiếp theo, chúng tôi sẽ giới thiệu cách cơ chế Bao gồm Lực lượng được triển khai trong bốn Bản tổng hợp nổi bật: Optimism, Arbitrum, StarkNet và zkSync.
Đầu tiên, chúng ta hãy thảo luận về quy trình Gửi tiền của Optimism. Quá trình gửi tiền này không chỉ liên quan đến việc chuyển tiền vào Optimism mà còn gửi "tin nhắn người dùng đến L2". Khi một nút L2 nhận được một tin nhắn mới được gửi, nó sẽ chuyển đổi tin nhắn thành giao dịch L2 và thực hiện nó, gửi nó đến người nhận được chỉ định.
Tin nhắn người dùng gửi từ L1 đến L2
Hợp đồng L1CrossDomainMessenger
Khi người dùng muốn nạp tiền ETH hoặc ERC-20 token vào Optimism, họ tương tác với hợp đồng L1StandardBridge trên L1 thông qua trang web frontend, chỉ định số tiền cần nạp tiền và địa chỉ L2 sẽ nhận các tài sản này. Hợp đồng L1StandardBridge sau đó chuyển tiếp tin nhắn đến hợp đồng L1CrossDomainMessenger, hoạt động như cầu giao tiếp chính giữa L1 và L2. L1StandardBridge sử dụng thành phần giao tiếp này để tương tác với L2StandardBridge trên L2, xác định ai có thể đúc token trên L2 hoặc mở khóa token từ L1. Các nhà phát triển cần tạo các hợp đồng tương tác và đồng bộ hóa các trạng thái giữa L1 và L2 có thể xây dựng chúng trên hợp đồng L1CrossDomainMessenger.
Tin nhắn người dùng được truyền từ L1 đến L2 thông qua Hợp đồng CrossDomainMessenger
Lưu ý: Trong một số hình ảnh trong bài viết này, CrossDomainMessenger được viết là CrossChainMessenger.
Hợp đồng OptimismPortal
Hợp đồng L1CrossDomainMessenger sau đó chuyển tiếp tin nhắn đến lớp thấp nhất, hợp đồng OptimismPortal. Sau khi xử lý tin nhắn, hợp đồng OptimismPortal phát ra một sự kiện gọi là TransactionDeposited, bao gồm các tham số như "người gửi", "người nhận" và các chi tiết thực hiện có liên quan khác. Các nút Optimism trên L2 lắng nghe sự kiện TransactionDeposited này từ hợp đồng OptimismPortal và chuyển đổi các tham số của sự kiện thành giao dịch L2. Người khởi xướng giao dịch này sẽ là "người gửi" được chỉ định trong sự kiện, người nhận sẽ là "người nhận" được đề cập trong sự kiện và các chi tiết giao dịch khác cũng sẽ được lấy từ các thông số của sự kiện.
nút L2 chuyển đổi các tham số của sự kiện Đã gửi giao dịch do OptimismPortal phát ra thành giao dịch L2.
Ví dụ: khi người dùng gửi 0,01 ETH thông qua hợp đồng L1StandardBridge, tin nhắn và ETH được truyền đến hợp đồng OptimismPortal (địa chỉ 0xbEb5... 06Ed). Vài phút sau, điều này được chuyển đổi thành giao dịch L2: người gửi tin nhắn là hợp đồng L1CrossDomainMessenger, người nhận là hợp đồng L2CrossDomainMessenger trên L2 và nội dung tin nhắn cho biết L1StandardBridge đã nhận được 0,01 ETH nạp tiền từ Bob. Điều này sau đó kích hoạt các quy trình bổ sung, chẳng hạn như đang đúc 0,01 ETH cho L2StandardBridge, sau đó chuyển nó sang Bob.
Làm thế nào để kích hoạt nó
Nếu bạn muốn buộc đưa một giao dịch vào hợp đồng Rollup của Optimism, mục tiêu của bạn là đảm bảo rằng một giao dịch "được khởi tạo và thực hiện từ địa chỉ L2 của bạn trên L2" có thể được thực hiện thành công. Để đạt được điều này, bạn nên gửi tin nhắn trực tiếp đến hợp đồng OptimismPortal bằng địa chỉ L2 của bạn (lưu ý rằng hợp đồng OptimismPortal thực sự nằm trên L1, nhưng định dạng địa chỉ OP khớp với định dạng địa chỉ L1, vì vậy bạn có thể gọi hợp đồng này bằng tài khoản L1 có cùng địa chỉ với tài khoản L2 của bạn). "Người gửi" của giao dịch L2 bắt nguồn từ sự kiện Ký quỹ giao dịch được phát ra bởi hợp đồng này sau đó sẽ là tài khoản L2 của bạn và định dạng giao dịch sẽ phù hợp với giao dịch L2 tiêu chuẩn.
Trong giao dịch L2 bắt nguồn từ sự kiện Giao dịch đã gửi, chính Bob sẽ là người khởi tạo; người nhận sẽ là hợp đồng Uniswap; và nó sẽ bao gồm ETH được chỉ định, giống như Bob đang tự bắt đầu giao dịch L2.
Để sử dụng chức năng Force Inclusion của Optimism, bạn cần gọi trực tiếp hàm depositTransaction của hợp đồng OptimismPortal và nhập các tham số của giao dịch bạn muốn thực hiện trên L2. Tôi đã tiến hành một thí nghiệm bao gồm lực lượng đơn giản. Mục tiêu của giao dịch này là thực hiện tự chuyển khoản trên L2 bằng địa chỉ của tôi (0xeDc1... 6909) và bao gồm một thông báo nói rằng "buộc bao gồm." Đây là giao dịch L1 mình đã thực hiện bằng cách gọi hàm depositTransaction thông qua hợp đồng OptimismPortal. Như bạn có thể thấy từ sự kiện Đã nạp tiền giao dịch mà nó phát ra, cả người gửi và người nhận đều là chính tôi.
Các giá trị còn lại trong cột Dữ liệu mờ đục mã hóa thông tin như "người gọi hàm depositTransaction đính kèm ETH bao nhiêu", "người khởi tạo giao dịch L2 muốn gửi bao nhiêu ETH cho người nhận", "GasLimit giao dịch L2" và "Dữ liệu cho người nhận L2". Sau khi giải mã thông tin này, bạn sẽ nhận được các chi tiết sau: "người gọi tiền gửi đính kèm ETH bao nhiêu": 0, vì tôi không gửi ETH từ L1 đến L2; "người khởi tạo giao dịch L2 muốn gửi cho người nhận ETH bao nhiêu": 5566 (wei); "L2 giao dịch GasLimit": 50000; "Dữ liệu cho máy thu L2": 0x666f72636520696e636c7573696f6e, là mã hóa thập lục phân của chuỗi "bao gồm lực". Ngay sau đó, giao dịch L2 được chuyển đổi xuất hiện: một giao dịch L2 trong đó tôi chuyển 5566 wei cho chính mình, với trường Dữ liệu chứa chuỗi "bao gồm lực". Ngoài ra, trong dòng thứ hai đến dòng cuối cùng của phần Thuộc tính khác, TxnType (loại giao dịch) được hiển thị là giao dịch hệ thống 126 (Hệ thống), cho biết rằng giao dịch này không được tôi khởi xướng trên L2 mà được chuyển đổi từ sự kiện Nạp tiền của giao dịch L1.
Chuyển đổi giao dịch L2
Nếu bạn muốn gọi hợp đồng L2 thông qua Force Inclusion và gửi Dữ liệu khác nhau, bạn chỉ cần điền các tham số vào hàm depositTransaction. Chỉ cần nhớ sử dụng cùng một địa chỉ L1 với tài khoản L2 của bạn khi gọi hàm depositTransaction. Bằng cách này, khi Sự kiện nạp tiền được chuyển đổi thành giao dịch L2, người khởi tạo sẽ là tài khoản L2 của bạn. Cửa sổ Sequencer Nút Optimism L2 chuyển đổi sự kiện Transaction Deposited thành giao dịch L2 thực sự là Sequencer. Vì điều này liên quan đến thứ tự giao dịch, chỉ Sequencer mới có thể quyết định khi nào chuyển đổi sự kiện thành giao dịch L2. Khi Sequencer lắng nghe sự kiện TransactionDeposited, nó không nhất thiết phải chuyển đổi sự kiện thành giao dịch L2 ngay lập tức; Có thể có một sự chậm trễ. Thời gian tối đa của độ trễ này được gọi là Cửa sổ trình tự. Hiện tại, Sequencer Window trên mainnet Optimism là 24 giờ. Điều này có nghĩa là khi người dùng gửi tiền từ L1 hoặc sử dụng Force Inclusion cho một giao dịch, trong trường hợp xấu nhất, nó sẽ được đưa vào lịch sử giao dịch L2 sau 24 giờ.
Trong Optimism, hoạt động nạp tiền L1 kích hoạt sự kiện Transaction Deposited, và sau đó chỉ là vấn đề chờ đợi Sequencer bao gồm hoạt động. Tuy nhiên, trong Arbitrum, các hoạt động trên L1 (chẳng hạn như gửi tiền hoặc gửi tin nhắn đến L2) được lưu trữ trong hàng đợi trên L1, thay vì chỉ đơn giản là phát ra một sự kiện. Trình sắp xếp chuỗi có một khoảng thời gian cụ thể để bao gồm các giao dịch được xếp hàng đợi này vào lịch sử giao dịch L2. Nếu Trình sắp xếp không làm như vậy trong khung thời gian này, bất kỳ ai cũng có thể tham gia để hoàn thành việc đưa vào thay mặt cho Trình sắp xếp.
Arbitrum duy trì Hàng đợi trong hợp đồng L1. Nếu Trình sắp xếp chuỗi không xử lý các giao dịch trong Hàng đợi trong một khoảng thời gian nhất định, bất kỳ ai cũng có thể buộc đưa các giao dịch này vào lịch sử giao dịch L2. Trong thiết kế của Arbitrum, các hoạt động trên L1, chẳng hạn như tiền gửi, phải trải qua hợp đồng Hộp thư đến bị trì hoãn, trong đó, như tên cho thấy, các hoạt động này sẽ bị trì hoãn trước khi có hiệu lực. Một hợp đồng khác, Sequencer Inbox, là nơi Sequencer trực tiếp tải các giao dịch L2 lên L1. Mỗi lần Trình sắp xếp chuỗi tải lên các giao dịch L2, nó cũng có thể lấy một số giao dịch đang chờ xử lý từ Hộp thư đến bị trì hoãn và đưa chúng vào lịch sử giao dịch.
Khi Sequencer ghi các giao dịch mới, nó cũng có thể bao gồm các giao dịch từ DelayedInbox.
Thiết kế phức tạp và thiếu tài liệu tham khảo
Nếu bạn tham khảo tài liệu chính thức của Arbitrum về Sequencer và Force Inclusion, bạn sẽ tìm thấy lời giải thích chung về cách thức hoạt động của Force Inclusion, cùng với một số tham số và tên hàm: Trước tiên, người dùng gọi hàm sendUnsignedTransaction trên hợp đồng DelayedInbox. Nếu Sequencer không bao gồm nó trong vòng khoảng 24 giờ, người dùng có thể gọi hàm forceInclusion trên hợp đồng SequencerInbox. Tuy nhiên, tài liệu chính thức không cung cấp liên kết đến các chức năng này, vì vậy bạn phải tự tra cứu chúng trong mã hợp đồng. Khi bạn tìm thấy hàm sendUnsignedTransaction, bạn nhận ra rằng bạn phải tự điền giá trị nonce và giá trị maxFeePerGas. Đó là nonce của ai? MaxFeePerGas của mạng nào? Làm thế nào bạn nên điền nó một cách chính xác? Không có tài liệu tham khảo, thậm chí không có NatSpec. Bạn cũng sẽ tìm thấy nhiều chức năng tương tự trong hợp đồng Arbitrum: sendL1FundedUnsignedTransaction, sendUnsignedTransactionToFork, sendContractTransaction, sendL1FundedContractTransaction. Không có tài liệu nào giải thích sự khác biệt giữa các hàm này, cách sử dụng chúng hoặc cách điền vào các tham số, thậm chí không có NatSpec.
Bạn thử điền vào các thông số và gửi giao dịch với cách tiếp cận thử-và-sai, hy vọng sẽ tìm thấy cách sử dụng chính xác. Tuy nhiên, bạn phát hiện ra rằng tất cả các chức năng này áp dụng Địa chỉ Aliasing cho địa chỉ L1 của bạn, khiến Người gửi giao dịch trên L2 là một địa chỉ hoàn toàn khác, khiến địa chỉ L2 của bạn không hoạt động. Sau đó, bạn vô tình vấp phải kết quả tìm kiếm của Google tiết lộ rằng Arbitrum có thư viện Hướng dẫn với các tập lệnh trình bày cách gửi các giao dịch L2 từ L1 (về cơ bản là Force Inclusion). Hướng dẫn liệt kê một hàm không được đề cập trước đây: sendL2Message. Đáng ngạc nhiên, tham số tin nhắn được yêu cầu thực sự là một giao dịch L2 đã ký bằng cách sử dụng tài khoản L2. Ai có thể biết rằng "tin nhắn được gửi đến L2 thông qua Force Inclusion" thực sự là một "giao dịch L2 đã ký"? Hơn nữa, không có tài liệu hoặc NatSpec giải thích khi nào và làm thế nào để sử dụng chức năng này.
Kết luận: Việc tạo thủ công một giao dịch bắt buộc trên Arbitrum khá phức tạp. Bạn nên làm theo Hướng dẫn chính thức và sử dụng SDK Arbitrum. Không giống như các bản tổng hợp khác, Arbitrum thiếu tài liệu dành cho nhà phát triển và chú thích mã rõ ràng. Nhiều chức năng thiếu giải thích cho mục đích và tham số của chúng, khiến các nhà phát triển dành nhiều thời gian hơn dự kiến để tích hợp và sử dụng chúng. Tôi cũng đã yêu cầu giúp đỡ trong Arbitrum Discord, nhưng không nhận được câu trả lời thỏa đáng. Khi hỏi trên Discord, họ chỉ hướng dẫn tôi xem sendL2Message và không giải thích các chức năng của các phương thức khác (bao gồm cả những phương thức được đề cập trong tài liệu Force Inclusion như sendUnsignedTransaction), mục đích của chúng, cách sử dụng chúng hoặc khi nào sử dụng chúng.
Thật không may, StarkNet hiện không có cơ chế Force Inclusion. Chỉ có hai bài viết trên diễn đàn chính thức thảo luận về Kiểm duyệt và Bao gồm Lực lượng. Lý do cho việc không thể chứng minh các giao dịch thất bại là hệ thống bằng chứng không có kiến thức của StarkNet không thể chứng minh một giao dịch thất bại, vì vậy không thể cho phép Force Inclusion. Nếu ai đó cố ý (hoặc vô ý) ép buộc một giao dịch thất bại, không thể chứng minh được, StarkNet sẽ bị mắc kẹt: bởi vì một khi giao dịch bị buộc phải đưa vào, Người chứng minh phải chứng minh giao dịch thất bại, nhưng nó không thể. StarkNet dự kiến sẽ giới thiệu khả năng chứng minh các giao dịch thất bại trong phiên bản v0.15.0, sau đó cơ chế Force Inclusion nên được triển khai thêm.
cơ chế truyền tin nhắn L1->L2 và Force Inclusion của zkSync được xử lý thông qua hàm requestL2Transaction của hợp đồng MailBox. Người dùng chỉ định địa chỉ L2, calldata, lượng ETH để đính kèm, giá trị L2GasLimit và các chi tiết khác. Hàm requestL2Transaction kết hợp các tham số này vào một giao dịch L2 và đặt nó vào PriorityQueue. Khi Sequencer đóng gói các giao dịch và tải chúng lên L1 (thông qua hàm commitBatches), nó cho biết có bao nhiêu giao dịch cần thực hiện từ PriorityQueue để đưa vào bản ghi giao dịch L2. Về mặt Force Inclusion, zkSync tương tự như Optimism, trong đó địa chỉ L2 của người khởi tạo (giống như địa chỉ L1) được sử dụng để gọi các hàm có liên quan và điền vào các chi tiết cần thiết (callee, calldata, v.v.), thay vì như Arbitrum, yêu cầu giao dịch L2 đã ký. Tuy nhiên, về thiết kế, nó tương tự như Arbitrum, vì cả hai đều duy trì hàng đợi trên L1 và Sequencer nhận các giao dịch đang chờ xử lý do người dùng gửi trực tiếp từ Hàng đợi và ghi chúng vào lịch sử giao dịch.
Nếu bạn nạp tiền ETH thông qua cầu chính thức của zkSync, như giao dịch này, nó sẽ gọi hàm requestL2Transaction của hợp đồng MailBox. Hàm này đặt giao dịch Deposit ETH L2 vào PriorityQueue và phát ra sự kiện NewPriorityRequest. Vì hợp đồng mã hóa dữ liệu giao dịch L2 thành một chuỗi byte, nên nó không dễ đọc. Tuy nhiên, nếu bạn nhìn vào các thông số của giao dịch L1 này, bạn sẽ thấy rằng người nhận L2 cũng là người khởi xướng giao dịch (vì nó là nạp tiền cho chính mình). Sau một thời gian, khi Sequencer đưa giao dịch L2 này ra khỏi PriorityQueue và đưa nó vào lịch sử giao dịch, nó sẽ được chuyển đổi thành giao dịch L2 nơi bạn chuyển cho chính mình. Số tiền chuyển sẽ là số tiền ETH được đính kèm bởi người khởi tạo trong giao dịch ETH nạp L1. Trong giao dịch Tiền gửi L1, cả người khởi tạo và người nhận đều 0xeDc1... 6909, số tiền là 0,03 ETH và không có calldata. Trên L2, sẽ có một giao dịch mà 0xeDc1... 6909 chuyển đến chính nó. Loại giao dịch (TxnType) là 255, cho biết giao dịch hệ thống. Sau đó, giống như tôi đã thử nghiệm với chức năng giao dịch bắt buộc trên Optimism trước đây, tôi đã gọi hàm requestL2Transaction của zkSync và bắt đầu giao dịch tự chuyển: không có ETH nào được đính kèm và calldata chứa mã hóa HEX của chuỗi "bao gồm lực". Điều này sau đó được chuyển đổi thành một giao dịch L2 nơi tôi chuyển cho chính mình, với calldata chứa chuỗi thập lục phân cho "bao gồm lực": 0x666f72636520696e636c7573696f6e. Khi Sequencer nhận các giao dịch từ PriorityQueue và ghi chúng vào lịch sử giao dịch, chúng sẽ được chuyển đổi thành các giao dịch L2 tương ứng. Sử dụng hàm requestL2Transaction, người dùng có thể gửi dữ liệu trên L1 với cùng tài khoản L1 với địa chỉ L2 của họ, chỉ định người nhận L2, số lượng ETH cần đính kèm và calldata. Nếu người dùng muốn gọi các hợp đồng khác hoặc bao gồm các Data khác nhau, họ chỉ cần điền các tham số vào hàm requestL2Transaction. Chưa có chức năng bao gồm lực lượng cho người dùng Mặc dù một giao dịch L2 được đặt trong PriorityQueue sẽ có khoảng thời gian chờ được tính toán để đưa vào bởi Sequencer, thiết kế hiện tại của zkSync không có chức năng Force Inclusion cho phép người dùng thực thi nó. Điều này có nghĩa là nó chỉ là một giải pháp một phần. Mặc dù có một "khoảng thời gian chờ đợi để đưa vào", nhưng cuối cùng nó phụ thuộc vào việc Sequencer có quyết định bao gồm nó hay không: Sequencer có thể bao gồm nó sau khi khoảng thời gian hết hạn hoặc không bao giờ bao gồm bất kỳ giao dịch nào từ PriorityQueue. Trong tương lai, zkSync nên thêm các chức năng cho phép người dùng buộc đưa các giao dịch vào lịch sử giao dịch L2 nếu chúng chưa được Trình sắp xếp chuỗi đưa vào sau thời gian chờ đợi. Đây sẽ là một cơ chế bao gồm lực lượng thực sự hiệu quả. Tóm tắt
L1 dựa vào một số lượng lớn Người xác thực để đảm bảo "bảo mật" và "kháng kiểm duyệt" của mạng. Tuy nhiên, Rollup có kháng kiểm duyệt yếu hơn vì các giao dịch được viết bởi một vài hoặc thậm chí một Sequencer duy nhất. Do đó, Rollups cần một cơ chế Force Inclusion để cho phép người dùng bỏ qua Sequencer và ghi các giao dịch vào lịch sử, ngăn chặn sự kiểm duyệt của Sequencer làm cho Rollup không sử dụng được và ngăn người dùng rút tiền. Force Inclusion cho phép người dùng buộc ghi các giao dịch vào lịch sử, nhưng thiết kế phải chọn liệu "các giao dịch có thể được chèn ngay vào lịch sử và có hiệu lực ngay lập tức hay không". Nếu hiệu lực ngay lập tức được cho phép, nó sẽ tác động tiêu cực đến Trình sắp xếp vì các giao dịch đang chờ xử lý trên L2 có thể bị ảnh hưởng bởi các giao dịch được bao gồm cưỡng bức từ L1. Do đó, các cơ chế Force Inclusion hiện tại trong Rollups trước tiên đặt các giao dịch được chèn từ L1 vào trạng thái chờ và cung cấp cho Sequencer một khoảng thời gian để phản ứng và quyết định có bao gồm các giao dịch đang chờ xử lý này hay không. zkSync và Arbitrum đều duy trì một hàng đợi trên L1 để quản lý các giao dịch L2 hoặc tin nhắn được gửi từ L1 đến L2. Arbitrum gọi nó là DelayedInbox; zkSync gọi nó là PriorityQueue. Tuy nhiên, phương thức gửi giao dịch L2 của zkSync tương tự như Optimism, trong đó các tin nhắn được gửi từ L1 bằng địa chỉ L2, do đó khi được chuyển đổi thành giao dịch L2, người khởi tạo là địa chỉ L2. Chức năng gửi các giao dịch L2 trong Optimism được gọi là depositTransaction; trong zkSync, nó được gọi là requestL2Transaction. Ngược lại, Arbitrum tạo ra một giao dịch L2 hoàn chỉnh và ký nó, sau đó gửi nó thông qua hàm sendL2Message. Trên L2, Arbitrum sử dụng chữ ký để khôi phục người ký với tư cách là người khởi xướng giao dịch L2. StarkNet hiện không có cơ chế Force Inclusion; zkSync có cơ chế Force Inclusion được triển khai một nửa — nó có PriorityQueue và mỗi giao dịch L2 trong Hàng đợi có thời hạn hiệu lực bao gồm, nhưng thời hạn hiệu lực này hiện chỉ để hiển thị. Trong thực tế, Sequencer có thể chọn không bao gồm bất kỳ giao dịch L2 nào từ PriorityQueue.
Bài viết này được chuyển tiếp từ: [Geek Web3], tiêu đề gốc là "Lý thuyết và thực hành: Làm thế nào để kích hoạt các giao dịch chống kiểm duyệt trong Ethereum Rollup?", ghi công bản quyền cho tác giả gốc [NIC Lin, Giám đốc Taipei Ethereum Meetup], nếu bạn có bất kỳ phản đối nào đối với việc tái bản, vui lòng liên hệ Gate Learn Team, nhóm sẽ xử lý trong thời gian sớm nhất theo quy trình liên quan.
Tuyên bố từ chối trách nhiệm: Các quan điểm và ý kiến được thể hiện trong bài viết này chỉ đại diện cho quan điểm cá nhân của tác giả và không cấu thành bất kỳ lời khuyên đầu tư nào.
Các phiên bản ngôn ngữ khác của bài viết được dịch bởi nhóm Gate Learn. Không tham khảo Gate.io, việc sao chép, phân phối hoặc đạo văn các bài báo đã dịch đều bị cấm.
Mới hôm qua, một sự kiện gây sốc đã xảy ra: Linea, giải pháp Ethereum Layer 2 được phát triển bởi Consensys, công ty mẹ của Metamask, đã chủ động ngừng hoạt động. Lý do chính thức được đưa ra là để giảm thiểu tác động của sự cố hack Velocore. Sự cố này chắc chắn gợi nhớ đến một trường hợp trước đó khi chuỗi BSC (BNB Chain) cũng bị đóng cửa dưới sự phối hợp chính thức để giảm thiểu tổn thất hack. Những sự kiện này thường khiến mọi người đặt câu hỏi về các giá trị phi tập trung mà Web3 ủng hộ.
Lý do cốt lõi đằng sau các sự kiện nói trên nằm ở sự không hoàn hảo của cơ sở hạ tầng, đặc biệt là thiếu sự phân cấp. Nếu một blockchain được phân cấp đủ, nó sẽ không thể đóng cửa dễ dàng như vậy. Do cấu trúc độc đáo của Ethereum Layer 2, hầu hết các giải pháp Layer 2 đều dựa vào các bộ giải trình tự tập trung. Mặc dù diễn ngôn ngày càng tăng về các trình tự phi tập trung trong những năm gần đây, với mục đích và cấu trúc của Layer 2, chúng ta có thể giả định rằng các trình tự Layer 2 khó có thể đạt được mức độ phân cấp cao. Trên thực tế, chúng có thể sẽ ít phi tập trung hơn chuỗi BSC. Nếu đây là trường hợp, những gì có thể được thực hiện? Đối với Layer 2, rủi ro trực tiếp nhất của các trình tự không phi tập trung là thiếu kháng kiểm duyệt và sự sống động. Nếu chỉ có một vài thực thể xử lý giao dịch (trình tự chuỗi), họ có quyền lực tuyệt đối đối với việc có phục vụ bạn hay không: họ có thể từ chối giao dịch của bạn theo ý muốn, khiến bạn không có quyền truy đòi. Giải quyết vấn đề kháng kiểm duyệt trong Layer 2 rõ ràng là một chủ đề quan trọng. Trong vài năm qua, các giải pháp Ethereum Layer 2 khác nhau đã đề xuất các cách tiếp cận khác nhau để giải quyết vấn đề này. Ví dụ, Loopring, Degate và StarkEx đã giới thiệu các chức năng rút bắt buộc và thoát nở, trong khi Arbitrum và các Optimistic Rollups khác đã triển khai các tính năng Force Inclusion. Các cơ chế này có thể áp đặt kiểm tra đối với các trình tự để ngăn chặn việc từ chối tùy tiện các giao dịch của người dùng. Trong bài viết hôm nay, NIC Lin từ Hiệp hội Ethereum Đài Bắc chia sẻ kinh nghiệm trực tiếp của mình, thử nghiệm các tính năng giao dịch chống kiểm duyệt của bốn Bản tổng hợp chính và cung cấp phân tích chuyên sâu về cơ chế Bao gồm Lực lượng, tập trung vào quy trình làm việc và phương pháp hoạt động. Phân tích này đặc biệt có giá trị đối với cộng đồng Ethereum và những người nắm giữ tài sản lớn.
duyệt sự kháng cự trong các giao dịch là rất quan trọng đối với bất kỳ blockchain nào. Nếu một blockchain có thể tùy tiện kiểm duyệt và từ chối các giao dịch của người dùng, nó không khác gì một máy chủ Web2. kháng kiểm duyệt giao dịch của Ethereum hiện được đảm bảo bởi nhiều Người xác thực của nó. Nếu ai đó muốn kiểm duyệt giao dịch của Bob và ngăn chặn nó được đưa vào blockchain, họ sẽ phải hối lộ phần lớn Người xác thực của mạng hoặc spam mạng bằng các giao dịch rác có phí cao hơn Bob, do đó chiếm không gian khối. Cả hai phương pháp đều cực kỳ tốn kém.
Lưu ý: Trong kiến trúc Proposer-Builder Separation (PBS) hiện tại của Ethereum, chi phí kiểm duyệt các giao dịch được giảm đáng kể. Ví dụ: bạn có thể xem tỷ lệ các khối tuân thủ kiểm duyệt của OFAC đối với các giao dịch Tornado Cash. Việc kháng kiểm duyệt hiện tại dựa vào các Người xác thực và rơle độc lập nằm ngoài thẩm quyền của OFAC và các tổ chức chính phủ khác.
Nhưng còn Rollups thì sao? Rollups không yêu cầu một số lượng lớn các Người xác thực để đảm bảo an ninh. Ngay cả khi một Rollup chỉ có một thực thể tập trung (Sequencer) tạo ra các khối, nó vẫn an toàn như Lớp 1 (L1). Tuy nhiên, bảo mật và kháng kiểm duyệt là hai vấn đề khác nhau. Một Rollup, trong khi an toàn như Ethereum, vẫn có thể kiểm duyệt bất kỳ giao dịch nào của người dùng nếu nó chỉ có một trình tự tập trung duy nhất.
Sequencer có thể từ chối xử lý giao dịch của người dùng, dẫn đến tiền của người dùng bị khóa và không thể rời khỏi Bản tổng hợp.
Thay vì yêu cầu Rollups phải có một số lượng lớn các trình tự phi tập trung, sẽ hiệu quả hơn khi tận dụng trực tiếp kháng kiểm duyệt của Lớp 1 (L1):
Vì trình sắp xếp chuỗi cần đóng gói dữ liệu giao dịch và gửi nó đến hợp đồng Rollup trên L1, chúng tôi có thể thêm một tính năng trong hợp đồng cho phép người dùng tự chèn các giao dịch của họ vào hợp đồng Rollup. Cơ chế này được gọi là "Bao gồm lực lượng". long như trình sắp xếp không thể kiểm duyệt người dùng ở cấp L1, nó không thể ngăn người dùng buộc chèn các giao dịch tại L1. Bằng cách này, Rollup có thể kế thừa kháng kiểm duyệt của L1.
Sequencer không thể xem xét các giao dịch L1 của người dùng mà không phải trả chi phí cao
Nếu các giao dịch được phép được ghi trực tiếp vào hợp đồng Rollup thông qua Force Inclusion (nghĩa là chúng có hiệu lực ngay lập tức), trạng thái của Rollup sẽ thay đổi ngay lập tức. Ví dụ: nếu Bob sử dụng cơ chế Force Inclusion để chèn một giao dịch chuyển 1000 DAI cho Carol và giao dịch có hiệu lực ngay lập tức, số dư của Bob sẽ giảm 1000 DAI, trong khi số dư của Carol sẽ tăng 1000 DAI ở trạng thái cập nhật.
Nếu Force Inclusion cho phép các giao dịch được ghi trực tiếp vào hợp đồng Rollup và có hiệu lực ngay lập tức, trạng thái của Rollup sẽ thay đổi ngay lập tức. Nếu trình sắp xếp chuỗi đồng thời thu thập các giao dịch off-chain và chuẩn bị gửi lô tiếp theo đến hợp đồng Rollup, nó có thể bị gián đoạn bởi giao dịch buộc phải chèn của Bob có hiệu lực ngay lập tức. Để tránh vấn đề này, Rollups thường không cho phép các giao dịch Force Inclusion có hiệu lực ngay lập tức. Thay vào đó, người dùng ban đầu chèn các giao dịch của họ vào hàng đợi trên L1, nơi họ vào trạng thái "chuẩn bị". Khi trình sắp xếp chuỗi đóng gói off-chain giao dịch để gửi đến hợp đồng Tổng hợp, nó có thể chọn có bao gồm các giao dịch được xếp hàng đợi này hay không. Nếu trình sắp xếp chuỗi liên tục bỏ qua các giao dịch ở trạng thái "chuẩn bị", khi khoảng thời gian cửa sổ kết thúc, người dùng có thể buộc chèn các giao dịch này vào hợp đồng Tổng hợp. Trình tự có thể quyết định khi nào "ngẫu nhiên bao gồm" các giao dịch từ hàng đợi chờ, nhưng nó vẫn có thể từ chối xử lý chúng. Nếu trình sắp xếp chuỗi liên tục từ chối, sau một khoảng thời gian nhất định, bất kỳ ai cũng có thể sử dụng chức năng Force Inclusion để buộc chèn các giao dịch vào hợp đồng Rollup. Tiếp theo, chúng tôi sẽ giới thiệu việc triển khai cơ chế Bao gồm Lực lượng trong bốn Bản tổng hợp nổi bật: Optimism, Arbitrum, StarkNet và zkSync.
Sequencer có thể chọn thời điểm nhận giao dịch từ hàng đợi chờ.
Trình tự vẫn có thể từ chối xử lý các giao dịch trong hàng đợi chờ.
Nếu trình sắp xếp chuỗi liên tục từ chối xử lý các giao dịch, sau một khoảng thời gian nhất định, bất kỳ ai cũng có thể sử dụng chức năng Force Inclusion để buộc chèn các giao dịch vào hợp đồng Rollup. Tiếp theo, chúng tôi sẽ giới thiệu cách cơ chế Bao gồm Lực lượng được triển khai trong bốn Bản tổng hợp nổi bật: Optimism, Arbitrum, StarkNet và zkSync.
Đầu tiên, chúng ta hãy thảo luận về quy trình Gửi tiền của Optimism. Quá trình gửi tiền này không chỉ liên quan đến việc chuyển tiền vào Optimism mà còn gửi "tin nhắn người dùng đến L2". Khi một nút L2 nhận được một tin nhắn mới được gửi, nó sẽ chuyển đổi tin nhắn thành giao dịch L2 và thực hiện nó, gửi nó đến người nhận được chỉ định.
Tin nhắn người dùng gửi từ L1 đến L2
Hợp đồng L1CrossDomainMessenger
Khi người dùng muốn nạp tiền ETH hoặc ERC-20 token vào Optimism, họ tương tác với hợp đồng L1StandardBridge trên L1 thông qua trang web frontend, chỉ định số tiền cần nạp tiền và địa chỉ L2 sẽ nhận các tài sản này. Hợp đồng L1StandardBridge sau đó chuyển tiếp tin nhắn đến hợp đồng L1CrossDomainMessenger, hoạt động như cầu giao tiếp chính giữa L1 và L2. L1StandardBridge sử dụng thành phần giao tiếp này để tương tác với L2StandardBridge trên L2, xác định ai có thể đúc token trên L2 hoặc mở khóa token từ L1. Các nhà phát triển cần tạo các hợp đồng tương tác và đồng bộ hóa các trạng thái giữa L1 và L2 có thể xây dựng chúng trên hợp đồng L1CrossDomainMessenger.
Tin nhắn người dùng được truyền từ L1 đến L2 thông qua Hợp đồng CrossDomainMessenger
Lưu ý: Trong một số hình ảnh trong bài viết này, CrossDomainMessenger được viết là CrossChainMessenger.
Hợp đồng OptimismPortal
Hợp đồng L1CrossDomainMessenger sau đó chuyển tiếp tin nhắn đến lớp thấp nhất, hợp đồng OptimismPortal. Sau khi xử lý tin nhắn, hợp đồng OptimismPortal phát ra một sự kiện gọi là TransactionDeposited, bao gồm các tham số như "người gửi", "người nhận" và các chi tiết thực hiện có liên quan khác. Các nút Optimism trên L2 lắng nghe sự kiện TransactionDeposited này từ hợp đồng OptimismPortal và chuyển đổi các tham số của sự kiện thành giao dịch L2. Người khởi xướng giao dịch này sẽ là "người gửi" được chỉ định trong sự kiện, người nhận sẽ là "người nhận" được đề cập trong sự kiện và các chi tiết giao dịch khác cũng sẽ được lấy từ các thông số của sự kiện.
nút L2 chuyển đổi các tham số của sự kiện Đã gửi giao dịch do OptimismPortal phát ra thành giao dịch L2.
Ví dụ: khi người dùng gửi 0,01 ETH thông qua hợp đồng L1StandardBridge, tin nhắn và ETH được truyền đến hợp đồng OptimismPortal (địa chỉ 0xbEb5... 06Ed). Vài phút sau, điều này được chuyển đổi thành giao dịch L2: người gửi tin nhắn là hợp đồng L1CrossDomainMessenger, người nhận là hợp đồng L2CrossDomainMessenger trên L2 và nội dung tin nhắn cho biết L1StandardBridge đã nhận được 0,01 ETH nạp tiền từ Bob. Điều này sau đó kích hoạt các quy trình bổ sung, chẳng hạn như đang đúc 0,01 ETH cho L2StandardBridge, sau đó chuyển nó sang Bob.
Làm thế nào để kích hoạt nó
Nếu bạn muốn buộc đưa một giao dịch vào hợp đồng Rollup của Optimism, mục tiêu của bạn là đảm bảo rằng một giao dịch "được khởi tạo và thực hiện từ địa chỉ L2 của bạn trên L2" có thể được thực hiện thành công. Để đạt được điều này, bạn nên gửi tin nhắn trực tiếp đến hợp đồng OptimismPortal bằng địa chỉ L2 của bạn (lưu ý rằng hợp đồng OptimismPortal thực sự nằm trên L1, nhưng định dạng địa chỉ OP khớp với định dạng địa chỉ L1, vì vậy bạn có thể gọi hợp đồng này bằng tài khoản L1 có cùng địa chỉ với tài khoản L2 của bạn). "Người gửi" của giao dịch L2 bắt nguồn từ sự kiện Ký quỹ giao dịch được phát ra bởi hợp đồng này sau đó sẽ là tài khoản L2 của bạn và định dạng giao dịch sẽ phù hợp với giao dịch L2 tiêu chuẩn.
Trong giao dịch L2 bắt nguồn từ sự kiện Giao dịch đã gửi, chính Bob sẽ là người khởi tạo; người nhận sẽ là hợp đồng Uniswap; và nó sẽ bao gồm ETH được chỉ định, giống như Bob đang tự bắt đầu giao dịch L2.
Để sử dụng chức năng Force Inclusion của Optimism, bạn cần gọi trực tiếp hàm depositTransaction của hợp đồng OptimismPortal và nhập các tham số của giao dịch bạn muốn thực hiện trên L2. Tôi đã tiến hành một thí nghiệm bao gồm lực lượng đơn giản. Mục tiêu của giao dịch này là thực hiện tự chuyển khoản trên L2 bằng địa chỉ của tôi (0xeDc1... 6909) và bao gồm một thông báo nói rằng "buộc bao gồm." Đây là giao dịch L1 mình đã thực hiện bằng cách gọi hàm depositTransaction thông qua hợp đồng OptimismPortal. Như bạn có thể thấy từ sự kiện Đã nạp tiền giao dịch mà nó phát ra, cả người gửi và người nhận đều là chính tôi.
Các giá trị còn lại trong cột Dữ liệu mờ đục mã hóa thông tin như "người gọi hàm depositTransaction đính kèm ETH bao nhiêu", "người khởi tạo giao dịch L2 muốn gửi bao nhiêu ETH cho người nhận", "GasLimit giao dịch L2" và "Dữ liệu cho người nhận L2". Sau khi giải mã thông tin này, bạn sẽ nhận được các chi tiết sau: "người gọi tiền gửi đính kèm ETH bao nhiêu": 0, vì tôi không gửi ETH từ L1 đến L2; "người khởi tạo giao dịch L2 muốn gửi cho người nhận ETH bao nhiêu": 5566 (wei); "L2 giao dịch GasLimit": 50000; "Dữ liệu cho máy thu L2": 0x666f72636520696e636c7573696f6e, là mã hóa thập lục phân của chuỗi "bao gồm lực". Ngay sau đó, giao dịch L2 được chuyển đổi xuất hiện: một giao dịch L2 trong đó tôi chuyển 5566 wei cho chính mình, với trường Dữ liệu chứa chuỗi "bao gồm lực". Ngoài ra, trong dòng thứ hai đến dòng cuối cùng của phần Thuộc tính khác, TxnType (loại giao dịch) được hiển thị là giao dịch hệ thống 126 (Hệ thống), cho biết rằng giao dịch này không được tôi khởi xướng trên L2 mà được chuyển đổi từ sự kiện Nạp tiền của giao dịch L1.
Chuyển đổi giao dịch L2
Nếu bạn muốn gọi hợp đồng L2 thông qua Force Inclusion và gửi Dữ liệu khác nhau, bạn chỉ cần điền các tham số vào hàm depositTransaction. Chỉ cần nhớ sử dụng cùng một địa chỉ L1 với tài khoản L2 của bạn khi gọi hàm depositTransaction. Bằng cách này, khi Sự kiện nạp tiền được chuyển đổi thành giao dịch L2, người khởi tạo sẽ là tài khoản L2 của bạn. Cửa sổ Sequencer Nút Optimism L2 chuyển đổi sự kiện Transaction Deposited thành giao dịch L2 thực sự là Sequencer. Vì điều này liên quan đến thứ tự giao dịch, chỉ Sequencer mới có thể quyết định khi nào chuyển đổi sự kiện thành giao dịch L2. Khi Sequencer lắng nghe sự kiện TransactionDeposited, nó không nhất thiết phải chuyển đổi sự kiện thành giao dịch L2 ngay lập tức; Có thể có một sự chậm trễ. Thời gian tối đa của độ trễ này được gọi là Cửa sổ trình tự. Hiện tại, Sequencer Window trên mainnet Optimism là 24 giờ. Điều này có nghĩa là khi người dùng gửi tiền từ L1 hoặc sử dụng Force Inclusion cho một giao dịch, trong trường hợp xấu nhất, nó sẽ được đưa vào lịch sử giao dịch L2 sau 24 giờ.
Trong Optimism, hoạt động nạp tiền L1 kích hoạt sự kiện Transaction Deposited, và sau đó chỉ là vấn đề chờ đợi Sequencer bao gồm hoạt động. Tuy nhiên, trong Arbitrum, các hoạt động trên L1 (chẳng hạn như gửi tiền hoặc gửi tin nhắn đến L2) được lưu trữ trong hàng đợi trên L1, thay vì chỉ đơn giản là phát ra một sự kiện. Trình sắp xếp chuỗi có một khoảng thời gian cụ thể để bao gồm các giao dịch được xếp hàng đợi này vào lịch sử giao dịch L2. Nếu Trình sắp xếp không làm như vậy trong khung thời gian này, bất kỳ ai cũng có thể tham gia để hoàn thành việc đưa vào thay mặt cho Trình sắp xếp.
Arbitrum duy trì Hàng đợi trong hợp đồng L1. Nếu Trình sắp xếp chuỗi không xử lý các giao dịch trong Hàng đợi trong một khoảng thời gian nhất định, bất kỳ ai cũng có thể buộc đưa các giao dịch này vào lịch sử giao dịch L2. Trong thiết kế của Arbitrum, các hoạt động trên L1, chẳng hạn như tiền gửi, phải trải qua hợp đồng Hộp thư đến bị trì hoãn, trong đó, như tên cho thấy, các hoạt động này sẽ bị trì hoãn trước khi có hiệu lực. Một hợp đồng khác, Sequencer Inbox, là nơi Sequencer trực tiếp tải các giao dịch L2 lên L1. Mỗi lần Trình sắp xếp chuỗi tải lên các giao dịch L2, nó cũng có thể lấy một số giao dịch đang chờ xử lý từ Hộp thư đến bị trì hoãn và đưa chúng vào lịch sử giao dịch.
Khi Sequencer ghi các giao dịch mới, nó cũng có thể bao gồm các giao dịch từ DelayedInbox.
Thiết kế phức tạp và thiếu tài liệu tham khảo
Nếu bạn tham khảo tài liệu chính thức của Arbitrum về Sequencer và Force Inclusion, bạn sẽ tìm thấy lời giải thích chung về cách thức hoạt động của Force Inclusion, cùng với một số tham số và tên hàm: Trước tiên, người dùng gọi hàm sendUnsignedTransaction trên hợp đồng DelayedInbox. Nếu Sequencer không bao gồm nó trong vòng khoảng 24 giờ, người dùng có thể gọi hàm forceInclusion trên hợp đồng SequencerInbox. Tuy nhiên, tài liệu chính thức không cung cấp liên kết đến các chức năng này, vì vậy bạn phải tự tra cứu chúng trong mã hợp đồng. Khi bạn tìm thấy hàm sendUnsignedTransaction, bạn nhận ra rằng bạn phải tự điền giá trị nonce và giá trị maxFeePerGas. Đó là nonce của ai? MaxFeePerGas của mạng nào? Làm thế nào bạn nên điền nó một cách chính xác? Không có tài liệu tham khảo, thậm chí không có NatSpec. Bạn cũng sẽ tìm thấy nhiều chức năng tương tự trong hợp đồng Arbitrum: sendL1FundedUnsignedTransaction, sendUnsignedTransactionToFork, sendContractTransaction, sendL1FundedContractTransaction. Không có tài liệu nào giải thích sự khác biệt giữa các hàm này, cách sử dụng chúng hoặc cách điền vào các tham số, thậm chí không có NatSpec.
Bạn thử điền vào các thông số và gửi giao dịch với cách tiếp cận thử-và-sai, hy vọng sẽ tìm thấy cách sử dụng chính xác. Tuy nhiên, bạn phát hiện ra rằng tất cả các chức năng này áp dụng Địa chỉ Aliasing cho địa chỉ L1 của bạn, khiến Người gửi giao dịch trên L2 là một địa chỉ hoàn toàn khác, khiến địa chỉ L2 của bạn không hoạt động. Sau đó, bạn vô tình vấp phải kết quả tìm kiếm của Google tiết lộ rằng Arbitrum có thư viện Hướng dẫn với các tập lệnh trình bày cách gửi các giao dịch L2 từ L1 (về cơ bản là Force Inclusion). Hướng dẫn liệt kê một hàm không được đề cập trước đây: sendL2Message. Đáng ngạc nhiên, tham số tin nhắn được yêu cầu thực sự là một giao dịch L2 đã ký bằng cách sử dụng tài khoản L2. Ai có thể biết rằng "tin nhắn được gửi đến L2 thông qua Force Inclusion" thực sự là một "giao dịch L2 đã ký"? Hơn nữa, không có tài liệu hoặc NatSpec giải thích khi nào và làm thế nào để sử dụng chức năng này.
Kết luận: Việc tạo thủ công một giao dịch bắt buộc trên Arbitrum khá phức tạp. Bạn nên làm theo Hướng dẫn chính thức và sử dụng SDK Arbitrum. Không giống như các bản tổng hợp khác, Arbitrum thiếu tài liệu dành cho nhà phát triển và chú thích mã rõ ràng. Nhiều chức năng thiếu giải thích cho mục đích và tham số của chúng, khiến các nhà phát triển dành nhiều thời gian hơn dự kiến để tích hợp và sử dụng chúng. Tôi cũng đã yêu cầu giúp đỡ trong Arbitrum Discord, nhưng không nhận được câu trả lời thỏa đáng. Khi hỏi trên Discord, họ chỉ hướng dẫn tôi xem sendL2Message và không giải thích các chức năng của các phương thức khác (bao gồm cả những phương thức được đề cập trong tài liệu Force Inclusion như sendUnsignedTransaction), mục đích của chúng, cách sử dụng chúng hoặc khi nào sử dụng chúng.
Thật không may, StarkNet hiện không có cơ chế Force Inclusion. Chỉ có hai bài viết trên diễn đàn chính thức thảo luận về Kiểm duyệt và Bao gồm Lực lượng. Lý do cho việc không thể chứng minh các giao dịch thất bại là hệ thống bằng chứng không có kiến thức của StarkNet không thể chứng minh một giao dịch thất bại, vì vậy không thể cho phép Force Inclusion. Nếu ai đó cố ý (hoặc vô ý) ép buộc một giao dịch thất bại, không thể chứng minh được, StarkNet sẽ bị mắc kẹt: bởi vì một khi giao dịch bị buộc phải đưa vào, Người chứng minh phải chứng minh giao dịch thất bại, nhưng nó không thể. StarkNet dự kiến sẽ giới thiệu khả năng chứng minh các giao dịch thất bại trong phiên bản v0.15.0, sau đó cơ chế Force Inclusion nên được triển khai thêm.
cơ chế truyền tin nhắn L1->L2 và Force Inclusion của zkSync được xử lý thông qua hàm requestL2Transaction của hợp đồng MailBox. Người dùng chỉ định địa chỉ L2, calldata, lượng ETH để đính kèm, giá trị L2GasLimit và các chi tiết khác. Hàm requestL2Transaction kết hợp các tham số này vào một giao dịch L2 và đặt nó vào PriorityQueue. Khi Sequencer đóng gói các giao dịch và tải chúng lên L1 (thông qua hàm commitBatches), nó cho biết có bao nhiêu giao dịch cần thực hiện từ PriorityQueue để đưa vào bản ghi giao dịch L2. Về mặt Force Inclusion, zkSync tương tự như Optimism, trong đó địa chỉ L2 của người khởi tạo (giống như địa chỉ L1) được sử dụng để gọi các hàm có liên quan và điền vào các chi tiết cần thiết (callee, calldata, v.v.), thay vì như Arbitrum, yêu cầu giao dịch L2 đã ký. Tuy nhiên, về thiết kế, nó tương tự như Arbitrum, vì cả hai đều duy trì hàng đợi trên L1 và Sequencer nhận các giao dịch đang chờ xử lý do người dùng gửi trực tiếp từ Hàng đợi và ghi chúng vào lịch sử giao dịch.
Nếu bạn nạp tiền ETH thông qua cầu chính thức của zkSync, như giao dịch này, nó sẽ gọi hàm requestL2Transaction của hợp đồng MailBox. Hàm này đặt giao dịch Deposit ETH L2 vào PriorityQueue và phát ra sự kiện NewPriorityRequest. Vì hợp đồng mã hóa dữ liệu giao dịch L2 thành một chuỗi byte, nên nó không dễ đọc. Tuy nhiên, nếu bạn nhìn vào các thông số của giao dịch L1 này, bạn sẽ thấy rằng người nhận L2 cũng là người khởi xướng giao dịch (vì nó là nạp tiền cho chính mình). Sau một thời gian, khi Sequencer đưa giao dịch L2 này ra khỏi PriorityQueue và đưa nó vào lịch sử giao dịch, nó sẽ được chuyển đổi thành giao dịch L2 nơi bạn chuyển cho chính mình. Số tiền chuyển sẽ là số tiền ETH được đính kèm bởi người khởi tạo trong giao dịch ETH nạp L1. Trong giao dịch Tiền gửi L1, cả người khởi tạo và người nhận đều 0xeDc1... 6909, số tiền là 0,03 ETH và không có calldata. Trên L2, sẽ có một giao dịch mà 0xeDc1... 6909 chuyển đến chính nó. Loại giao dịch (TxnType) là 255, cho biết giao dịch hệ thống. Sau đó, giống như tôi đã thử nghiệm với chức năng giao dịch bắt buộc trên Optimism trước đây, tôi đã gọi hàm requestL2Transaction của zkSync và bắt đầu giao dịch tự chuyển: không có ETH nào được đính kèm và calldata chứa mã hóa HEX của chuỗi "bao gồm lực". Điều này sau đó được chuyển đổi thành một giao dịch L2 nơi tôi chuyển cho chính mình, với calldata chứa chuỗi thập lục phân cho "bao gồm lực": 0x666f72636520696e636c7573696f6e. Khi Sequencer nhận các giao dịch từ PriorityQueue và ghi chúng vào lịch sử giao dịch, chúng sẽ được chuyển đổi thành các giao dịch L2 tương ứng. Sử dụng hàm requestL2Transaction, người dùng có thể gửi dữ liệu trên L1 với cùng tài khoản L1 với địa chỉ L2 của họ, chỉ định người nhận L2, số lượng ETH cần đính kèm và calldata. Nếu người dùng muốn gọi các hợp đồng khác hoặc bao gồm các Data khác nhau, họ chỉ cần điền các tham số vào hàm requestL2Transaction. Chưa có chức năng bao gồm lực lượng cho người dùng Mặc dù một giao dịch L2 được đặt trong PriorityQueue sẽ có khoảng thời gian chờ được tính toán để đưa vào bởi Sequencer, thiết kế hiện tại của zkSync không có chức năng Force Inclusion cho phép người dùng thực thi nó. Điều này có nghĩa là nó chỉ là một giải pháp một phần. Mặc dù có một "khoảng thời gian chờ đợi để đưa vào", nhưng cuối cùng nó phụ thuộc vào việc Sequencer có quyết định bao gồm nó hay không: Sequencer có thể bao gồm nó sau khi khoảng thời gian hết hạn hoặc không bao giờ bao gồm bất kỳ giao dịch nào từ PriorityQueue. Trong tương lai, zkSync nên thêm các chức năng cho phép người dùng buộc đưa các giao dịch vào lịch sử giao dịch L2 nếu chúng chưa được Trình sắp xếp chuỗi đưa vào sau thời gian chờ đợi. Đây sẽ là một cơ chế bao gồm lực lượng thực sự hiệu quả. Tóm tắt
L1 dựa vào một số lượng lớn Người xác thực để đảm bảo "bảo mật" và "kháng kiểm duyệt" của mạng. Tuy nhiên, Rollup có kháng kiểm duyệt yếu hơn vì các giao dịch được viết bởi một vài hoặc thậm chí một Sequencer duy nhất. Do đó, Rollups cần một cơ chế Force Inclusion để cho phép người dùng bỏ qua Sequencer và ghi các giao dịch vào lịch sử, ngăn chặn sự kiểm duyệt của Sequencer làm cho Rollup không sử dụng được và ngăn người dùng rút tiền. Force Inclusion cho phép người dùng buộc ghi các giao dịch vào lịch sử, nhưng thiết kế phải chọn liệu "các giao dịch có thể được chèn ngay vào lịch sử và có hiệu lực ngay lập tức hay không". Nếu hiệu lực ngay lập tức được cho phép, nó sẽ tác động tiêu cực đến Trình sắp xếp vì các giao dịch đang chờ xử lý trên L2 có thể bị ảnh hưởng bởi các giao dịch được bao gồm cưỡng bức từ L1. Do đó, các cơ chế Force Inclusion hiện tại trong Rollups trước tiên đặt các giao dịch được chèn từ L1 vào trạng thái chờ và cung cấp cho Sequencer một khoảng thời gian để phản ứng và quyết định có bao gồm các giao dịch đang chờ xử lý này hay không. zkSync và Arbitrum đều duy trì một hàng đợi trên L1 để quản lý các giao dịch L2 hoặc tin nhắn được gửi từ L1 đến L2. Arbitrum gọi nó là DelayedInbox; zkSync gọi nó là PriorityQueue. Tuy nhiên, phương thức gửi giao dịch L2 của zkSync tương tự như Optimism, trong đó các tin nhắn được gửi từ L1 bằng địa chỉ L2, do đó khi được chuyển đổi thành giao dịch L2, người khởi tạo là địa chỉ L2. Chức năng gửi các giao dịch L2 trong Optimism được gọi là depositTransaction; trong zkSync, nó được gọi là requestL2Transaction. Ngược lại, Arbitrum tạo ra một giao dịch L2 hoàn chỉnh và ký nó, sau đó gửi nó thông qua hàm sendL2Message. Trên L2, Arbitrum sử dụng chữ ký để khôi phục người ký với tư cách là người khởi xướng giao dịch L2. StarkNet hiện không có cơ chế Force Inclusion; zkSync có cơ chế Force Inclusion được triển khai một nửa — nó có PriorityQueue và mỗi giao dịch L2 trong Hàng đợi có thời hạn hiệu lực bao gồm, nhưng thời hạn hiệu lực này hiện chỉ để hiển thị. Trong thực tế, Sequencer có thể chọn không bao gồm bất kỳ giao dịch L2 nào từ PriorityQueue.
Bài viết này được chuyển tiếp từ: [Geek Web3], tiêu đề gốc là "Lý thuyết và thực hành: Làm thế nào để kích hoạt các giao dịch chống kiểm duyệt trong Ethereum Rollup?", ghi công bản quyền cho tác giả gốc [NIC Lin, Giám đốc Taipei Ethereum Meetup], nếu bạn có bất kỳ phản đối nào đối với việc tái bản, vui lòng liên hệ Gate Learn Team, nhóm sẽ xử lý trong thời gian sớm nhất theo quy trình liên quan.
Tuyên bố từ chối trách nhiệm: Các quan điểm và ý kiến được thể hiện trong bài viết này chỉ đại diện cho quan điểm cá nhân của tác giả và không cấu thành bất kỳ lời khuyên đầu tư nào.
Các phiên bản ngôn ngữ khác của bài viết được dịch bởi nhóm Gate Learn. Không tham khảo Gate.io, việc sao chép, phân phối hoặc đạo văn các bài báo đã dịch đều bị cấm.