Tác giả:Suhas Daftuar
Bài viết gốc được xuất bản vào tháng 2 năm 2019.
bản tóm tắt
Block Header Bitcoin chứa cam kết đối với tập hợp các giao dịch được khối xác nhận. Điều này nhằm xây dựng Merkle trees bằng cách sử dụng ID giao dịch (giá trị băm của lần phép tính SHA256 liên tiếp của giao dịch), sau đó Điều này đạt được bằng cách đưa vào. gốc cây trong Block Header . Theo đó, chúng ta có thể sử dụng nó để chứng minh cho máy trạm Bitcoin light rằng một giao dịch nhất định được xác nhận bởi một khối nhất định bằng cách cung cấp đường dẫn Merkle từ gốc cây đến giao dịch. Tuy nhiên, cấu trúc đặc biệt của trong đó Merkle trees có một số điểm yếu về bảo mật, bao gồm ít nhất hai lỗ hổng tan chảy khối ảnh hưởng đến logic đồng thuận của Bitcoin Core và tấn công vào các máy khách nhẹ (một giao dịch không hợp lệ có thể được "chứng minh" đã xuất hiện trong một khối). ) với công việc ít hơn nhiều so với việc tìm ra sự va chạm của lần phép toán băm SHA256 liên tiếp.
Lời cảm ơn
Nhiều người đã báo cáo một số vấn đề được mô tả trong bản tóm tắt này trên danh sách gửi thư của nhà phát triển bitcoin, bao gồm cả Sergio Lerner và Peter Todd. Bản tóm tắt này dựa trên các cuộc thảo luận IRC riêng của tác giả với Johnson Law và Greg Maxwell. Tôi cho rằng rằng một số quan sát được thảo luận trong Chương 3 có nguồn gốc từ Luke Dashjr.
1 bối cảnh
1.1 Xây dựng cội nguồn Merkel
Để xem xét, cấu trúc gốc Merkle được Bitcoin sử dụng bắt đầu bằng cách thực hiện lần thao tác SHA256 liên tiếp (double-SHA256) trên mỗi giao dịch [1] để thu được giá trị băm $H$ dưới dạng một chiếc lá trên cây. Đối với mỗi cặp lá liên tiếp, chúng tôi ghép các lá và thực hiện lần phép băm SHA256 liên tiếp trên các lá và sử dụng giá trị băm thu được làm nút lớn của cặp lá. Điều quan trọng là nếu có số lượng nút lẻ ở một mức nhất định trong cây thì phần tử cuối cùng sẽ được sao chép trước, do đó nút lớn sẽ là giá trị băm của phần tử tự sao chép và ghép nối với nhau. Ví dụ: nếu có ba giao dịch trong một khối, Merkle trees sẽ trông như thế này:
Ở đây, Node1 được tính bằng cách sử dụng H(H(Tx1)||H(Tx2))
, trong khi Node2 được tính bằng cách sử dụng H(H(Tx3)||H(Tx3))
. Cuối cùng, gốc Merkle được tính bằng cách sử dụng H(Node1||Node2)
và gốc Merkle này sẽ xuất hiện trong Block Header.
Nếu chỉ có một giao dịch trong một khối thì gốc Merkle sẽ là hàm băm của giao dịch đó. Lưu ý rằng mỗi khối hợp lệ phải chứa ít nhất một giao dịch.
1.2 Hiệu lực khối trong Bitcoin Core
Logic đồng thuận của Bitcoin Core chia việc xác minh khối thành nhiều phần và theo dõi tính hợp lệ của một khối thông qua tất cả các giai đoạn này. Ví dụ: khi xử lý Block Header mới (thường là trước khi nhận khối), Block Header sẽ được kiểm tra tính hợp lệ theo quy tắc đồng thuận của mạng. Sau đó, khi khối đến, khối cũng được xử lý theo từng giai đoạn, đầu tiên chạy kiểm tra không ngữ cảnh (không phụ thuộc vào bất kỳ khối và Block Header nào khác), sau đó tùy thuộc vào vị trí của khối . Chuỗi Block Header và cuối cùng là kiểm tra các giao dịch và chữ ký của chúng, đồng thời kiểm tra xem khối có thuộc Chuỗi Block Header có nhiều công việc nhất hay không.
Mỗi Block Header được lưu trữ có một giá trị bộ đệm liên quan để theo dõi số lượng xác minh mà khối liên quan đã hoàn thành. Nếu một khối được phát hiện là không hợp lệ, Bitcoin Core sẽ lưu trữ vĩnh viễn trạng thái không hợp lệ của khối đó và tránh xử lý lại khối đó cũng như các khối tiếp theo của nó.
Trong chương tiếp theo, chúng tôi thảo luận về những lo ngại xung quanh đánh dấu vĩnh viễn các khối không hợp lệ này để ngăn chặn kẻ tấn công sử dụng tính năng tối ưu hóa này để phân chia mạng.
2 Sao chép giao dịch, CVE-2012-2459
Điều này được viết bằng mã nguồn Bitcoin Core:
警告!如果你是为学习密码学以及/或者设计一种将要使用默克尔树的新系统,请记住,下面的默克尔树算法有一个跟交易id 重合相关的严重错误,最终会产生漏洞(CVE-2012-2456)。原因在于,如果某个时刻,在列表中的哈希值的数量是奇数,则最后一个哈希值会被复制,以计算下一层(这在默克尔树中是不常见的设计)。这导致交易的特定排序会产生相同的默克尔根。举个例子,这两棵树: AA / \ / \ BCBC / \ | / \ / \ DEFDEEF/ \ / \ / \ / \ / \ / \ / \1 2 3 4 5 6 1 2 3 4 5 6 5 6交易列表[1, 2, 3, 4, 5, 6] 跟[1, 2, 3, 4, 5, 6, 5, 6](5 和6 被重复了)会得出相同的哈希值A(因为(F) 和(F, F) 的哈希值都是C)。漏洞在于,你可以发送一个带有重复交易列表的区块,它跟原版区块有相同的默克尔根值、相同的区块哈希值,但却无法通过验证。然而,如果接收节点将这个区块标记为永久无效的,就不再能接收同一区块没有篡改过(因此可能是有效)的版本。我们通过检测这种情形来防止这种误伤:检测会在列表末尾哈希两个完全相同的哈希值的行为,并跟具有无效默克尔根的区块采取相同的处理措施。假设没有double-SHA256 的碰撞,这将检查出所有已知的改变交易而不影响默克尔根的方法。
Trong phần tiếp theo, chúng ta thảo luận về một loại khả năng tan chảy khối mới chưa được phát hiện tại thời điểm ghi chú trên được viết.
3 điểm yếu do sự mơ hồ Merkle trees
Greg Maxwell đã chỉ ra (trong giao tiếp riêng tư của IRC) rằng điểm yếu bắt nguồn từ việc "thiếu sự phân tách miền giữa các lá và nút " Merkle trees . Nút không phải lá Merkle trees là hàm băm của đầu vào 64 byte (nối nút con của nó). Đồng thời, nút lá là giá trị băm của một giao dịch (dạng tuần tự hóa không có nhân chứng). Nếu dạng giao dịch được tuần tự hóa (không có dữ liệu nhân chứng) có thể là 64 byte thì không thể phân biệt nút lá với nút không phải lá, điều này có thể làm lộ ra lỗ hổng bảo mật.
3.1 Khả năng tan chảy của khối
Hãy xem xét một khối $B$ với 2 giao dịch. Giá trị gốc Merkle của khối B như sau:
Bây giờ hãy tưởng tượng một khối chỉ có 1 giao dịch. Khi đó gốc Merkel sẽ là H(Tx1)
.
Giả sử một nút hàng chuyển tiếp Block Header của $B$ và tuyên bố rằng $B$ chỉ có một giao dịch chứ không phải hai và hình thức giao dịch được tuần tự hóa $T$ trong khối chính xác là H(Tx1)||H(Tx2)
. Nếu T có thể được giải tuần tự hóa thành công thành một giao dịch [2] (và thực sự được tuần tự hóa lại thành H(Tx1)||H(Tx2)
), thì giá trị băm của $T$ sẽ giống với giá trị băm trong Block Header. Giá trị gốc Merkle khớp. Nếu T không hợp lệ thì nút nhận phiên bản khối $B$ này sẽ từ chối khối và coi nó là khối không hợp lệ. Tuy nhiên, nếu nút nhận đánh dấu vĩnh viễn hàm băm khối là không hợp lệ, nó sẽ không thể xử lý và chấp nhận khối $B$ thực sự hợp lệ nữa, ngay cả khi nút trung thực đã truyền hai giao dịch hợp lệ. Điều này có thể được sử dụng để loại bỏ một nút ra khỏi sự đồng thuận.
Cuộc tấn công này có thể được khái quát hóa. Trong một khối có giao dịch $N$, kẻ tấn công tuyên bố rằng khối thực sự có N/ 2k giao dịch, tất cả đều là "giao dịch" 64 byte. Giá trị băm của chúng là nút ở hàng thứ k. của cây ban đầu. Nếu tất cả các giá trị 64 byte này có thể được giải tuần tự hóa thành công thành các giao dịch (và do đó có thể được truyền đạt), thì nút nút khối sẽ không đánh dấu vĩnh viễn giá trị băm là không hợp lệ, ngay cả khi các giá trị 64 byte này Phần giao dịch không hợp lệ .
**3.1.1 Trả giá bao nhiêu công việc để tạo ra một khối 2 giao dịch như vậy sao cho hình ảnh ban đầu của gốc Merkel có thể được giải tuần tự hóa thành một giao dịch? **
Các giao dịch được tuần tự hóa như thế này:
[version][vin][vout][locktime]
Số phiên bản và thời gian khóa đều là các trường dài 4 byte và không có yêu cầu giải tuần tự hóa. Và $vin$ (đầu vào giao dịch) và $vout$ (đầu ra giao dịch) được tuần tự hóa như thế này:
[|vin|][vin0]...[vinn][|vout|][vout0]...[voutn]
Kích thước của $vin$ được mã hóa bằng cách sử dụng “khối lượng dày đặc” của Bitcoin. Bởi vì mỗi $vin$ chứa hàm băm 32 byte của giao dịch trước đó và chúng tôi muốn tạo một giao dịch 64 byte có thể được giải tuần tự hóa thành công thành một giao dịch, nên chúng tôi có thể giới hạn |vin|
thành 1, chỉ một byte ( 0x01
) có thể được mã hóa. Mỗi $vin_i$ bao gồm các trường sau:
[hash][index][scriptSig][sequence]
Trong đó hash
là giá trị băm của giao dịch đặt hàng trước 32 byte và index
là số thứ tự dài 4 byte, được lập chỉ mục cho vectơ $vout$ của giao dịch được chỉ định bởi hash
. Giao dịch coinbase hợp lệ phải bao gồm hàm băm giao dịch trống trước đó và số chỉ mục được đặt thành Oxffffffff
, nhưng giao dịch coinbase không hợp lệ sẽ không bị hạn chế bởi các giá trị này.
scriptsig
sẽ mã hóa độ dài tập lệnh cộng với nội dung của tập lệnh, do đó có một ràng buộc: độ dài phải khớp với số byte được đọc. Hiện tại, chúng ta có thể giả sử $scriptSig$ trống, chỉ dài 1 byte và được mã hóa là 0x00
.
sequence
là trường dài 4 byte không có ràng buộc.
Mảng $vout$ cũng sẽ được mã hóa cùng với độ dài. Để việc tuần tự hóa có hiệu quả, quy tắc này cũng phải được tuân theo. Vì vậy, chúng tôi cũng giới hạn âm lượng của $vout$ thành 1, điều này sẽ giới thiệu thêm một byte cố định 0x01
. Vout vout còn lại sẽ được tuần tự hóa như thế này:
[amount][scriptPubKey]
amount
là trường dài 8 byte biểu thị số lượng và scriptPubKey
, giống như scriptSig
, có mã hóa độ dài nên ít nhất là 1 byte.
Tóm lại, một giao dịch 64 byte có thể được giải tuần tự hóa thành công có thể được xây dựng như sau:
A = số phiên bản (4 byte, không giới hạn)
B = số lượng vins (1 byte, bị ràng buộc)
C = id giao dịch đặt hàng trước (32 byte, không có ràng buộc)
D = số chỉ mục đầu ra đặt hàng trước (4 byte, không bị giới hạn)
E = chữ ký tập lệnh (1 byte, bị ràng buộc)
F = chuỗi (4 byte, không bị giới hạn)
G = số vout (1 byte, bị ràng buộc)
H = số lượng (8 byte, không có ràng buộc)
I = độ dài của khóa chung của tập lệnh (1 byte, bị ràng buộc)
J = phần còn lại của khóa chung của tập lệnh (4 byte, không bị giới hạn)
K = thời gian khóa (4 byte, không bị giới hạn)
Ở đây, chúng tôi đặt $scriptPubKey$ trong $vout_0$ thành tổng cộng 5 byte, do đó giao dịch dài 64 byte và quá trình giải tuần tự hóa thành công bị hạn chế chỉ ở những byte được đề cập ở trên (mã hóa độ dài). Nhưng nhìn tổng thể, chúng ta có thể thấy rằng chúng ta chỉ cần tổng độ dài của $scriptPubKey$ và $scriptSig$ là 4 byte.
Cũng lưu ý rằng chỉ có 4 trong số 64 byte bị hạn chế và tất cả chúng đều xuất hiện ở các nửa khác nhau. Vì vậy, để tạo ra tiền đề của gốc Merkle có thể được giải tuần tự hóa một cách hiệu quả thành Block Header cho giao dịch 64 byte, người ta chỉ cần tìm kiếm 8 bit để tìm giao dịch coinbase có thể sử dụng được (sẽ băm thành 32 byte), cộng với khoảng 22 bit tìm kiếm ((1/5) * 2 24 , ít hơn 22 byte một chút) để tìm giao dịch thứ hai có hàm băm là Nút 32 byte thứ hai - Rất ít nỗ lực tính toán.
(Lưu ý của người dịch: Điều này có nghĩa là bạn cần tìm một giá trị 64 byte có thể được giải tuần tự hóa thành một giao dịch; và 32 byte đầu tiên của nó chính xác là giá trị băm của một giao dịch coinbase. value và 32 byte tiếp theo chính xác là giá trị băm của một giao dịch khác cũng có thể nói rằng bạn cần tìm sự kết hợp giữa giao dịch coinbase + giao dịch thông thường và việc ghép các giá trị băm của chúng chỉ có thể được giải tuần tự hóa cho một giao dịch).
3.1.2 Cần bao nhiêu công việc để tạo ra một khối có nút trong một hàng nhất định của Merkle trees đều có thể được giải tuần tự hóa thành các giao dịch hợp lệ?
Lưu ý rằng giao dịch đầu tiên của một khối phải là giao dịch coinbase và như đã đề cập trước đó, điều này hạn chế phần lớn 32 byte đầu tiên đại diện cho giao dịch đầu tiên: chỉ số phiên bản 4 byte là không bị ràng buộc. Do đó, bạn cần tìm kiếm ít nhất 28*8 = 224 bit để tìm nửa đầu của nút đầu tiên của một hàng nhất định trong cây sẽ khớp với giao dịch coinbase, sau đó tiếp tục tìm kiếm để tìm nửa sau khớp với giao dịch coinbase. coinbase khớp với một giao dịch có ý nghĩa nào đó (điều này dễ dàng hơn nhiều, chỉ có khoảng 16 byte bị hạn chế, do đó chỉ cần tìm kiếm 128 bit để tìm xung đột). Tất nhiên, người ta có thể sử dụng bất kỳ hàng nào Merkle trees, nhưng rõ ràng điều này không khả thi về mặt tính toán.
3.2 Tấn công vào máy khách SPV (nhẹ)
Máy trạm SPV dự kiến sẽ nhận được bằng chứng cho thấy giao dịch xuất hiện trong một khối. Bản chất của bằng chứng này là cung cấp cho máy trạm một đường đi xuyên qua Merkle trees, từ gốc cây cho đến giao dịch.
Xuống Merkle trees Tuy nhiên, giả sử một giao dịch 64 byte (hợp lệ) $T$ được bao gồm trong một khối và 32 byte sau (ít bị ràng buộc hơn 32 byte trước đó) được xây dựng cẩn thận để va chạm với các giao dịch giả và không hợp lệ khác. giao dịch F Gọi $R$ là giá trị gốc của Merkel, khi đó ta có:
R = H(H(H(...H(T)||H(...)...)T = [32bytes]||[H(F)]
Nếu một giao dịch như vậy có thể được xây dựng thì một nút có thể đánh lừa máy trạm SPV tin rằng $F$ nằm trong khối này - bởi vì nó có thể cung cấp merkle từ gốc merkle đến đường dẫn $T$ el, sau đó diễn giải $T$ như một nút bên trong (chứ không phải là nút lá). Vì không thể nhìn thấy số lượng giao dịch trong một khối trong Block Header nên máy trạm SPV không thể biết số này trước và do đó không thể biết độ sâu chính xác của cây.
3.2.1 Cần bao nhiêu công việc tạo ra một giao dịch 64 byte hợp lệ sao cho 32 byte tiếp theo va chạm với giá trị băm của giao dịch khác?
Lưu ý rằng Sergio Lerner đã xuất bản một phân tích chuyên biệt cho biết rằng nó có thể được thực hiện bằng tìm kiếm 72-bit; Peter Todd cũng đã xuất bản một phân tích khẳng định rằng nó có thể được thực hiện bằng tìm kiếm 60-bit.
Từ sơ đồ trên, chúng ta có thể biết rằng 32 byte đầu tiên của giao dịch bị hạn chế hơn vì nó chứa nhiều đầu ra của đơn đặt hàng trước đã chi tiêu, phải hợp lệ (nếu không thì giao dịch không hợp lệ). Vì vậy, chúng tôi tập trung vào 32 byte cuối cùng:
C = ID giao dịch trước trình tự (5 byte còn lại của id giao dịch trước trình tự, không bị ràng buộc)
D = Số chỉ mục đầu ra mở đầu (4 byte, ràng buộc 21 bit)
E = scriptSig (1 byte, bị ràng buộc)
F = chuỗi (4 byte, nếu số phiên bản giao dịch là 1 thì không có ràng buộc)
G = số lượng đầu ra giao dịch (1 byte, bị ràng buộc)
H = số lượng (8 byte, khoảng 33 byte bị hạn chế, xem bên dưới)
I = độ dài của scriptPubKey (1 byte, bị ràng buộc)
J = phần còn lại của scriptPubKey (4 byte, không bị ràng buộc)
K = thời gian khóa (4 byte, ~29 bit không bị giới hạn, xem bên dưới)
Chúng ta có thể giả định rằng các bit còn lại của ID giao dịch trước đó không bị ràng buộc, bởi vì khi chúng ta tìm thấy một giao dịch ứng viên, chúng ta có thể thực hiện tìm kiếm 40 bit chuyên dụng để tìm một giao dịch có 5 bit cuối cùng của ID giao dịch trước đó khớp với đầu vào mà chúng ta yêu cầu . Tương tự, chúng ta có thể hạn chế một phần số chỉ mục đầu ra đặt hàng trước, chỉ cần yêu cầu nó không lớn hơn (giả định) 2048, vì chúng ta có thể giả định rằng chúng ta có khả năng tạo một giao dịch với 2048 đầu ra và các vị trí đầu ra thích hợp có lượng giao dịch phù hợp.
Chúng ta có thể giả định rằng $sequence$ không bị ràng buộc vì trường này không có ý nghĩa đồng thuận đối với các giao dịch phiên bản 1. Vì chúng tôi giả định rằng 32 byte đầu tiên của giao dịch là cố định nên chúng tôi giả định rằng số phiên bản là 1.
Và $amount$ là trường 8 byte. Nếu kẻ tấn công có thể nhận được nhiều tiền thì sẽ có nhiều bit không bị ràng buộc hơn vì ràng buộc đồng thuận là giá trị của đầu ra phải nhỏ hơn hoặc bằng giá trị của đầu vào. Tuy nhiên, vì bất kỳ ai cũng có thể sử dụng số tiền đầu vào cho một giao dịch như vậy (hoặc không ai có thể chi tiêu), nên số tiền được sử dụng trong cuộc tấn công như vậy có thể không được phục hồi (nếu kẻ tấn công cũng là một thợ đào thì điều đó có thể không thực hiện được) . Một nỗ lực được thực hiện để thu hồi tiền bằng cách chi tiêu lại cùng một khối, mặc dù thợ đào khác có thể tách khối đó ra, do đó đánh cắp phí và kết quả đầu ra của kẻ tấn công mà bất kỳ ai cũng có thể chi tiêu). Và, miễn là chúng tôi có thể mất tiền, chúng tôi phải xem xét các cuộc tấn công khác có thể thực hiện với cùng mức chi phí, chẳng hạn như khai thác một số lượng nhỏ các khối không hợp lệ và sử dụng các khối này để tấn công máy trạm yếu (lưu ý rằng mặc dù bản chất của các khối này các cuộc tấn công không giống nhau, Bởi vì cuộc tấn công này có thể đánh lừa máy trạm nhẹ tin rằng một giao dịch giả mạo đã được xác nhận bởi bất kỳ số khối nào - điều này có thể có giá trị hơn việc khai thác một số lượng nhỏ khối giả, vì các khối giả không có sự nhượng bộ như vậy. Khả năng giao dịch mục tiêu nhận được xác nhận ở bất kỳ số khối nào).
Để thảo luận, chúng ta hãy đặt đại khái chi phí mà kẻ tấn công sẵn sàng chịu là 25 BTC, hiện có giá trị bằng 2 phần thưởng khối. Tại thời điểm này, số lượng bit bị ràng buộc là 33. (Nếu chúng tôi giả định rằng kẻ tấn công sẵn sàng rủi ro 687 BTC thì số lượng tìm kiếm cần thiết giảm 5 bit).
$locktime$ là số nguyên 4 byte. Nếu vượt quá 5 0000 0000, nó sẽ được hiểu là thời gian Unix; nếu nhỏ hơn giá trị này, nó sẽ được hiểu là Block Height. Thời gian hiện tại là khoảng 1,4 tỷ giây kể từ thời điểm đó, vì vậy chúng tôi ước tính có 900 triệu giá trị thời gian khóa hợp lệ, tức là khoảng 29 bit tự do.
Tóm lại, chúng ta có 81 bit bị hạn chế, nghĩa là kẻ tấn công có thể chạy tìm kiếm 81 bit (cộng thêm 40 bit để xây dựng giao dịch cấp vốn cung cấp tiền mà bất kỳ ai cũng có thể chi tiêu), Bạn có thể sử dụng phương pháp này để đánh lừa light node SPV. (Lưu ý: Con số này nhỏ hơn nhiều so với 128 bit mà chúng tôi mong đợi để tìm kiếm hai giao dịch có cùng hàm băm.)
4 Tính dễ bị tổn thương và biện pháp giảm thiểu
4.1 Khả năng tan chảy của khối
Rủi ro chia tách đồng thuận do khả năng tan chảy của khối bắt nguồn từ logic xử lý xung quanh các khối không hợp lệ. Như đã đề cập trong các nhận xét về mã Bitcoin Core ở trên, chúng tôi đã nhận ra rằng miễn là khối đang được xử lý có thể bị tan chảy thì logic đồng thuận không được đánh dấu vĩnh viễn bất kỳ Block Header là không hợp lệ: miễn là một tiêu đề khối nhất định tương ứng với cùng một Block Header Khối có thể hợp lệ và việc vô hiệu hóa vĩnh viễn Block Header có thể gây ra sự chia rẽ đồng thuận.
Sao chép giao dịch Sự cố sao chép giao dịch đã được khắc phục kể từ phiên bản Bitcoin-Qt 0.6.1. Vào thời điểm đó (và bây giờ) có một bộ kiểm tra để nhập khối (được thực hiện trong một hàm có tên CheckBlock()
) và nếu kiểm tra không thành công, khối sẽ không được lưu trữ - và lỗi kiểm tra không được phát hiện vĩnh viễn. Một biện pháp kiểm tra mới cho các giao dịch được sao chép cũng đã được thêm vào bộ kiểm tra này để giải quyết vấn đề.
Một cách kiểm tra khác Merkle trees, cũng được thực hiện trong CheckBlock()
có liên quan đến giao dịch coinbase: nếu giao dịch đầu tiên trong một khối không có cấu trúc sàn giao dịch- đầu vào, giao dịch trước đó của nó. tất cả đều bằng 0 và số chỉ mục đều bằng 1 - khi đó khối này cũng sẽ không xác minh được. Một tác dụng phụ của việc kiểm tra này là về cơ bản nó ngăn chặn sự cố trước khi chúng ta biết về khả năng tan chảy của khối được thảo luận trong Phần 3.1 - như đã đề cập trước đó, nó yêu cầu kẻ tấn công phải tìm kiếm số lượng ít nhất 224 bit để tạo ra khối nóng chảy có thể. vượt qua kiểm tra giao dịch coinbase.
Kể từ Bitcoin Core 0.13.0, việc triển khai xử lý khả năng tan chảy của khối đã thay đổi, do đó, khả năng tan chảy Merkle trees có thể được kiểm tra trong CheckBlock()
và thẻ sẽ theo dõi xem khối có bị tan chảy hay không. Thẻ này sẽ được đưa vào logic xác định xem khối này có nên bị vô hiệu hóa vĩnh viễn hay không. Nhưng CheckBlock()
vẫn sẽ được gọi lần: một lần với tính năng quay lại sớm khi thất bại, như đã đề cập ở trên và lần còn lại trước khi lưu trữ khối (yêu cầu vượt qua kiểm tra). Vì vậy, ngay cả khi một khối bị lỗi trong CheckBlock()
và vì những lý do khiến chúng tôi cho rằng nó phải không hợp lệ (không có khả năng là do bị tan chảy), logic của hàm sẽ không làm cho khối đó bị vô hiệu hóa vĩnh viễn.
Vì vậy, gọi nó lần có vẻ dư thừa. Trong cam kết mã Bitcoin Core dbb89dc
, có vẻ như lệnh gọi dư thừa đã bị loại bỏ, do đó khi lỗi CheckBlock()
do khả năng tan chảy không xác định, lỗi này sẽ vô hiệu hóa vĩnh viễn khối tương ứng. Do đó, Bitcoin Core 0.13.0, 0.13.1 và 0.13.2 đều dễ bị tấn công được mô tả trong Phần 3.1.
Sau khi vấn đề được phát hiện một cách riêng tư, thay đổi đã được hủy bỏ trong cam kết mã Bitcoin Core ba803ef
, trước bản phát hành 0.14.0. Phiên bản 0.13 là phiên bản duy nhất được biết là dễ bị tấn công bởi kiểu tấn công này.
Có thể có các biện pháp giảm thiểu tiếp theo trong tương lai. Ví dụ: nếu một khối bao gồm toàn bộ các giao dịch 64 byte, nó sẽ không bao giờ được đánh dấu vĩnh viễn là khối không hợp lệ [3] hoặc, các giao dịch 64 byte có thể bị vô hiệu hóa trong sự đồng thuận. . buôn bán. Các đề xuất về các biện pháp khắc phục tức thời hơn này đã bị hoãn lại để chờ phát hiện và giảm thiểu các vấn đề mà máy trạm hạng nhẹ gặp phải (như được mô tả trong Phần 3.2).
4.2 Máy trạm nhẹ
Để bảo vệ máy trạm hạng nhẹ khỏi các cuộc tấn công được mô tả trong Chương 3.2, một số biện pháp giảm thiểu có thể được sử dụng. Bắt đầu với Bitcoin Core 0.16.1, các giao dịch 64 byte không còn có thể vào nhóm giao dịch nữa. Nếu thợ đào cũng áp dụng quy tắc này, sẽ là hợp lý khi đề xuất một thay đổi đồng thuận làm mất hiệu lực các giao dịch 64 byte, nếu được thông qua sẽ loại bỏ vĩnh viễn sự mơ hồ giữa các lá và nút bên trong Merkle trees , đồng thời cũng sẽ Bảo vệ máy trạm nhẹ hiện có (chúng không yêu cầu bất kỳ thay đổi nào) [4] .
Lưu ý rằng đã có một số lượng nhỏ giao dịch 64 byte trên blockchain Bitcoin .
Một biện pháp giảm nhẹ khác mà máy trạm hạng nhẹ có thể áp dụng là yêu cầu bằng chứng cũng chứa bằng chứng về giao dịch coinbase cũng như chính giao dịch coinbase (được sử dụng để xác định độ sâu độ sâu của Merkle trees cần thiết cho tất cả các giao dịch trong cùng một khối). Điều này sẽ yêu cầu thay đổi phần mềm máy trạm nhẹ—đặc biệt là để xác minh rằng các giao dịch coinbase đến có hình thức được xác định trước—nhưng không phải là thay đổi đồng thuận.
Sergio Lerner cũng thảo luận về các biện pháp giảm thiểu bổ sung trong báo cáo của mình.
Tham khảo
Sergio Lerner, “ Lỗ hổng nút lá trong thiết kế cây Merkle Bitcoin ,” ngày 4 tháng 8 năm 2017. https://bitslog.com/2018/06/09/leaf-node-weakness-in-bitcoin-merkle-tree-design/
Peter Todd, “ Độ sâu cây merkle đáng tin cậy để có bằng chứng đưa vào tx an Safe mà không cần fork mềm ,” ngày 7 tháng 6 năm 2018. https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2018- June/016091.html
chú thích cuối trang
1. Trong bài viết này, chúng tôi chỉ thảo luận về giá trị gốc Merkle trong Block Header , do đó giao dịch được tuần tự hóa và sau đó được băm mà không cần nhân chứng. ↩
2. Lưu ý rằng bất kỳ khối nào, dù có bị tan chảy hay không, sẽ chỉ được cho rằng khối nút nếu nó có thể được truyền đạt - nghĩa là, tin nhắn có thể được deserialized theo quy tắc xử lý tin nhắn của mạng. Những tin nhắn không thể hiểu được sẽ bị loại bỏ. ↩
3. Lưu ý rằng "64 byte" trong bài viết này đề cập đến độ dài của giao dịch sau khi xê-ri hóa mà không có nhân chứng. ↩
4. Chúng tôi bỏ qua các cuộc tấn công vào nút SPV bằng cách đi lên Merkle trees và tuyên bố rằng nút nội bộ là giao dịch quan tâm. Theo các giả định hợp lý, 116 bit công việc có thể được sử dụng để đánh lừa máy trạm nhẹ nghĩ rằng một trong các đầu ra của nó đã được sử dụng. Nếu thay đổi đồng thuận làm mất hiệu lực các giao dịch 64 byte và máy trạm nhẹ được sửa đổi để từ chối các giao dịch 64 byte thì bạn không cần phải lo lắng về vấn đề này. ↩