
Bài viết mới nhất của Vitalik: Thảo luận về tương lai và thách thức của ZK-EVM
Tuyển chọn TechFlowTuyển chọn TechFlow

Bài viết mới nhất của Vitalik: Thảo luận về tương lai và thách thức của ZK-EVM
ZK-EVM nhằm giảm việc triển khai lại các chức năng giao thức Ethereum của các dự án L2 và nâng cao hiệu quả xác minh khối Ethereum.
Tác giả: Vitalik Buterin
Dịch: 1912212.eth, Foresight News
Các giao thức EVM lớp hai trên Ethereum, bao gồm optimistic rollups và ZK rollups, đều phụ thuộc vào việc xác thực EVM. Tuy nhiên, điều này buộc họ phải tin tưởng vào một kho mã nguồn khổng lồ, và nếu tồn tại lỗi trong kho mã đó, các máy ảo (VM) này có nguy cơ bị tấn công. Ngoài ra, điều này cũng có nghĩa là ngay cả những ZK-EVM mong muốn hoàn toàn tương đương với EVM lớp 1 (L1) cũng cần một hình thức quản trị nào đó để sao chép các thay đổi từ EVM L1 vào triển khai EVM riêng của họ.
Tình trạng này không lý tưởng, vì các dự án này đang sao chép chức năng vốn đã tồn tại trong giao thức Ethereum — nơi mà quản trị Ethereum đã chịu trách nhiệm nâng cấp và sửa lỗi: về cơ bản, ZK-EVM làm cùng một công việc như việc xác minh khối Ethereum lớp 1! Hơn nữa, trong vài năm tới, chúng ta dự kiến các client nhẹ sẽ ngày càng mạnh mẽ hơn, sớm đạt đến mức sử dụng ZK-SNARKs để xác minh hoàn toàn việc thực thi EVM lớp 1. Khi đó, mạng Ethereum sẽ hiệu quả tạo thành một ZK-EVM tích hợp sẵn. Do đó, câu hỏi đặt ra là: tại sao không để chính ZK-EVM cũng phục vụ cho rollup?
Bài viết này sẽ trình bày một số phiên bản "ZK-EVM tích hợp" có thể thực hiện được, đồng thời thảo luận về các điểm đánh đổi, thách thức thiết kế, và lý do không theo đuổi một hướng cụ thể nào. Lợi ích của việc triển khai tính năng giao thức cần được cân nhắc so với lợi ích của việc để hệ sinh thái tự xử lý và giữ cho giao thức nền tảng đơn giản.
Chúng ta kỳ vọng những đặc tính then chốt nào từ ZK-EVM tích hợp?
-
Chức năng cơ bản: Xác minh khối Ethereum. Tính năng giao thức (hiện chưa rõ là opcode, tiền biên dịch hay cơ chế khác) nên chấp nhận ít nhất một gốc trạng thái trước, một khối và một gốc trạng thái sau làm đầu vào, và xác minh rằng gốc trạng thái sau thực sự là kết quả sau khi thực thi khối.
-
Tương thích với nhiều client Ethereum khác nhau. Điều này có nghĩa là chúng ta muốn tránh áp dụng duy nhất một hệ thống chứng minh, mà thay vào đó cho phép các client khác nhau sử dụng các hệ thống chứng minh khác nhau. Điều này dẫn đến các điểm sau:
-
Yêu cầu về tính sẵn có dữ liệu: Với mọi việc thực thi EVM sử dụng ZK-EVM tích hợp để chứng minh, chúng ta muốn đảm bảo dữ liệu nền tảng luôn sẵn có, để các bên chứng minh dùng hệ thống chứng minh khác có thể chứng minh lại việc thực thi, và cho phép các client phụ thuộc vào hệ thống chứng minh đó xác minh được chứng minh mới được tạo.
-
Chứng minh nằm ngoài EVM và cấu trúc dữ liệu khối: Chức năng ZK-EVM tích hợp sẽ không đưa SNARK vào làm đầu vào bên trong EVM, bởi vì các client khác nhau sẽ kỳ vọng các loại SNARK khác nhau. Thay vào đó, nó có thể giống như việc xác minh blob: giao dịch có thể bao gồm tuyên bố (trạng thái trước, thân khối, trạng thái sau) cần được chứng minh, một opcode hoặc tiền biên dịch có thể truy cập nội dung các tuyên bố này, còn quy tắc đồng thuận của client sẽ kiểm tra riêng biệt tính sẵn có dữ liệu và sự tồn tại của chứng minh cho từng tuyên bố.
-
Khả năng kiểm toán. Nếu bất kỳ lần thực thi nào được chứng minh, chúng ta muốn dữ liệu nền tảng là sẵn có, để khi có vấn đề xảy ra, người dùng và nhà phát triển có thể kiểm tra. Trên thực tế, điều này làm tăng thêm một lý do nữa tại sao yêu cầu về tính sẵn có dữ liệu lại quan trọng đến vậy.
-
Khả năng nâng cấp. Nếu một phương án ZK-EVM nào đó bị phát hiện có lỗi, chúng ta cần có thể nhanh chóng sửa chữa nó. Điều này có nghĩa là không cần hard fork để sửa lỗi. Đây cũng là một lý do bổ sung cho việc chứng minh phải nằm ngoài EVM và cấu trúc dữ liệu khối.
-
Hỗ trợ hầu hết mọi EVM. Một trong những điểm hấp dẫn của L2 là đổi mới ở tầng thực thi và mở rộng EVM. Nếu VM của một L2 nào đó chỉ khác EVM một chút, thì sẽ rất tốt nếu L2 đó vẫn có thể sử dụng ZK-EVM tích hợp trong phần giống EVM, và chỉ phụ thuộc vào mã riêng của mình ở những phần khác biệt. Điều này có thể thực hiện bằng cách thiết kế chức năng ZK-EVM cho phép người gọi chỉ định các trường bit, danh sách opcode hoặc địa chỉ, mà các trường, danh sách hoặc địa chỉ này được xử lý bởi một bảng cung cấp từ bên ngoài thay vì bởi chính EVM. Chúng ta cũng có thể mở khả năng chỉnh sửa chi phí Gas ở một mức độ nào đó.
Hệ thống đa client "mở" và "đóng"
"Triết lý đa client" có lẽ là yêu cầu chủ quan nhất trong danh sách này. Có thể lựa chọn từ bỏ nó, tập trung vào một sơ đồ ZK-SNARK duy nhất, điều này sẽ đơn giản hóa thiết kế nhưng đi kèm với cái giá là một "bước ngoặt triết học" lớn hơn đối với Ethereum (vì thực chất là từ bỏ triết lý đa client lâu đời của Ethereum), và rủi ro cao hơn. Có thể con đường này sẽ tốt hơn trong tương lai nếu kỹ thuật xác minh hình thức trở nên tốt hơn, nhưng hiện tại dường như rủi ro quá lớn.
Một lựa chọn khác là hệ thống đa client đóng, trong đó giao thức xác định sẵn một tập hợp cố định các hệ thống chứng minh. Ví dụ, chúng ta có thể quyết định sử dụng ba ZK-EVM: PSE ZK-EVM, Polygon ZK-EVM và Kakarot. Một khối chỉ hợp lệ nếu có chứng minh từ ít nhất hai trong ba hệ thống này. Cách này tốt hơn hệ thống chứng minh đơn, nhưng khiến hệ thống kém linh hoạt hơn, vì người dùng phải duy trì bộ xác minh cho mỗi hệ thống chứng minh tồn tại, và chắc chắn sẽ có quá trình quản trị mang tính chính trị để đưa thêm hệ thống chứng minh mới vào.
Điều này thúc đẩy tôi nghiêng về hệ thống đa client mở, trong đó chứng minh được đặt "ngoài khối" và được các client xác minh riêng lẻ. Người dùng cá nhân có thể sử dụng bất kỳ client nào họ muốn để xác minh khối, miễn là có ít nhất một bên chứng minh tạo chứng minh cho hệ thống đó. Các hệ thống chứng minh sẽ giành ảnh hưởng bằng cách thuyết phục người dùng chạy chúng, chứ không phải bằng cách thuyết phục quá trình quản trị giao thức. Tuy nhiên, phương pháp này thực sự có chi phí phức tạp cao hơn, như chúng ta sẽ thấy.
Chúng ta kỳ vọng những thuộc tính then chốt nào từ việc triển khai ZK-EVM?
Ngoài các đảm bảo cơ bản về tính đúng đắn và an toàn chức năng, thuộc tính quan trọng nhất là tốc độ. Mặc dù chúng ta có thể thiết kế tính năng ZK-EVM trong giao thức dưới dạng bất đồng bộ, chỉ trả lời kết quả cho mỗi tuyên bố sau N khe trống, nhưng nếu chúng ta có thể đảm bảo đáng tin cậy rằng một chứng minh có thể được tạo ra trong vài giây, thì mọi thứ sẽ dễ dàng hơn rất nhiều — khi đó mọi khối đều tự chứa đựng đầy đủ thông tin bất kể chuyện gì xảy ra.
Mặc dù hiện tại việc tạo chứng minh cho khối Ethereum mất hàng phút hoặc hàng giờ, chúng ta biết rằng không có lý do lý thuyết nào ngăn cản việc song song hóa quy mô lớn: chúng ta luôn có thể kết hợp đủ GPU để chứng minh riêng biệt từng phần của việc thực thi khối, rồi dùng SNARK đệ quy để ghép các chứng minh lại. Hơn nữa, tăng tốc phần cứng qua FPGA và ASIC có thể giúp tối ưu hóa thêm. Tuy nhiên, thực sự đạt được bước này là một thách thức kỹ thuật khổng lồ không thể xem nhẹ.
Tính năng ZK-EVM trong giao thức có thể trông như thế nào về mặt cụ thể?
Tương tự như giao dịch blob trong EIP-4844, chúng ta giới thiệu một loại giao dịch mới chứa các tuyên bố ZK-EVM:
class ZKEVMClaimTransaction(Container):pre_state_root: bytes32post_state_root: bytes32transaction_and_witness_blob_pointers: List[VersionedHash]
Giống như EIP-4844, đối tượng được truyền trong mempool sẽ là phiên bản đã sửa đổi của giao dịch:
class ZKEvmClaimNetworkTransaction(Container):pre_state_root: bytes32post_state_root: bytes32proof: bytestransaction_and_witness_blobs: List[Bytes[FIELD_ELEMENTS_PER_BLOB * 31]]
Phiên bản sau có thể chuyển đổi thành phiên bản trước, nhưng ngược lại thì không. Chúng ta cũng mở rộng đối tượng sidecar của khối (được giới thiệu trong EIP-4844) để bao gồm danh sách các chứng minh được tuyên bố trong khối.

Lưu ý rằng trong thực tế, chúng ta có thể muốn tách sidecar thành hai sidecar riêng biệt, một cho blobs và một cho chứng minh, và thiết lập subnet riêng cho mỗi loại chứng minh (cũng như cho các subnet con bổ sung của blobs).
Ở tầng đồng thuận, chúng ta thêm các quy tắc xác thực: chỉ chấp nhận khối nếu client nhìn thấy chứng minh hợp lệ cho mỗi tuyên bố trong khối. Chứng minh phải là một ZK-SNARK, chứng minh rằng chuỗi nối các transaction_and_witness_blobs là một dãy các cặp (Block, Witness), và việc thực thi khối trên Witness với pre_state_root
(i) là hợp lệ, và
(ii) cho ra post_state_root đúng. Có thể xảy ra trường hợp client có thể chọn đợi M-trong-N loại chứng minh.
Lưu ý ở đây là việc thực thi khối bản thân nó có thể được coi đơn giản như một trong các bộ ba cần được kiểm tra cùng với bộ ba cung cấp trong đối tượng ZKEVMClaimTransaction (σpre,σpost,Proof). Do đó, triển khai ZK-EVM của người dùng có thể thay thế client thực thi của họ; client thực thi vẫn sẽ được sử dụng bởi
(i) các bên chứng minh và các bên xây dựng khối, và
(ii) các nút quan tâm đến việc lập chỉ mục và lưu trữ dữ liệu để sử dụng cục bộ.
Hơn nữa, do kiến trúc này tách biệt thực thi khỏi xác minh, nó có thể mang lại sự linh hoạt và hiệu quả cao hơn cho các vai trò khác nhau trong hệ sinh thái Ethereum. Ví dụ, các bên chứng minh có thể tập trung vào việc tạo chứng minh mà không cần lo lắng về chi tiết thực thi, trong khi các client thực thi có thể được tối ưu hóa để đáp ứng nhu cầu cụ thể của người dùng, ví dụ như đồng bộ nhanh hoặc chức năng lập chỉ mục nâng cao.
Xác minh và chứng minh lại
Giả sử có hai client Ethereum, một dùng PSE ZK-EVM và một dùng Polygon ZK-EVM, cả hai triển khai này đã phát triển đến mức có thể chứng minh việc thực thi khối Ethereum trong vòng 5 giây, và với mỗi hệ thống chứng minh, có đủ nhiều tình nguyện viên độc lập chạy phần cứng để tạo chứng minh.
Tiếc là vì các hệ thống chứng minh riêng lẻ không được chính thức công nhận, chúng không thể nhận được khuyến khích trong giao thức; tuy nhiên, chúng ta dự đoán chi phí vận hành chứng minh sẽ thấp hơn nhiều so với nghiên cứu và phát triển, do đó chúng ta có thể dễ dàng tài trợ cho các bên chứng minh thông qua các tổ chức hỗ trợ hàng hóa công cộng.
Giả sử ai đó đăng một giao dịch ZKEvmClaimNetworkTransaction, nhưng chỉ đăng chứng minh theo phiên bản PSE ZK-EVM. Nút chứng minh của Polygon ZK-EVM nhìn thấy điều này, tính toán và đăng lại đối tượng đó, kèm theo chứng minh của Polygon ZK-EVM.

Việc này sẽ làm tăng tổng độ trễ tối đa giữa nút trung thực đầu tiên chấp nhận khối và nút trung thực cuối cùng chấp nhận khối đó, từ δ lên 2δ+Tprove (giả sử Tprove<5s).
Tuy nhiên, tin tốt là nếu chúng ta áp dụng tính cuối cùng trong một khe duy nhất (single-slot finality), chúng ta gần như chắc chắn có thể "lập ống dẫn" (pipeline) độ trễ bổ sung này cùng với độ trễ đồng thuận nhiều vòng vốn có trong SSF. Ví dụ, trong đề xuất 4 tiểu khe này, bước "bỏ phiếu đầu khối" có thể chỉ cần kiểm tra tính hợp lệ cơ bản của khối, nhưng bước "đóng băng và xác nhận" thì cần có sự tồn tại của một chứng minh.
Mở rộng: Hỗ trợ "almost-EVMs"
Mục tiêu đáng mong muốn của chức năng ZK-EVM là hỗ trợ "almost-EVMs": các EVM có thêm chức năng. Điều này có thể bao gồm các tiền biên dịch mới, opcode mới, hợp đồng có thể dùng EVM hoặc hoàn toàn dùng một VM khác (ví dụ như trong Arbitrum Stylus), thậm chí là nhiều EVM song song giao tiếp đồng bộ với nhau.
Một số sửa đổi có thể được hỗ trợ theo cách đơn giản: chúng ta có thể định nghĩa một ngôn ngữ cho phép ZKEVMClaimTransaction truyền toàn bộ mô tả các quy tắc EVM đã sửa đổi. Điều này có thể dùng cho các trường hợp sau:
-
Bảng chi phí Gas tùy chỉnh (người dùng không được phép giảm chi phí Gas, nhưng có thể tăng chúng)
-
Vô hiệu hóa một số opcode nhất định
-
Thiết lập số khối (có nghĩa là có các quy tắc khác nhau tùy theo hard fork)
-
Thiết lập các cờ, kích hoạt bộ thay đổi EVM đã được chuẩn hóa cho việc sử dụng trên L2 nhưng không áp dụng cho L1, hoặc các thay đổi đơn giản hơn khác
Để cho phép người dùng thêm chức năng theo cách mở hơn, ví dụ như đưa vào tiền biên dịch (hoặc opcode) mới, chúng ta có thể thêm vào phần blob của ZKEVMClaimNetworkTransaction một cách để chứa bản ghi đầu vào/đầu ra của tiền biên dịch:
class PrecompileInputOutputTranscript(Container):used_precompile_addresses: List[Address]inputs_commitments: List[VersionedHash]outputs: List[Bytes]
Việc thực thi EVM sẽ được sửa đổi như sau. Một mảng tên là inputs sẽ được khởi tạo rỗng. Mỗi khi một địa chỉ trong used_precompile_addresses được gọi, chúng ta thêm vào inputs một đối tượng InputsRecord(callee_address, Gas, input_calldata), và đặt RETURNDATA của lời gọi thành outputs[i]. Cuối cùng, chúng ta kiểm tra used_precompile_addresses được gọi tổng cộng len(outputs) lần, và inputs_commitments có khớp với kết quả cam kết SSZ nối chuỗi của blob inputs hay không. Việc phơi bày inputs_commitments nhằm mục đích cho phép SNARK bên ngoài chứng minh mối quan hệ giữa inputs và outputs.
Lưu ý sự bất đối xứng giữa inputs và outputs: inputs được lưu trong dạng hash, còn outputs được lưu dưới dạng byte phải cung cấp đầy đủ. Bởi vì việc thực thi cần được thực hiện bởi các client chỉ nhìn thấy đầu vào và hiểu EVM. Việc thực thi EVM đã tự sinh ra các đầu vào, do đó chúng chỉ cần kiểm tra đầu vào sinh ra có khớp với đầu vào tuyên bố hay không, điều này chỉ cần kiểm tra hash. Tuy nhiên, outputs phải được cung cấp đầy đủ cho chúng, do đó bắt buộc phải có tính sẵn có dữ liệu.
Một chức năng hữu ích khác có thể là cho phép "giao dịch đặc quyền" được gọi từ tài khoản gửi bất kỳ. Những giao dịch này có thể chạy giữa hai giao dịch khác, hoặc bên trong một giao dịch khác (có thể cũng là đặc quyền), đồng thời gọi tiền biên dịch. Điều này có thể dùng để cho phép các cơ chế phi EVM gọi lại EVM.
Thiết kế này có thể được sửa đổi để hỗ trợ opcode mới hoặc đã sửa đổi, ngoài các tiền biên dịch mới hoặc đã sửa đổi. Ngay cả khi chỉ có tiền biên dịch, thiết kế này cũng rất mạnh mẽ. Ví dụ:
Bằng cách thiết lập used_precompile_addresses để bao gồm danh sách các địa chỉ tài khoản thông thường mà trong đối tượng tài khoản của chúng trong trạng thái có đặt một cờ nhất định, và tạo chứng minh SNARK về việc xây dựng đúng, có thể hỗ trợ chức năng giống Arbitrum Stylus, nơi hợp đồng có thể viết mã của mình trong EVM hoặc WASM (hoặc VM khác). Giao dịch đặc quyền có thể dùng để cho phép tài khoản WASM gọi lại EVM.
Bằng cách thêm kiểm tra bên ngoài để đảm bảo bản ghi đầu vào/đầu ra và giao dịch đặc quyền của nhiều lần thực thi EVM khớp đúng cách, có thể chứng minh hệ thống nhiều EVM song song giao tiếp với nhau qua kênh đồng bộ.
ZK-EVM loại 4 có thể hoạt động bằng cách có nhiều triển khai: một triển khai chuyển trực tiếp Solidity hoặc một ngôn ngữ cấp cao hơn sang VM thân thiện với SNARK, và một triển khai khác biên dịch sang mã EVM và thực thi trong ZK-EVM quy định. Triển khai thứ hai (chắc chắn chậm hơn) chỉ chạy khi bên chứng minh lỗi gửi một giao dịch tuyên bố có lỗi, và nếu họ có thể cung cấp bằng chứng rằng hai bên xử lý khác nhau, họ có thể nhận thưởng.
Có thể thực hiện VM hoàn toàn bất đồng bộ bằng cách làm tất cả lời gọi trả về 0 và ánh xạ lời gọi thành các giao dịch đặc quyền được thêm vào cuối khối.
Mở rộng: Hỗ trợ các bên chứng minh trạng thái
Thách thức của thiết kế trên là nó hoàn toàn vô trạng thái, khiến hiệu quả về dữ liệu kém. Với nén dữ liệu lý tưởng, nén có trạng thái so với chỉ nén vô trạng thái có thể làm cho việc gửi ERC20 hiệu quả về mặt không gian hơn tới 3 lần.

Hơn nữa, EVM có trạng thái không cần cung cấp dữ liệu witness. Trong cả hai trường hợp, nguyên tắc là như nhau: khi chúng ta đã biết dữ liệu sẵn có vì nó là dữ liệu được đưa vào hoặc sinh ra bởi lần thực thi EVM trước đó, thì việc yêu cầu dữ liệu sẵn có là lãng phí.
Nếu chúng ta muốn làm cho chức năng ZK-EVM có trạng thái, thì có hai lựa chọn:
Yêu cầu σpre phải rỗng, hoặc là danh sách các khóa và giá trị đã tuyên bố sẵn có dữ liệu, hoặc là σpost của một lần thực thi trước đó.
Thêm một cam kết blob cho các biên lai R được tạo bởi khối vào bộ ba (σpre, σpost, Proof). Cam kết trong blob có thể được tham chiếu trong ZKEVMClaimTransaction và truy cập trong quá trình thực thi của nó, bao gồm cam kết biểu thị khối, witness, biên lai hoặc thậm chí là giao dịch blob EIP-4844 thông thường (có thể có một số giới hạn thời gian, có thể tham chiếu qua một chuỗi lệnh: “chèn các byte N...N+k-1 của cam kết i tại vị trí j của khối + dữ liệu witness”)
(1) Ý nghĩa cơ bản là: thay vì xác lập xác minh EVM vô trạng thái, chúng ta sẽ xác lập chuỗi con EVM.
(2) Về bản chất là tạo ra một thuật toán nén có trạng thái nhỏ nhất tích hợp sẵn, sử dụng blob đã dùng hoặc tạo trước đó làm từ điển. Cả hai đều đặt gánh nặng lên các nút chứng minh, và chỉ đặt gánh nặng lên các nút chứng minh, để lưu trữ thêm thông tin;
Trong trường hợp (2), dễ dàng giới hạn thời gian cho gánh nặng này hơn, trong khi ở trường hợp (1) thì khó hơn.
Lập luận cho hệ thống chứng minh đóng nhiều bên và dữ liệu ngoài chuỗi
Hệ thống chứng minh đóng nhiều bên, trong đó có số lượng cố định các hệ thống chứng minh theo cấu trúc M-trong-N, tránh được nhiều phức tạp kể trên. Đặc biệt, hệ thống này không cần lo lắng về việc đảm bảo dữ liệu tồn tại trên chuỗi. Hơn nữa, hệ thống chứng minh đóng nhiều bên sẽ cho phép ZK-EVM chứng minh việc thực thi ngoài chuỗi; điều này làm cho nó tương thích với các giải pháp EVM Plasma.
Tuy nhiên, hệ thống chứng minh đóng nhiều bên làm tăng độ phức tạp quản trị và làm suy yếu khả năng kiểm toán, những điều này là cái giá cao cần cân nhắc so với các lợi thế nói trên.
Nếu chúng ta tích hợp ZK-EVM và làm nó thành tính năng giao thức, thì vai trò còn lại của các dự án L2 là gì?
Chức năng xác thực EVM hiện do các đội L2 tự triển khai sẽ được xử lý bởi giao thức, nhưng các dự án L2 vẫn sẽ chịu trách nhiệm về nhiều chức năng quan trọng:
-
Xác nhận trước nhanh: Tính cuối cùng trong một khe có thể làm chậm khe L1, trong khi L2 đã cung cấp dịch vụ hỗ trợ người dùng với độ trễ thấp hơn nhiều một khe thông qua xác nhận trước dựa trên bảo mật riêng của họ. Dịch vụ này sẽ tiếp tục hoàn toàn do L2 chịu trách nhiệm.
-
Chiến lược giảm thiểu MEV: Bao gồm các tính năng như mempool mã hóa, lựa chọn thứ tự dựa trên uy tín,... mà L1 không muốn triển khai.
-
Mở rộng EVM: Các dự án lớp hai có thể giới thiệu các mở rộng quan trọng cho EVM, mang lại giá trị đáng kể cho người dùng. Bao gồm cả "almost-EVMs" và các phương pháp hoàn toàn khác, ví dụ như hỗ trợ WASM của Arbitrum Stylus và ngôn ngữ thân thiện với SNARK Cairo.
-
Tiện ích cho người dùng và nhà phát triển: Các đội lớp hai nỗ lực rất nhiều để thu hút người dùng và dự án vào hệ sinh thái của họ và làm họ cảm thấy được chào đón; họ được trả công bằng cách thu thập MEV và phí tắc nghẽn trong mạng của mình. Mối quan hệ này sẽ tiếp tục tồn tại.
Chào mừng tham gia cộng đồng chính thức TechFlow
Nhóm Telegram:https://t.me/TechFlowDaily
Tài khoản Twitter chính thức:https://x.com/TechFlowPost
Tài khoản Twitter tiếng Anh:https://x.com/BlockFlow_News










