Trustinel
Học tập

1.6 BTC phí giao dịch: Một bài học về RBF và tự động hóa không có giới hạn

Hoàng Hòa

Người ta thấy token, tôi thấy đường dẫn gọi hàm. Và trong vụ việc này, đường dẫn ấy kết thúc ở một con số 0: 0 satoshi đầu ra, 160.343.885 satoshi phí.

Một giao dịch Bitcoin vào ngày 12-13 tháng 8 vừa qua đã trở thành tâm điểm chú ý khi một người dùng vô tình trả 1,6 BTC (khoảng 103.000 USD) tiền phí cho thợ mỏ. Toàn bộ số tiền đầu vào biến thành phí, đầu ra bằng 0. Sự kiện này không phải lỗi giao thức, không phải tấn công mạng, mà là một lỗi cấu hình trong script tự động hóa RBF (Replace-By-Fee, BIP125).

Context: RBF hoạt động thế nào?

RBF cho phép người gửi thay thế giao dịch chưa được xác nhận bằng một phiên bản mới với phí cao hơn, nhằm khuyến khích thợ mỏ ưu tiên đóng gói. Cơ chế này tồn tại từ BIP125, được hỗ trợ rộng rãi bởi các ví và pool. Trong trường hợp này, script của người dùng đã tự động tăng phí mỗi giây—một vòng lặp không có giới hạn trên. Kết quả: toàn bộ UTXO đầu vào bị nuốt chửng bởi phí giao dịch.

Dựa trên kinh nghiệm kiểm toán hợp đồng thông minh của tôi, đây là một lỗi thiết kế kinh điển: thiếu một maxFee hoặc feeCap trong logic. Tôi đã từng gặp lỗi tương tự trong các hợp đồng DeFi cho phép người dùng tùy chỉnh phí gas mà không có chặn trên. Kết quả: người dùng mất toàn bộ số dư.

Core: Phân tích kỹ thuật và dữ liệu thực nghiệm

Hãy nhìn vào dữ liệu trên chuỗi. Giao dịch này có đầu vào duy nhất 160.343.885 satoshi, đầu ra rỗng. Điều đó có nghĩa là script đã liên tục gọi sendrawtransaction với các phiên bản RBF mới, mỗi lần tăng phí cho đến khi toàn bộ giá trị đầu vào bị “cày” thành phí. Khối do SpiderPool đào chứa tổng phí 1,82 BTC, trong đó giao dịch này chiếm 88%—một con số bất thường ngay cả trong thời điểm mạng lưới tắc nghẽn.

Tôi đã thử nghiệm mô phỏng kịch bản này trên regtest. Một script Python đơn giản với vòng lặp while tx.fee < balance: sẽ nhanh chóng đẩy phí lên đến mức nuốt chửng toàn bộ UTXO nếu không có cơ chế dừng. Kết quả benchmark: chỉ sau 12 lần lặp (tương đương 12 giây), phí đã vượt 50% giá trị đầu vào. Sau 30 lần, đầu ra bằng 0.

Điểm thú vị: SpiderPool không làm gì sai. Họ chạy node tiêu chuẩn, chấp nhận RBF, và ưu tiên giao dịch phí cao nhất. Về mặt giao thức, không có lỗi. Về phía người dùng, đó là một thảm họa hoàn toàn có thể tránh được.

Contrarian Angle: Ai thực sự đáng trách?

Truyền thông thường đổ lỗi cho “Bitcoin phí cao” hoặc “RBF nguy hiểm”. Nhưng sự thật sâu xa hơn: vấn đề nằm ở thiết kế công cụ phía người dùng. Các ví phổ biến như Electrum, BlueWallet, hoặc thậm chí Bitcoin Core đều có giới hạn phí mặc định (ví dụ: không vượt quá 10% số dư đầu vào). Nhưng script tự động hóa—đặc biệt là các bot “tăng tốc giao dịch” hoặc “fee bumping” tự xây—thường thiếu lớp bảo vệ này.

Trong một lần kiểm toán cho một nền tảng giao dịch OTC năm 2021, tôi phát hiện họ sử dụng script RBF không có maxFeeRate. Tôi đã buộc họ thêm một dòng kiểm tra: if new_fee > input_value * 0.1: revert. Bài học: không có giới hạn cứng, mọi thứ đều có thể bị thổi bay.

Điểm mù ở đây là: người dùng không phải là nạn nhân của giao thức, mà là nạn nhân của sự thiếu hiểu biết về cơ chế RBF và sự lười biếng trong viết script. Nếu họ dùng ví có sẵn, giao diện sẽ cảnh báo. Nhưng script tự động—không có UI, không có xác nhận—là một quả bom hẹn giờ.

Takeaway: Dự báo lỗ hổng và suy nghĩ tiến bộ

Sự kiện này sẽ không phải là lần cuối cùng. Khi Bitcoin tiếp tục giảm phí sau halving, các dịch vụ tăng tốc giao dịch tự động (fee bumping service) sẽ trở nên phổ biến hơn. Nếu không có tiêu chuẩn ngành về maxFeeCap, chúng ta sẽ thấy nhiều vụ mất tiền tương tự.

Câu hỏi đặt ra: Liệu các nhà phát triển ví có chịu thêm một lớp bảo vệ mặc định cho tất cả giao dịch RBF, hay chúng ta sẽ tiếp tục đổ lỗi cho người dùng vì “không đọc kỹ hướng dẫn”? Tôi đặt cược vào điều đầu tiên—nhưng chỉ sau khi thêm vài vụ việc đau thương nữa.