Bể chứa gas rò rỉ của Ethereum: Tiết lộ 13 điểm không nhất quán của mô hình gas tốn kém

Bài viết này được dịch máy
Xem bản gốc

13 điểm không nhất quán của mô hình Gas trong Ethereum

Bài viết này tóm tắt 13 điểm không nhất quán trong mô hình gas của Ethereum.
Tất cả các biểu tượng đều xuất phát từ Ethereum Yellow Paper (đặc biệt là Phụ lục G. Biểu phí).


1. Giao dịch bên ngoài không phát sinh phí tài khoản mới ( G_{newaccount} G n e w a c c o u n t ) khi tạo tài khoản, nhưng giao dịch nội bộ thì

Ví dụ
Giả sử bạn muốn có một hợp đồng C để chuyển ETH sang một tài khoản A hoàn toàn mới chưa tồn tại.

  • Nếu C chuyển trực tiếp, đường dẫn tài khoản mới nội bộ sẽ tính phí 25.000 gas ( G_{newaccount} G n e w a c c o u n t ).
  • Phương án thay thế: trước tiên gửi một giao dịch bên ngoài từ EOA đến A với 1 Wei. Giao dịch này tốn 21.000 gas theo cơ sở chuẩn. Sau đó, A tồn tại. Bây giờ, việc chuyển tiền của C sang A không còn phát sinh phí tài khoản mới nữa ( Tiết kiệm ~4.000 gas ).

Phần kết luận
Nếu bạn dựa vào hợp đồng để tạo tài khoản mới, bạn sẽ phải trả 25.000 gas.
Nhưng nếu trước tiên bạn gửi một giao dịch bên ngoài (21.000 gas) rồi để hợp đồng gửi tiền, về cơ bản bạn sẽ tiết kiệm được ~4.000 gas .

Gây ra
Đường dẫn tạo bên ngoài và bên trong sử dụng các móc tính phí khác nhau; chỉ có hợp đồng được gọi mới kích hoạt phí tài khoản mới rõ ràng.

2. Các lệnh gọi biên dịch trước đôi khi bỏ qua phí byte đầu vào giao dịch

Ví dụ
Việc gọi một hợp đồng được biên dịch trước (ví dụ: ECRECOVER ) có thể bỏ qua việc tính phí cho các byte đầu vào giao dịch. Thông thường, mỗi byte đầu vào có giá 4 gas (không) hoặc 16 gas (khác không) . Hãy xem xét hai ví dụ giao dịch thực tế:
* 1. Giao dịch 0x6b01 gọi ECRECOVER với 24.276 gas, trong đó 276 gas dành cho các byte đầu vào.
* 2. Giao dịch 0x1fb0 gọi ECRECOVER với 24.000 gas, trong đó 0 gas dành cho các byte đầu vào.
Nếu bạn đọc mã nguồn của máy khách thực thi, bạn có thể thấy giao dịch thứ hai cũng có thể thực thi ECRECOVER mà không tính phí cho các byte đầu vào. Máy khách sẽ thêm dữ liệu bằng 0 vào đầu vào để phù hợp với kích thước dự kiến.

Ghi chú thêm
Tôi đoán là bạn đủ thông minh để nhận ra rằng hai giao dịch tôi vừa đề cập đều là giao dịch bên ngoài.
Vậy tại sao họ lại viện dẫn các hợp đồng được biên dịch trước?

Tôi đoán một phần lý do là một số trình khám phá dán nhãn sai địa chỉ biên dịch trước (0x01–0x0A) thành "địa chỉ ghi", khiến người dùng càng thêm bối rối (xem Snapshot nhanh bên dưới).

địa chỉ ghi
burn_address 539×182 39,1 KB

Bên cạnh đó, việc triển khai các địa chỉ biên dịch trước trong các địa chỉ đặc biệt này (0x01–0x0A) là một thiết kế thất bại.
Đôi khi, mọi người chỉ muốn gọi trực tiếp đến những địa chỉ đặc biệt này.

Gây ra
Thiết kế địa chỉ kém của các hợp đồng được biên dịch trước và việc trình khám phá Block gây hiểu lầm dẫn đến nhầm lẫn và dán nhãn sai.

3. Các mục nhập trong danh sách truy cập sẽ bị tính phí ngay cả khi không bao giờ được truy cập (tức là, G_{accesslistaddress} G a c c e s s l i s t a d r e s s , G_{accessliststorage} G a c c e s s l i s t s t o r a g e )

Ví dụ
Đề xuất cải tiến Ethereum (EIP)-2930 giới thiệu danh sách truy cập, cho phép các giao dịch chỉ định địa chỉ và khe lưu trữ nào họ muốn truy cập. Tuy nhiên, một giao dịch có thể bao gồm địa chỉ và khe lưu trữ trong danh sách truy cập của mình nhưng không bao giờ chạm đến chúng.
Ví dụ, giao dịch 0x0dd0c thiết lập danh sách truy cập nhưng không bao giờ truy cập vào các khe cắm được chỉ định do địa chỉ.

Gây ra
Giao thức tính phí khi đưa vào để đơn giản hóa việc thực thi, bất kể các mục nhập có được sử dụng hay không. Nếu bạn tin tưởng người dùng có thể cung cấp thông tin đầu vào chính xác, thì cũng giống như bạn tin Taylor Swift là vợ mình vậy.

4. Tự chuyển vẫn tính phí chuyển gas

Ví dụ
Tài khoản A gửi ETH cho chính nó.
Không có thay đổi nào về số dư, nhưng phí vẫn bao gồm 9.000 gas ( G_{callvalue} G c a l l v a l u e ) cho việc chuyển giá trị. Theo bài đăng này từ @vbuterin .

Hai lệnh ghi tài khoản (một lệnh CALL chỉnh sửa số dư thường tốn 9000 gas)

Tại sao việc viết một tài khoản vẫn tốn 9.000 gas ? Thực ra, nếu bạn đọc mã nguồn của máy khách thực thi, bạn sẽ thấy rằng khi địa chỉ gửi và địa chỉ nhận giống nhau, máy khách sẽ không làm gì cả.

Các trường hợp trên có thể xảy ra khi giao dịch là tự chuyển tiền hoặc sử dụng CALLCODE để chuyển giá trị.

Gây ra
Phí thực hiện sẽ được áp dụng bất kể giao dịch có bị vô hiệu hay không.

5. Sự không phù hợp về giá đĩa bytecode theo hợp đồng so với Calldata

Ví dụ

  • Dữ liệu cuộc gọi Tx: 16 gas/byte (khác không) hoặc 4 gas/byte (không) .
  • Mã byte hợp đồng: 200 gas/byte .
    Cả hai đều chiếm dụng ổ đĩa, nhưng giá cả lại không nhất quán. Điều này khiến tôi rất bối rối, vì tx calldata rẻ hơn contract bytecode vì nó phải tính đến mức sử dụng ổ đĩa thực tế và chi phí mạng.

Gây ra
Lịch trình gas tách biệt “calldata” và “code deposit” mà không căn chỉnh chúng theo mức sử dụng đĩa thực tế.

6. Các giao dịch được hoàn lại sẽ được tính phí như thể chúng đã ghi vào đĩa

Ví dụ
Giao dịch hoàn nguyên sẽ sửa đổi trạng thái trong bộ nhớ nhưng không có thay đổi nào được duy trì, tuy nhiên phí ghi vẫn được áp dụng, các khoản phí gas sau đây bị ảnh hưởng:

  • 25.000 gas (tài khoản mới, G_{newaccount} G n e w a c c o u n t )
  • 9.000 gas (chuyển giá trị, G_{callvalue} G c a l l v a l u e )
  • 2.100 gas (khe lạnh, G_{coldslot} G c o l d s l o t )
  • 200 gas (mã tiền gửi, G_ { codedeposit } G c o d e d e preposit )

Chi phí thực tế chỉ dành cho bộ nhớ sẽ là ~ 100 gas .

Gây ra
Gas được tính phí trong quá trình thực thi; việc hoàn nguyên sau đó sẽ hủy các thay đổi trạng thái nhưng không hủy phí. Việc triển khai tính phí một cách thận trọng để ngăn ngừa DoS.

7. Nhiều giao dịch chuyển ETH trong một giao dịch duy nhất bị tính nhầm là giao dịch lạnh

Ví dụ
Giả sử một hợp đồng gửi ETH đến nhiều tài khoản khác nhau nhiều lần trong một giao dịch duy nhất.

  • Giao dịch chuyển tiền đầu tiên sẽ ghi đúng giá trị G_{callvalue} G call ( 9.000 gas ) vào số tài gas .
  • Các giao dịch chuyển tiền tiếp theo sang tài khoản khác trong cùng giao dịch sẽ bị tính phí truy cập ấm ( 100 gas + 4.500 gas ), nhưng đôi khi vẫn bị tính phí truy cập lạnh ( 9.000 gas ).

Gây ra
Sổ kế toán truy cập nóng/lạnh không được cập nhật liên tục cho nhiều lần chuyển giá trị trong một giao dịch duy nhất.

8. Phần thưởng cho thợ đào/người xác thực hoặc việc rút tiền không bị tính phí

Ví dụ
Các bản cập nhật số dư ở cấp độ giao thức (ví dụ: phần thưởng, rút ​​tiền) sẽ sửa đổi trạng thái trên đĩa nhưng không tốn gas .

Gây ra
Kế toán cấp hệ thống bỏ qua các thủ tục kế toán gas .

9. Lần đọc đĩa đầu tiên của SSTORE không được tính phí (theo Đề xuất cải tiến Ethereum (EIP)-2200)

Ví dụ
Khi opcode SSTORE được thực thi, trước tiên nó sẽ đọc giá trị hiện tại từ đĩa (lưu trữ hợp đồng) trước khi quyết định có nên ghi giá trị mới hay không. Theo Đề xuất cải tiến Ethereum (EIP)-2200 , nếu giá trị được lưu trữ khớp với giá trị hiện có, việc ghi đĩa sẽ không diễn ra và chỉ tính một khoản phí gas tối thiểu. Tuy nhiên, bản thân lần đọc đĩa ban đầu không bị tính phí gas — giao thức chỉ tính phí cho lần ghi tiếp theo nếu giá trị thay đổi.

Gây ra
Logic của Đề xuất cải tiến Ethereum (EIP)-2200 tập trung vào việc tính phí cho các thay đổi trạng thái, nhưng bỏ qua việc tính phí cho lần đọc đĩa luôn xảy ra trước. Điều này có nghĩa là lần truy cập đầu tiên vào khe lưu trữ sẽ miễn phí, ngay cả khi đó là đọc lạnh.

10. Tối ưu hóa việc đọc lưu trữ đã giảm I/O nhưng gas vẫn không đổi

Ví dụ
Các máy khách Ethereum đã áp dụng các tối ưu hóa lưu trữ/ Snapshot phẳng (ví dụ: cấu trúc tăng tốc Snapshot cho geth), tổ chức trạng thái dưới dạng kho lưu trữ khóa-giá trị phẳng và cho phép đọc trực tiếp đĩa, bỏ qua các nút trung gian theo yêu cầu của Merkle-Patricia Trie (MPT) cũ. Tối ưu hóa này giúp giảm đáng kể I/O đĩa cho các lần đọc Ví lạnh . Ví dụ: Geth và các máy khách khác hiện sử dụng SAS hoặc các cấu trúc tương tự, nhưng phí gas cho các truy cập lạnh — 2.600 / 2.100 / 2.400 / 1.900 gas — vẫn không đổi.

