Giới thiệu: Merkel hóa mã byte EVM
Lưu ý của biên tập viên: Bài viết này đến từUnitimes(ID:Uni-times)Lưu ý của biên tập viên: Bài viết này đến từ
Tóm tắt: Một khách hàng không trạng thái cần gửi mã hợp đồng thông minh được gọi trong khối như một phần của nhân chứng khối. Mã hợp đồng là yếu tố đóng góp lớn thứ hai cho chi phí băng thông khối không trạng thái. Hợp nhất hóa mã được cho là giúp giảm chi phí này. Bài viết này giải thích chi tiết cách chúng tôi chia mã hợp đồng thành các khối, Hợp nhất hóa các khối này (lưu ý của tác giả: đề cập đến việc làm cho các khối này tạo thành cây Merkle) và chỉ truyền các khối cần thiết để thực hiện giao dịch. Dựa trên các thử nghiệm được thực hiện với các khối mạng chính gần đây, chúng ta có thể thấy rằng phương pháp này giúp tiết kiệm tổng cộng 40-60% chuyển mã.
tiêu đề phụ
Khối không trạng thái lớn
Theo mô hình không trạng thái, (ít nhất một số) nút không cần lưu trữ trạng thái và dựa vào các nút khác (chẳng hạn như công cụ khai thác) để đóng gói trong các khối tất cả trạng thái cần thiết (bao gồm mã hợp đồng) và bằng chứng Merkle chứng minh tính hợp lệ của các trạng thái này. Điều này có nghĩa là băng thông mạng lớn hơn nhiều so với trước đây. Alexey Akhunov và nhóm turbo-geth[5] đã thực hiện các thử nghiệm để đo kích thước nhân chứng khối của các khối mạng chính lịch sử. Dưới đây là các phép đo cho 50.000 khối cuối cùng. Đường màu đỏ theo dõi số lượng mã hợp đồng cần được gửi trong một khối không trạng thái, đây là nguồn kích thước nhân chứng khối lớn thứ hai. Nếu Ethereum di chuyển từ trie hex hiện tại sang trie nhị phân, thì phần băm của những nhân chứng này sẽ giảm ~3 lần, khiến mã hợp đồng trở thành nguồn kích thước nhân chứng chính.
Dữ liệu từ github[6]. Biểu đồ hiển thị thành phần nhân chứng khối không trạng thái cho 50.000 khối mainnet gần đây. Các giá trị này đang di chuyển trung bình trên một cửa sổ gồm 128 khối.
tiêu đề phụ
Không cần gửi mã đầy đủ
Để xem chính xác cách thức hoạt động của nó, hãy tưởng tượng một hợp đồng mới đang được triển khai. Chúng tôi quét mã hợp đồng và xác định khối cơ bản [7] (xem thuật toán [8]) (ghi chú của tác giả, một khối cơ bản có thể được hiểu là một đoạn mã được thực thi tuần tự). Lưu ý rằng khách hàng chỉ cần quét mã một lần để phân tích JUMPDEST, do đó không có chi phí cao nào được đưa vào. Các khối cơ bản này có hai đặc điểm:
Mô tả hình ảnh
Một khối cơ bản của bytecode tưởng tượng
Mỗi khối cơ bản bắt đầu tại chỉ số 0 hoặc tại JUMPDEST. Điều này là để cho phép các máy khách phi trạng thái thực hiện phân tích JUMPDEST một cách an toàn (thêm về điều này sau).
Mỗi khối cơ bản không thay đổi luồng điều khiển (ví dụ: không có JUMP). Vì vậy, chúng tôi có thể chắc chắn rằng một khi chúng tôi bắt đầu thực hiện một khối cơ bản, nó sẽ chạy đến cuối hoặc sẽ hết gas. Chúng tôi cho rằng giải pháp này sẽ hiệu quả hơn nhưng chưa thử nghiệm các giải pháp thay thế để so sánh.
Để đạt hiệu quả, các khối cơ bản liền kề được hợp nhất cho đến khi mỗi khối cơ bản có độ dài tối thiểu là 128 byte (đây là tham số có thể định cấu hình). Sau đó, chúng được chèn vào trie, sử dụng chỉ mục của byte đầu tiên làm khóa. Cuối cùng, khách hàng lưu trữ gốc của bộ ba này trong tài khoản mới được tạo để ghi lại hợp đồng. Như được hiển thị bên dưới, mã trie thực sự trở thành một cây con của trie trạng thái (tương tự như trie lưu trữ).
Hãy kiểm tra điều này bằng cách gửi một giao dịch gọi là hợp đồng. Những người khai thác thực hiện các giao dịch và đánh dấu các khối được chạm vào trong quá trình thực hiện (khối 1 và 3 trong trường hợp này). Khi xuất bản một khối, công cụ khai thác sẽ bao gồm bằng chứng về trạng thái của tài khoản hợp đồng và bằng chứng turbo về việc chạm vào khối mã [9].
Mô tả hình ảnh
Sau khi nhận được khối, máy khách không trạng thái có thể xác minh rằng hợp đồng là một phần của trạng thái và có các thuộc tính chính xác: số dư, giá trị nonce, gốc trạng thái và gốc mã. Sau đó, nó có thể xác thực khối mã và khóa của nó đối với gốc mã. Thông tin trên đủ để máy khách tái tạo lại một phần mã byte từ các khối này và để trống các khối khác. Điều đáng chú ý là theo thuật toán tách khối mà chúng tôi sử dụng, khách hàng biết rằng mọi khối (ngoại trừ khối đầu tiên) đều bắt đầu bằng JUMPDEST, vì vậy nó có thể thực hiện bước nhảy một cách an toàn.
tiêu đề phụ
cuộc thí nghiệm
cuộc thí nghiệm
tiêu đề phụ
đi đâu
đi đâu
Như bạn có thể nhớ lại, độ dài tối thiểu của mỗi khối là một tham số có thể định cấu hình (đặt nó thành 128 byte ở trên). Việc sửa đổi tham số này có hai tác động trái ngược nhau đối với kích thước của nhân chứng khối. Ví dụ: giảm xuống 32 byte làm cho độ chi tiết của khối tốt hơn, do đó giảm tổng lượng mã cần gửi. Nhưng đồng thời, độ sâu của cây trie cũng tăng lên, điều này cuối cùng dẫn đến sự gia tăng số lượng hàm băm cần thiết để chứng minh. Bước tiếp theo sẽ là tiến hành phân tích kỹ lưỡng hơn về cài đặt kích thước khối tối thiểu để xem liệu có giá trị hiệu quả nhất về không gian hay không. Bất kể giá trị của kích thước khối tối thiểu là bao nhiêu, việc chuyển từ bộ ba thập lục phân sang bộ ba nhị phân sẽ giảm hàm băm cần thiết cho bằng chứng xuống 1/4 (xem tại đây [11]), tiếp tục giảm kích thước của khối chứng kiến.
Đối với nguyên mẫu này, chúng tôi đã chọn chia mã thành các khối cơ bản, nhưng vẫn tồn tại nhiều thuật toán phân tách khác, một số đơn giản hơn và một số phức tạp hơn. Cách đơn giản nhất là chia mã thành các khối có kích thước cố định (chẳng hạn cứ 32 byte cho một khối). Hiện tại, các vấn đề duy nhất với giải pháp này xoay quanh dữ liệu PUSH và phân tích JUMPDEST.
Mở rộng trên cơ sở này: nếu chúng ta phân tách mã byte ở các ranh giới tùy ý, các toán hạng của opcode PUSH và các opcode multibyte khác được giới thiệu trong tương lai có thể bị nhầm thành JUMPDEST (0x5b) bởi các máy khách nhận khối. Như được hiển thị bên dưới, một máy khách có mã hoàn chỉnh có thể biết rằng JUMP không hợp lệ (vì 0x5b là toán hạng của PUSH1) và dừng thực thi. Tuy nhiên, một khách hàng nhận được khối 6 và 8 chứ không phải khối 7 sẽ nhảy đến vị trí 41, phân tích cú pháp hợp đồng theo cách khác. Chúng tôi sẽ đề cập ngắn gọn các sơ đồ tránh được vấn đề này và hỗ trợ các giới hạn tùy ý sau.
Để giải quyết vấn đề này, Martin Holst Swende đã đề xuất thêm siêu dữ liệu vào mỗi khối, chỉ định có bao nhiêu byte của tiêu đề là toán hạng của PUSH. Sau đó, trình xác minh có thể bỏ qua các byte này trong quá trình phân tích JUMPDEST. Một cách khác mà Alexey đang khám phá là vô hiệu hóa các bước nhảy động trong EVM (ít nhất là đối với các hợp đồng muốn hợp nhất hóa mã của họ), cho phép chúng tôi phân tích tĩnh các bước nhảy trong một lượt tại thời điểm triển khai thay vì từng lượt trong khi thực thi mã. Alex Beregszaszi đề xuất rằng việc sử dụng các biểu đồ luồng kiểm soát hợp đồng có thể hướng dẫn quá trình Merkelization tốt hơn. Trong khi đó, Christian Reitweissner đã đề xuất một kế hoạch bằng chứng thực thi trong đó DAG Merkleized được tạo từ biểu đồ luồng kiểm soát của hợp đồng. Tôi không thể đánh giá khách quan suy nghĩ của anh ấy trong bài viết này và hy vọng anh ấy có thể giải thích thêm trong tương lai.
Các kết quả có thể chỉ cho thấy mức tăng hiệu quả không đáng kể đối với các thuật toán phân đoạn khác nhau. Trong trường hợp này, thuật toán đơn giản nhất sẽ là lựa chọn khôn ngoan nhất. Tin tốt là chúng tôi có ít nhất một thuật toán, dựa trên dữ liệu ban đầu, dường như giảm đáng kể lượng mã được truyền trong các khối không trạng thái.
Liên kết gốc:
Liên kết gốc:
Liên kết tham khảo:


