Tác giả: willcl-ark, l0rinc, hodlinator
Nguồn: https://bitcoinmagazine.com/print/the-core-issue-outrunning-entropy-why-bitcoin-cant-stand-still
Khởi tạo tải xuống khối
Để đồng bộ hóa một nút hoàn toàn mới với trạng thái mới nhất của mạng, cần phải trải qua một số giai đoạn khác nhau:
- Khám phá nút và lựa chọn blockchain: Nút kết nối với một nhóm nút được chọn ngẫu nhiên, sau đó Chuỗi có nhiều Bằng chứng công việc nhất sẽ được xác định.
- Tải xuống Block Header: Nút truy xuất Block Header từ nút ngang hàng này, sau đó kết nối chúng để tạo thành một Chuỗi Block Header hoàn chỉnh.
- Tải xuống khối: Nút đồng thời yêu cầu các khối thuộc Chuỗi này từ nhiều nút hàng khác.
- Xác minh khối và giao dịch: Các giao dịch trong một khối sẽ chỉ được xác minh sau khi các giao dịch trong khối tiếp theo đã được xác minh.
Mặc dù quá trình xác thực khối vốn dĩ mang tính tuần tự — mỗi khối phụ thuộc vào trạng thái được tạo ra bởi khối trước đó — nhiều tác vụ ngoại vi có thể được xử lý song song. Việc đồng bộ hóa Block Header, tải xuống khối và xác minh tập lệnh đều có thể chạy độc lập trong các luồng khác nhau. Một quy trình tải xuống khối ban đầu lý tưởng nên tận dụng tối đa tất cả các hệ thống con: một luồng mạng tải xuống dữ liệu, một luồng xác minh kiểm tra chữ ký và một luồng cơ sở dữ liệu ghi trạng thái được tạo ra.
Nếu không liên tục cải thiện hiệu năng, nút có cấu hình kém có thể sẽ không còn tham gia được mạng lưới trong tương lai.
giới thiệu
Văn hóa "không cần tin tưởng, có thể kiểm chứng" của Bitcoin đòi hỏi sổ cái có thể được tái tạo từ đầu bởi bất kỳ ai. Sau khi xử lý tất cả các giao dịch lịch sử, mỗi người dùng sẽ nhận được kết quả chính xác giống nhau về tình trạng tiền của họ như mọi người khác trên mạng.
Khả năng tái tạo này là cốt lõi trong thiết kế giảm thiểu sự phụ thuộc vào lòng tin của Bitcoin , nhưng nó đi kèm với một cái giá rất lớn: 17 năm sau khi blockchain Bitcoin ra đời, cơ sở dữ liệu không ngừng mở rộng này đòi hỏi những người mới tham gia mạng lưới phải tiêu tốn nhiều tài nguyên hơn so với những người đi trước để chuẩn bị cho việc sử dụng nó.
Để khởi tạo một nút mới từ đầu, nó phải tải xuống, xác minh và lưu trữ mọi khối từ Khối Genesis đến đỉnh của Chuỗi hiện tại — quá trình đồng bộ hóa lượng lớn nhiều tài nguyên này được gọi là "IBD (Initial Block Download)".
Trong khi phần cứng dành cho người tiêu dùng tiếp tục nâng cấp , việc giữ cho quá trình tải xuống khối ban đầu có gánh nặng thấp vẫn rất quan trọng đối với tính tập trung: đảm bảo mọi người đều có thể xác minh blockchain Bitcoin , từ các thiết bị tiêu thụ ít năng lượng (như Raspberry Pi) đến các máy chủ mạnh mẽ.
So sánh hiệu suất
Tối ưu hóa hiệu năng bắt đầu bằng việc hiểu rõ các thành phần phần mềm, mô hình dữ liệu, phần cứng và điều kiện mạng, cũng như cách chúng tương tác tạo ra các điểm nghẽn hiệu năng. Điều này đòi hỏi phải thử nghiệm lượng lớn, nhưng hầu trong đó các thử nghiệm đều mang lại ít hoặc không có kết quả. Bên cạnh sự cân bằng thông thường giữa tốc độ, mức sử dụng bộ nhớ và khả năng bảo trì, các nhà phát triển Bitcoin Core cũng phải lựa chọn những thay đổi rủi ro thấp/lợi nhuận cao. Những tối ưu hóa hiệu quả nhưng nhỏ thường bị từ chối vì rủi ro lớn hơn lợi nhuận.
Chúng tôi có một bộ các bài kiểm tra hiệu năng nhỏ quan trọng để đảm bảo rằng các chức năng hiện có không bị giảm hiệu suất. Điều này rất hữu ích để nắm bắt các hiệu ứng hồi quy (tức là sự suy giảm hiệu suất trong một đoạn mã duy nhất), nhưng không nhất thiết phản ánh hiệu suất tổng thể của quá trình tải xuống khối ban đầu.
Những người đóng góp vào các đề xuất tối ưu hóa đã cung cấp khả năng tái tạo và chỉ báo trên hoàn cảnh khác nhau: hệ điều hành, trình biên dịch, loại lưu trữ (SSD so với HDD), tốc độ mạng, kích thước bộ nhớ cache cơ sở dữ liệu, cấu hình nút(chế độ cắt tỉa so với chế độ lưu trữ) và các tổ hợp chỉ mục. Chúng tôi đã viết các bài kiểm tra hiệu năng đơn mục đích và sử dụng trình duyệt đã biên dịch để xác minh cài đặt nào hoạt động tốt hơn trong các kịch bản cụ thể nào (ví dụ: sử dụng tập hợp băm/tập hợp được sắp xếp/vectơ được sắp xếp để kiểm tra giao dịch chồng chéo giữa các khối).
Chúng tôi cũng định kì chạy các bài kiểm tra hiệu năng cho việc tải xuống khối ban đầu. Phương pháp kiểm tra bao gồm: lập chỉ mục lại trạng thái blockchain(chainstate) từ tệp khối cục bộ (điều này cũng có thể yêu cầu lập chỉ mục lại các khối); hoặc thực hiện tải xuống khối ban đầu hoàn chỉnh từ một nút hàng trong mạng nội bộ hoặc từ một mạng ngang hàng lớn (sử dụng nút trong mạng nội bộ giúp tránh ảnh hưởng của các kết nối nút chậm hơn đến thời gian).
Những cải tiến thể hiện trong các bài kiểm tra hiệu năng khi tải xuống các khối ban đầu thường nhỏ hơn so với những cải tiến thể hiện trong các bài kiểm tra hiệu năng chi tiết hơn, bởi vì băng thông mạng hoặc tốc độ đọc/ghi của ổ cứng thường là những điểm nghẽn; với tốc độ mạng trung bình toàn cầu, chỉ riêng việc tải xuống toàn bộ blockchain đã mất khoảng 16 giờ.
Để tối đa hóa khả năng tái tạo, chúng tôi thường ưu tiên phương pháp kiểm thử lập chỉ mục lại trạng thái Chuỗi , hiển thị mức sử dụng bộ nhớ và CPU trước và sau khi tối ưu hóa, đồng thời xác minh xem những thay đổi này ảnh hưởng đến các chức năng khác như thế nào.
Tối ưu hóa lịch sử và hiện tại
Các phiên bản đầu tiên của Bitcoin Core được thiết kế cho các khối nhỏ hơn nhiều. Nguyên mẫu sớm nhất, Satoshi Nakamoto viết, chỉ đặt nền móng, và nếu không có sự đổi mới liên tục từ các nhà phát triển Bitcoin Core , nó đã sớm không thể đáp ứng được quy mô chưa từng có của mạng lưới.
Ban đầu, chỉ mục khối lưu trữ mọi giao dịch lịch sử và trạng thái đã được sử dụng hay chưa. Tuy nhiên, vào năm 2012, nhà phát triển Ultraprune (PR #1677) đã tạo ra một cơ sở dữ liệu chuyên dụng để theo dõi các giao dịch chưa được sử dụng, từ đó thiết lập khái niệm "tập hợp UTXO". Cơ sở dữ liệu này lưu trữ trước trạng thái sớm nhất của tất cả các bút chì có thể sử dụng được , cung cấp một góc nhìn thống nhất cho việc xác minh khối. Kết hợp với việc chuyển đổi triển khai cơ sở dữ liệu từ Berkeley DB sang LevelDB, tốc độ xác minh đã được cải thiện đáng kể.
Tuy nhiên, quá trình chuyển đổi cơ sở dữ liệu này cũng dẫn đến sự fork Chuỗi BIP50 1 : một khối chứa nhiều đầu vào giao dịch đã được nút nâng cấp chấp nhận nhưng bị nút chưa được cập nhật từ chối (vì khối quá phức tạp). Điều này làm nổi bật sự khác biệt giữa phát triển Bitcoin Core và kỹ thuật phần mềm thông thường: ngay cả việc tối ưu hóa hiệu suất đơn thuần cũng có thể dẫn đến sự phân tách Chuỗi không mong muốn.
Năm sau đó, (PR #2060) cho phép xác minh chữ ký đa luồng. Cùng thời điểm đó, thư viện mật mã chuyên dụng libsecp256k1 được tạo ra và tích hợp vào Bitcoin Core năm 2014. Trong thập kỷ tiếp theo, thông qua việc tối ưu hóa liên tục, nó đã trở nên nhanh hơn gấp 8 lần so với chức năng tương tự trong thư viện OpenSSL đa năng.
"Đồng bộ hóa Block Header trước" (PR #4468, 2014) tái cấu trúc quy trình tải xuống khối ban đầu: trước tiên nó tải xuống Block Header của Chuỗi có khối lượng công việc tích lũy nhiều nhất, sau đó đồng thời yêu cầu các khối từ nhiều nút ngang hàng. Ngoài việc tăng tốc IBD, nó còn ngăn nút lãng phí băng thông vào các khối mồ côi không thuộc về Chuỗi chính.
Vào năm 2016, PR #9049 đã loại bỏ một bước kiểm tra đầu vào chồng chéo dường như thừa thãi, dẫn đến một lỗi đồng thuận cho phép lạm phát. May mắn thay, lỗi này đã được phát hiện và vá trước khi bị khai thác. Sự cố này đã thúc đẩy một khoản đầu tư lớn vào nguồn lực kiểm thử. Giờ đây, với kỹ thuật fuzzing khác biệt (differential fuzzing ), phạm vi bao phủ mã rộng rãi và kỷ luật kiểm toán nghiêm ngặt hơn, Bitcoin Core phát hiện và giải quyết các vấn đề nhanh hơn nhiều, và không có lỗ hổng đồng thuận nào có mức độ nghiêm trọng tương tự báo cáo kể từ đó.
Vào năm 2017, thẻ khởi chạy -assumevalid (PR #9484) đã tách biệt các kiểm tra tính hợp lệ của khối thông thường khỏi việc xác minh chữ ký tốn kém, khiến việc xác minh chữ ký trở nên tùy chọn đối với hầu hết các trường hợp IBD, do đó giảm thời gian thực hiện IBD xuống khoảng một nửa. Việc xây dựng khối, Bằng chứng công việc và các quy tắc chi phí vẫn được xác minh đầy đủ: chế độ -assumevalid chỉ đơn giản là bỏ qua hoàn toàn các kiểm tra chữ ký (trước khi đạt đến một độ cao nhất định).
Vào năm 2022, PR #25325 đã thay thế bộ cấp phát bộ nhớ tiêu chuẩn của Bitcoin Core bằng một bộ cấp phát tùy chỉnh, dựa trên nhóm, được tối ưu hóa đặc biệt cho việc lưu trữ bộ nhớ đệm của tiền điện tử. Bằng cách thiết kế riêng cho mô hình phân bổ của Bitcoin, nó đã giảm thiểu lãng phí bộ nhớ, cải thiện hiệu quả lưu trữ bộ nhớ đệm và giúp IBD nhanh hơn khoảng 21%, đồng thời cho phép lưu trữ nhiều tiền điện tử hơn trong cùng một lượng bộ nhớ.
Mặc dù bản thân mã nguồn không Đột biến, nhưng hệ thống chứa nó lại liên tục biến đổi. Trạng thái của Bitcoin thay đổi sau mỗi 10 phút—và với mỗi thay đổi trong mô hình sử dụng, các điểm nghẽn cũng dịch chuyển. Việc bảo trì và tối ưu hóa là bắt buộc; nếu không có sự cải tiến liên tục, Bitcoin sẽ tích lũy các lỗ hổng nhanh hơn khả năng chịu đựng của một mã nguồn tĩnh, và hiệu suất tải xuống khối ban đầu giảm nhanh chóng, ngay cả khi phần cứng tiếp tục được cải tiến.
Kích thước ngày càng mở rộng của tập hợp UTXO, cùng với sự gia tăng trọng lượng trung bình của các khối, đã khuếch đại những thay đổi này. Những nhiệm vụ từng tiêu tốn nhiều tài nguyên CPU (như xác minh chữ ký) giờ đây thường tiêu tốn nhiều tài nguyên ổ đĩa do việc truy cập trạng thái Chuỗi tăng lên (yêu cầu kiểm tra tập hợp UTXO trên ổ đĩa). Sự thay đổi này đã thúc đẩy các ưu tiên mới: tối ưu hóa bộ nhớ đệm, giảm tần suất ghi LevelDB và song song hóa việc đọc dữ liệu trên ổ đĩa để giữ cho các CPU đa lõi hiện đại hoạt động hiệu quả.

- Danh sách ngày IBD (Integrated Bond Day) cho các bản phân phối Bitcoin Core khác nhau -
Các tối ưu hóa gần đây
Nền tảng của thiết kế phần mềm là dự đoán các mô hình sử dụng, điều này chắc chắn sẽ khác xa so với thực tế khi mạng lưới phát triển. Khối lượng công việc xác định của Bitcoin cho phép chúng ta đo lường hành vi thực tế và thực hiện các điều chỉnh kịp thời, đảm bảo hiệu suất theo kịp tăng trưởng của mạng lưới.
Chúng tôi liên tục điều chỉnh các cài đặt mặc định của phần mềm để phù hợp hơn với các mô hình sử dụng thực tế. Dưới đây là một vài ví dụ:
- PR #30039 đã tăng kích thước tệp tối đa cho LevelDB — thay đổi tham số duy nhất này đã tăng tốc IBD lên gần 30% vì nó phù hợp hơn với các mẫu truy cập thực tế vào cơ sở dữ liệu trạng thái Chuỗi(tập hợp UTXO).
- PR #31645 đã tăng gấp đôi kích thước của lần ghi, giảm thiểu việc ghi dữ liệu phân mảnh vào đĩa trong giai đoạn ghi dữ liệu cường độ cao nhất của quá trình tải xuống khối ban đầu và tăng tốc độ lưu tiến trình khi quá trình tải xuống khối ban đầu bị gián đoạn.
- PR #32279 điều chỉnh kích thước lưu trữ của prevector nội bộ (chủ yếu được sử dụng để lưu trữ script trong bộ nhớ). Ngưỡng prevector witness riêng biệt cũ ưu tiên các mẫu script cũ hơn, gây bất lợi cho các mẫu mới hơn. Bằng cách điều chỉnh kích thước của nó để phù hợp với kích thước script mới hơn, việc phân bổ phân mảnh được tránh, hiện tượng phân mảnh bộ nhớ được giảm thiểu và việc thực thi script được hưởng lợi từ vị trí bộ nhớ cache tốt hơn.
Tất cả những thay đổi này đều nhỏ, nhưng chúng lại có tác động đáng kể.
Ngoài việc điều chỉnh các thông số, một số thay đổi cũng đòi hỏi chúng ta phải xem xét lại thiết kế hiện có:
- PR #28280 cải thiện cách nút được cắt tỉa (nút loại bỏ các khối cũ để tiết kiệm dung lượng đĩa) xử lý việc làm mới bộ nhớ cache thường xuyên. Thiết kế ban đầu hoặc loại bỏ toàn bộ bộ nhớ cache hoặc quét nó để tìm các mục đã sửa đổi. Việc theo dõi có chọn lọc các mục đã sửa đổi đã giúp tăng tốc hơn 30% đối với nút được cắt tỉa sử dụng bộ nhớ cache tối đa (
dbcache), và tăng tốc khoảng 9% với cài đặt mặc định. - PR #31551 đã giới thiệu tính năng xử lý theo lô cho việc đọc/ghi các tập tin khối, giảm thiểu chi phí phát sinh của nhiều thao tác hệ thống tập tin quy mô nhỏ. Tốc độ đọc tập tin khối được tăng từ 4 đến 8 lần, không chỉ mang lại lợi ích cho việc tải xuống khối ban đầu mà còn cho các RPC khác.
- PR #31144 tối ưu hóa việc làm mờ tệp khối tùy chọn hiện có (được sử dụng để đảm bảo dữ liệu không được lưu trữ trên đĩa dưới dạng văn bản thuần) bằng cách xử lý dữ liệu theo khối 64 bit thay vì byte, mang lại khả năng tăng tốc IBD hơn nữa. Với việc làm mờ gần như miễn phí, người dùng không còn cần phải lựa chọn giữa lưu trữ an toàn và hiệu suất nữa.
Các tối ưu hóa bộ nhớ đệm nhỏ khác (chẳng hạn như PR #32487) cho phép thực hiện các kiểm tra bảo mật bổ sung mà trước đây được cho rằng quá tốn kém theo PR #32638.
Tương tự, giờ đây chúng ta có thể ghi bộ nhớ đệm vào đĩa thường xuyên hơn (PR #30611) để đảm bảo nút không bao giờ mất quá một giờ làm việc xác minh trong thời gian ngừng hoạt động. Chi phí nhỏ này là chấp nhận được vì các tối ưu hóa tiếp theo đã giúp việc tải xuống khối ban đầu nhanh hơn nhiều.
PR #32043 hiện là một luồng theo dõi các cải tiến hiệu năng liên quan đến IBD. Nó tóm tắt hơn mười dự án đang được tiến hành, từ các tinh chỉnh về ổ đĩa và bộ nhớ cache đến các cải tiến về khả năng xử lý đồng thời, và cung cấp một khuôn khổ để đo lường tác động của mỗi thay đổi đến hiệu năng trong các tình huống thực tế. Phương pháp này khuyến khích những người đóng góp không chỉ cung cấp mã nguồn mà còn cả các điểm chuẩn có thể tái tạo, dữ liệu sử dụng và so sánh trên nhiều phần cứng khác nhau.
Đề xuất tối ưu hóa trong tương lai
PR #31132 song song hóa việc lấy dữ liệu đầu vào giao dịch trong quá trình xác thực khối. Hiện tại, mỗi dữ liệu đầu vào được lấy tuần tự từ tập hợp UTXO — nếu không tìm thấy trong bộ nhớ cache, cần phải giao tiếp với đĩa, tạo ra nút thắt cổ chai khi đọc/ghi. PR này giới thiệu việc lấy dữ liệu song song trên nhiều luồng xử lý, đạt được tốc độ tăng khoảng 30% với -reindex-chanstate (mất khoảng 10 giờ trên Chuỗi Pi 5 với bộ nhớ cache cơ sở dữ liệu 450MB). Một tác dụng phụ là nó thu hẹp khoảng cách hiệu suất giữa các cấu hình ` -dbcache cao và thấp, cho phép nút có ít bộ nhớ hơn đồng bộ hóa nhanh như nút có nhiều bộ nhớ hơn.
Ngoài việc khởi tạo quá trình tải xuống khối, PR #26966 cũng sử dụng các luồng xử lý có thể cấu hình để song song hóa việc lọc khối và biên dịch chỉ mục giao dịch.
Việc giữ cho tập hợp UTXO lưu trữ liên tục ở dạng nhỏ gọn là rất quan trọng đối với hiệu quả kinh tế nút. PR #33817 đã thử nghiệm tác động của việc giảm nhẹ kích thước này bằng cách loại bỏ một tính năng tùy chọn của LevelDB (có thể không cần thiết cho các ứng dụng Bitcoin).
SwiftSync 3 là một phương pháp thử nghiệm tận dụng thông tin từ các khối lịch sử. Biết được kết quả thực tế, chúng ta có thể phân loại từng đồng tiền gặp phải dựa trên trạng thái cuối cùng của nó ở độ cao mục tiêu: những đồng tiền chưa được sử dụng (để lưu trữ) và những đồng tiền đã được sử dụng trước độ cao đó (để bỏ qua; chỉ cần xác minh sự hiện diện của chúng trong cặp tạo/sử dụng phù hợp, bất kể vị trí cụ thể của chúng). Các gợi ý được tạo trước có thể mã hóa việc phân loại này, cho phép nút bỏ qua hoàn toàn các thao tác UTXO trên các đồng tiền có thời gian tồn tại ngắn.
Bitcoin dành cho tất cả mọi người.
Ngoài các bài kiểm tra hiệu năng tổng hợp, một thử nghiệm gần đây 4 cũng đã chạy nguyên mẫu Swiftsync trên Raspberry Pi 5 được giảm xung nhịp; Raspberry Pi 5 này, được cấp nguồn bằng một bộ pin duy nhất và kết nối qua WiFi, đã mã hóa lại trạng thái Chuỗi của 888.888 khối trong 3 giờ 14 phút. Các thử nghiệm sử dụng cấu hình tương đương cho thấy tốc độ tăng 250% đối với việc xác minh đầy đủ trên các phiên bản Bitcoin Core mới hơn 5 .
Nhiều năm nỗ lực tích lũy đã tạo nên tác động to lớn: gần 1 triệu khối đã được xác minh đầy đủ, và việc này có thể được thực hiện trong một ngày trên phần cứng giá rẻ; blockchain vẫn duy trì được tính kinh tế bất chấp tăng trưởng liên tục của nó.
Tự quản giờ đây dễ dàng hơn bao giờ hết.
Tham khảo
1. https://github.com/bitcoin/bips/blob/master/bip-0050.mediawiki
2. https://en.bitcoin.it/wiki/Common_Vulnerabilities_and_Exposures
3. https://delvingbitcoin.org/t/swiftsync-speeding-up-ibd-with-pre-generated-hints-poc/1562
4. https://x.com/L0RINC/status/1972062557835088347 ↩
5. https://x.com/L0RINC/status/1970918510248575358 ↩
Tất cả các yêu cầu kéo (PR) được liệt kê trong bài viết này đều có thể được tìm thấy ở đây theo số thứ tự: https://github.com/bitcoin/bitcoin/pulls