Gây ra
Hằng số gas cho truy cập lạnh ban đầu được hiệu chỉnh cho MPT, trong đó việc đọc đĩa tốn kém hơn do phải duyệt qua nhiều nút trie. Với SAS, mức tiêu thụ tài nguyên đĩa thực tế thấp hơn nhiều, nhưng giao thức chưa cập nhật phí gas tương ứng.

Giảm thiểu
Hiệu chỉnh lại hằng số gas để phản ánh lượng I/O đĩa giảm khi máy khách chuyển sang SAS hoặc các hệ thống lưu trữ được tối ưu hóa tương tự.

11. Sự không phù hợp về giá giữa SLOAD và MLOAD

Ví dụ

  • SLOAD (ấm) → 100 gas
  • MLOAD3 gas
    Cả hai đều là thiết bị đọc bộ nhớ, nhưng giá cả lại khác nhau rất nhiều.

Gây ra
Sự phân biệt cũ giữa các hoạt động trạng thái và bộ nhớ; các tối ưu hóa đã làm mờ đi khoảng cách chi phí thực tế.

12. Giao dịch nội bộ đôi khi cập nhật tài khoản mà không cần gas

Ví dụ
Khi việc cập nhật tài khoản trên đĩa diễn ra mà không tính phí gas cho các bản cập nhật đó. Cụ thể, vấn đề này phát sinh trong trường hợp người dùng gửi một giao dịch bên ngoài đến hợp đồng A, sau đó hợp đồng A lại thực hiện một lệnh gọi nội bộ đến hợp đồng B. Nếu hợp đồng B sửa đổi một khe cắm trong bộ nhớ của nó, gốc lưu trữ tương ứng trong tài khoản của hợp đồng B phải được cập nhật trên đĩa. Tuy nhiên, không tính phí gas cho bản cập nhật tài khoản B này, dẫn đến sự không nhất quán.

Gây ra
Lỗi này xảy ra do việc sửa đổi lưu trữ của hợp đồng B không phát sinh thêm phí gas khi cập nhật trạng thái tài khoản. Điều này là do giao thức không tính phí cho các bản cập nhật trạng thái tài khoản được kích hoạt bởi các giao dịch nội bộ, ngay cả khi việc ghi đĩa đã được thực hiện.

13. Mã lệnh EXT* được định giá quá thô

Ví dụ
EXTCODESIZE có thể đọc nhiều dữ liệu hơn BALANCE , nhưng cả hai đều bị tính phí tài khoản lạnh như nhau ( 2.600 gas ).

Gây ra
Giá theo mã lệnh khá thô và bỏ qua công việc biến đổi.

Ghi chú kết thúc

Vấn đề này xuất phát từ bài báo của tôi như sau, tôi chia sẻ nó theo LINK (Chainlink) này .

He, Z., Li, Z., Luo, J., Luo, F., Duan, J., Li, J., … & Zhang, X. (2025, tháng 2). Auspex: Tiết lộ những lỗi không nhất quán của cơ chế phí giao dịch trong Blockchain. Trong Kỷ yếu Hội nghị USENIX lần thứ 23 về Công nghệ Tệp và Lưu trữ.

Tôi sẽ rất vui nếu bạn có thể trích dẫn bài báo của tôi.

Tất cả những điều này nhấn mạnh nhu cầu xem xét và điều chỉnh toàn diện các cơ chế định giá gas trong giao thức Ethereum. Bằng cách giải quyết những bất cập này, chúng ta có thể đảm bảo một thị trường gas hiệu quả và công bằng hơn, phản ánh chính xác chi phí tài nguyên cơ bản của các hoạt động khác nhau.


Nguồn
Tuyên bố từ chối trách nhiệm: Nội dung trên chỉ là ý kiến của tác giả, không đại diện cho bất kỳ lập trường nào của Followin, không nhằm mục đích và sẽ không được hiểu hay hiểu là lời khuyên đầu tư từ Followin.
Thích
Thêm vào Yêu thích
Bình luận