ĐẠI HỌC QUỐC GIA TP HỒ CHÍ MINH TRƯỜNG ĐẠI HỌC CÔNG NGHỆ THÔNG TIN KHOA KHOA HỌC & KỸ THUẬT THÔNG TIN BÁO CÁO MÔN HỌC ĐỒ ÁN IT207 N11 CNCL GIẢNG VIÊN HƯỚNG DẪN VÕ NGỌC TÂN SINH VIÊN THỰC HIỆN ĐÀO VĨNH[.]
Trang 1ĐẠI HỌC QUỐC GIA TP HỒ CHÍ MINH
TRƯỜNG ĐẠI HỌC CÔNG NGHỆ THÔNG TIN KHOA KHOA HỌC & KỸ THUẬT THÔNG TIN
BÁO CÁO MÔN HỌC
ĐỒ ÁN IT207.N11.CNCL
GIẢNG VIÊN HƯỚNG DẪN: VÕ NGỌC TÂN
SINH VIÊN THỰC HIỆN: ĐÀO VĨNH KỲ - 19521730
TRẦN HÙNG - 19521584
TP HỒ CHÍ MINH, 12/2020
Trang 3Chương 6 Indexing and Storage 4
1.1 Indexing Data 4
1.1.1 Tracking ERC20 Token Holders 5
1.1.2 Revisiting the ERC20 Interface 5
1.1.3 Querying Transfer Events 6
1.1.4 Chia se( dư) lie*+u cu(a chu,ng to*i 11
1.1.5 Xư( ly, to chư,c la+i chuo/i 13
1.1.6 Sư( du+ng đa1ng ky, 13
1.1.7 Pha,t hie*+n mo*+t sư+ ta,i to chư,c 14
1.1.8 Hoa6n nguye*n ca,c thay đo.i 16
1.1.9 Kie.m thư( đơn vi+ 18
1.1.10 Cho+n mo*+t Node: 18
1.1.11 Kie.m tra trì6nh la*+p chì( mu+c 19
1.1.12 Sư( du+ng Ả>nh chu+p nhanh 22
1.1.13 Lưu y, ve@ ta*+p trung ho,a 23
1.1.14 Di+ch vu+ phi ta*+p trung 23
1.1.15 ỨBng du+ng ta*+p trung 24
1.2 Storage 24
1.2.1 Lưu trữ ngoài (Off-chain Storage) 25
1.2.2 Tiện ích mở rộng siêu dữ liệu ERC721(ERC721 Metadata Extension) 25
1.2.3 Saving Token Metadata 27
1.2.4 Interplanetary Storage 30
Trang 41.2.5 Sử dụng IpFS trong ứng dụng 32
1.2.6 Lưu trữ ứng dụng trên IPFS 34
1.3 Kết luận 35
Trang 5Chương 6 Indexing and Storage
Trong hai chương cuối, chúng ta đã học cách đọc và ghi vào mạng Ethereum Đọc có thể được thực hiện như các cuộc gọi thông thường đến các hợp đồng hoặc bằng cách truy vấncác sự kiện đã ghi, trong khi việc ghi luôn được thực hiện trong ngữ cảnh của một giao dịch Tuy nhiên, các thao tác này chỉ phù hợp với các trường hợp sử dụng cơ bản Nếu chúng tôi muốn hiển thị dữ liệu tổng hợp từ blockchain, việc truy vấn các sự kiện từ phía máy khách sẽ nhanh chóng bị thiếu hụt Tương tự như vậy, nếu chúng ta muốn lưu trữ một lượng lớn thông tin trong một hợp đồng, chi phí khí đốt khiến nó không khả thi về mặt kinh tế Trong chương này, chúng ta sẽ làm việc với các thành phần ngoài chuỗi để giải quyết cả hai vấn đề Trước tiên, chúng ta sẽ trải qua quá trình lập chỉ mục dữ liệu blockchain trong một máy chủ để truy vấn nó từ một ứng dụng khách và sau đó đi vào các giải pháp lưu trữ ngoài chuỗi Chúng tôi cũng sẽ xem xét các kỹ thuật để xử lý việc tổchức lại và thử nghiệm trong quá trình thực hiện, cũng như thảo luận về giá trị của các giải pháp tập trung so với phi tập trung
1.1 Indexing Data
Chúng ta sẽ bắt đầu với vấn đề lập chỉ mục dữ liệu blockchain Trong ngữ cảnh này, bằngcách lập chỉ mục, chúng tôi đề cập đến hành động thu thập các phần thông tin nhất định
từ mạng (chẳng hạn như số dư mã thông báo, giao dịch đã gửi hoặc hợp đồng được tạo)
và lưu trữ chúng trong kho dữ liệu có thể truy vấn, chẳng hạn như cơ sở dữ liệu quan hệ hoặc công cụ phân tích như ElasticSearch, để thực hiện các truy vấn phức tạp Trong suốtchương này, thay vì cố gắng lập chỉ mục toàn bộ chuỗi, chúng tôi sẽ chọn một tập dữ liệu
cụ thể và xây dựng một giải pháp phù hợp với nó , vì API sự kiện Ethereum không phù hợp để làm như vậy Ví dụ: không thể dễ dàng có được số lượng địa chỉ duy nhất chứa nhiều hơn một số dư nhất định của nội dung ERC20 - một truy vấn nhỏ khi chạy trên cơ
sở dữ liệu quan hệ
Lập chỉ mục cũng có thể được sử dụng để cải thiện hiệu suất khi truy vấn số lượng
Trang 6lớn sự kiện, bằng cách hoạt động như một bộ nhớ cache truy vấn Một cơ sở dữ liệu chuyên dụng có thể trả lời các truy vấn sự kiện nhanh hơn nhiều so với một nút Ethereumthông thường.
1.1.1 Tracking ERC20 Token Holders
Chúng tôi sẽ theo dõi những người nắm giữ mã thông báo của một đồng ERC20 cụ thể Hãy nhớ rằng các mã thông báo không thể thay thế ERC20 có thể hoạt động như một đồng xu, trong đó mỗi địa chỉ có một số dư nhất định Tuy nhiên, hợp đồng không đưa ra phương pháp nào để thực sự liệt kê chúng Ngay cả khi điều đó xảy ra, một số mã thông báo có cơ sở người dùng sẽ vượt quá khả năng của một ứng dụng chỉ phía máy khách truy vấn nút Ethereum Ví dụ: tại thời điểm viết bài này, mã thông báo OmiseGO (OMG)
có hơn 650.000 chủ sở hữu duy nhất.2
1.1.2 Revisiting the ERC20 Interface
Chúng tôi sẽ xem xét giao diện hợp đồng ERC20 để xác định các khối xây dựng mà chúng tôi sẽ sử dụng Bỏ qua các chức năng liên quan đến phụ cấp, tiêu chuẩn ERC20 bao gồm các phương pháp và sự kiện này
Như đã đề cập, không giống như tiêu chuẩn ERC721 mở rộng, ERC20 không cung
Trang 7danh sách như vậy là đi qua mọi sự kiện Chuyển và thu thập tất cả các địa chỉ người nhận.
1.1.3 Querying Transfer Events
Truy vấn sự kiện chuyển Chúng tôi sẽ bắt đầu bằng cách truy vấn tất cả các sự kiện chuyển nhượng từ một hợp đồng nhất định Chúng tôi sẽ xây dựng một lớp
ERC20Indexer, dựa vào nhà cung cấp kết nối web3, địa chỉ mã thông báo ERC20 và số khối để bắt đầu truy vấn từ đó (Liệt kê 6-1) Tham số cuối cùng này chỉ được thêm vào vì
lý do hiệu suất: không có ý nghĩa gì khi truy vấn bất kỳ khối nào trước khi hợp đồng mã thông báo được triển khai Liệt kê 6-1.Constructor cho lớp ERC20Indexer mà chúng tôi
sẽ làm việc trên Chúng tôi một lần nữa phụ thuộc vào openzeppelin-solidity@2.2.0 để cóđược ABI hợp đồng ERC20 Chúng tôi sẽ lưu trữ danh sách tất cả địa chỉ chủ sở hữu mã thông báo trên bộ chủ sở hữu và trường LastBlock sẽ theo dõi khối cuối cùng mà chúng tôi đã xử lý
Trang 8Bây giờ chúng ta có thể thêm một phương thức đầu tiên vào lớp này để lấy danh sách các sự kiện chuyển giao từ một hợp đồng nhất định (Liệt kê 6-2) Vì danh sách đó cókhả năng lớn hơn những gì chúng tôi có thể đáp ứng trong một yêu cầu duy nhất (OMG
có hơn 2 triệu lần chuyển đến thời điểm hiện tại), chúng tôi sẽ cần chia nó thành nhiều yêu cầu, vì vậy chúng tôi sẽ bắt đầu với một phương pháp xử lý tất cả các sự kiện trong một phạm vi của các khối
Liệt kê 6-2 Truy vấn tất cả các sự kiện chuyển từ một loạt các khối theo lô Ở đây
BATCH_SIZE sẽ phụ thuộc vào khối lượng giao dịch trên mỗi khối của hợp đồng
Phương thức này sẽ nhận tất cả các sự kiện chuyển trong một phạm vi khối từ một hợp đồng và gửi chúng đến một hàm ReduceEvent (Liệt kê 6-3) Chức năng giảm này sẽ nhận một sự kiện và sử dụng nó để cập nhật danh sách chủ sở hữu mã thông báo hiện tại
Trang 9Liệt kê 6-3 Truy xuất người nhận chuyển mã thông báo để thêm người đó vào danh sách
chủ sở hữu mã thông báo Việc chuyển đến địa chỉ số 0 thường là các mã thông báo bị cháy, vì vậy chúng tôi sẽ đưa nó ra khỏi danh sách của mình
Tuy nhiên, phương pháp này có thể mang lại một số kết quả dương tính giả Nếu một địa chỉ từng giữ một số số dư nhưng sau đó đã chuyển tất cả, địa chỉ đó sẽ được thêmvào danh sách chủ sở hữu của chúng tôi nhưng không bao giờ bị xóa Điều này có nghĩa
là chúng ta cần kiểm tra xem số dư địa chỉ có khác 0 để liệt kê nó hay không Vì chúng tôi đang ở đó, chúng tôi sẽ đi thêm một dặm và theo dõi số dư hiện tại của mỗi chủ sở hữu Chúng tôi có hai tùy chọn để thực hiện việc này, mỗi tùy chọn đều có ưu và nhược điểm riêng:
Chúng tôi có thể dựa vào phương pháp ERC20 balanceOf để kiểm tra số dư của từng địa chỉ mà chúng tôi thêm vào danh sách của mình Chúng tôi có thể thực hiện việc này ngay khi chúng tôi tìm thấy một địa chỉ mới để thêm vào tập hợp của mình và có mộtngười giữ với số dư của nó đã sẵn sàng Tuy nhiên, điều này có nghĩa là chúng tôi đang đưa ra yêu cầu bổ sung cho từng chủ sở hữu mã thông báo và chúng tôi cũng cần chạy lạitruy vấn này bất cứ khi nào chúng tôi thấy một khối mới với các lần chuyển mới
Chúng tôi có thể sử dụng thực tế rằng số dư của bất kỳ địa chỉ nào trong hợp đồngERC20 có thể được xác định bằng cách chỉ cần xem xét các sự kiện chuyển nhượng Vì chúng tôi đã truy vấn chúng, chúng tôi có thể theo dõi tất cả các chuyển động đến và đi từmỗi địa chỉ và cập nhật chúng cho phù hợp Điều này sẽ yêu cầu logic hơn một chút về
Trang 10phía chúng tôi, nhưng không cần bất kỳ yêu cầu bổ sung nào đối với mạng Ethereum Nhược điểm của nó là chúng ta không thể dựa vào số dư của một địa chỉ cho đến khi chúng ta quét xong cho đến khi khối mới nhất trong chuỗi
Để ưu tiên giảm số lượng yêu cầu, chúng tôi sẽ đi với chiến lược thứ hai (Liệt kê 6-4) Điều này có nghĩa là chức năng của chúng tôi để giảm bớt một sự kiện cũng sẽ cần tính đến giá trị của mỗi lần chuyển
Liệt kê 6-4 Giảm giá một sự kiện để cập nhật số dư của mỗi chủ sở hữu Ở đây số dư là
một đối tượng thay thế tập hợp các chủ sở hữu cũ Lưu ý rằng chúng tôi đang loại trừ địa chỉ số 0 với tư cách là người gửi và người nhận, vì chuyển từ địa chỉ này đại diện cho các
sự kiện đúc tiền và chuyển đến địa chỉ đó đại diện cho bỏng
Được trang bị một lớp có thể tạo danh sách những người nắm giữ và số dư của chúng cho một phạm vi khối nhất định, bây giờ chúng ta cần phải cập nhật danh sách nàykhi các khối mới được khai thác (Liệt kê 6-5) Chúng tôi sẽ sử dụng tính năng thăm dò đểnhận các khối mới, mặc dù đăng ký cũng là một giải pháp thay thế khả thi
Trang 11Liệt kê 6-5 Thanh toán cho các khối mới và truy xuất bất kỳ sự kiện chuyển giao mới
nào Hàm processNewBlocks sẽ truy vấn khối mới nhất và gọi vào processBlocks với phạm vi khối mới, trong khi hàm start khởi động một vòng lặp vô hạn liên tục thăm dò vàsau đó ngủ trong 1 giây
Một chi tiết quan trọng trong việc triển khai của chúng tôi là chúng tôi sẽ không
xử lý đến khối mới nhất mà chỉ xử lý cho đến một số khối nhất định trước đó Điều này đảm bảo rằng bất kỳ sự kiện chuyển giao nào mà chúng tôi đã xử lý đều được xác nhận
và sẽ không bị lùi lại như một phần của việc tổ chức lại Sau đó, chúng tôi sẽ xem xét cácchiến lược để truy vấn đến khối gần đây nhất và xử lý các bản ghi lại khi chúng tôi phát hiện ra chúng
Trang 121.1.4 Chia sẻ dữ liệu của chúng tôi
Bước cuối cùng là thực sự cung cấp quyền truy cập vào dữ liệu chúng tôi đã thu thập (Liệt kê 6-6) Chúng tôi sẽ thiết lập một máy chủ express đơn giản để hiển thị tập hợp số
dư ở định dạng JSON theo yêu cầu HTTP GET 188 Liệt kê 6-6 Máy chủ express đơn giản hiển thị số dư từ trình chỉ mục trong một điểm cuối HTTP Trình trợ giúp
mapValues lodash được sử dụng để định dạng các giá trị BigNumber trước khi tuần tự hóa chúng trong JSON Đảm bảo nhận được mã thông báo Infura để đặt biến
API_TOKEN
Trang 13Liệt kê 6-7 Truy vấn điểm cuối express để lấy số dư mã thông báo Chúng tôi đang sử
dụng tiện ích jq3 chỉ để in đẹp đầu ra JSON
1.1.5 Xử lý tổ chức lại chuỗi
Cho đến thời điểm này, chúng tôi đã tránh được vấn đề sắp xếp lại chuỗi bằng cách chỉ
xử lý các chuyển giao có thể được coi là đã hoàn thành, nói cách khác, các chuyển giao
đã xảy ra đủ khối trước đó cơ hội các khối đó bị xóa khỏi chuỗi là không đáng kể Giờ đây, chúng tôi sẽ loại bỏ hạn chế này và xem cách chúng tôi có thể xử lý các sự kiện mới nhất một cách an toàn bằng cách phản ứng đúng cách với một nhà tổ chức lại
1.1.6 Sử dụng đăng ký
Cách dễ nhất để phát hiện và phản ứng với một bản reorg là thông qua đăng ký Việc đăng ký một sự kiện, chẳng hạn như trên ERC20 Transfer, sẽ không chỉ đẩy các sự kiện mới vào quy trình của chúng tôi trong thời gian thực mà còn thông báo về bất kỳ sự kiện nào bị xóa do tổ chức lại Điều này có nghĩa là chúng ta có thể viết phần đối chiếu của hàm ReduceEvent để hoàn tác một sự kiện và chạy nó bất cứ khi nào nút Ethereum đẩy một loại bỏ sự kiện (Liệt kê 6-8)
Liệt kê 6-8 Ghi lại một sự kiện chuyển khoản trong danh sách số dư của chúng tôi
Logic ở đây là ngược lại trong phương thức ReduceEvent
Trang 14Liệt kê 6-9 Sử dụng đăng ký để theo dõi các sự kiện mới và theo dõi các đăng ký đã bị
loại bỏ do tổ chức lại Trình xử lý dữ liệu kích hoạt bất cứ khi nào có sự kiện mới và sự kiện đã thay đổi khi sự kiện bị xóa khỏi chuỗi do tổ chức lại
1.1.7 Phát hiện một sự tái tổ chức
Một sự sắp xếp lại xảy ra khi một chain fork tập hợp nhiều sức mạnh băm tích lũy hơn so với phần đầu hiện tại và fork đó trở thành chuỗi chính thức Điều này có thể xảy ra nếu các bộ công cụ khai thác khác nhau hoạt động trên các nhánh khác nhau Điều này có nghĩa là trong quá trình tổ chức lại, một hoặc nhiều khối (bắt đầu ngược từ phần đầu hiện tại) sẽ được thay thế bằng các khối khác Các khối mới này có thể chứa hoặc không chứa
Trang 15các giao dịch giống như các khối trước đó và cũng có thể được sắp xếp theo thứ tự khác nhau, 4 mang lại kết quả khác nhau Nhớ lại từ Chương 3 rằng mỗi khối được xác định bằng hàm băm của nó Hàm băm này được tính toán từ dữ liệu của khối và hàm băm của khối trước đó Đây là những gì tạo nên một blockchain về bản chất của nó: thực tế là mỗi khối được gắn với khối trước đó Và điều này có nghĩa là không thể thay đổi một khối cũ nếu không buộc phải thay đổi mã định danh của tất cả các khối tiếp theo Khi băm của một khối ở một độ cao nhất định thay đổi, điều đó có nghĩa là khối đó và có thể là các khối khác trước khi nó cũng thay đổi Sau đó, chúng tôi chỉ có thể theo dõi khối mới nhất
mà chúng tôi đã xử lý và nếu hàm băm của nó thay đổi tại bất kỳ thời điểm nào, chúng tôisau đó quét ngược lại các hàm băm đã thay đổi khác, cho đến khi chúng tôi phát hiện ra một tổ tiên chung (Liệt kê 6-10) Hãy sửa đổi tập lệnh của chúng tôi để thêm một kiểm tra các bản ghi lại bằng cách sử dụng chiến lược này, điều này sẽ yêu cầu chúng tôi theo dõi các hàm băm khối mà chúng tôi đã xử lý
Liệt kê 6-10 Cập nhật processNewBlocks hàm kiểm tra các bản ghi lại sau mỗi lần lặp
Hàm undoBlocks (Liệt kê 6-12) sẽ hoàn tác tất cả các lần chuyển liên quan đến các khối
đã xóa, trả về khối gần đây nhất không bị ảnh hưởng bởi việc sắp xếp lại
Trang 161.1.8 Hoàn nguyên các thay đổi
Khi việc tổ chức lại được phát hiện, chúng tôi cần hoàn nguyên mọi chuyển giao mà chúng tôi đã xử lý từ các khối đã xóa Để làm được điều đó, trước tiên chúng ta cần theo dõi những lần chuyển mà chúng ta đã xử lý trên mỗi khối (Liệt kê 6-11) Chúng ta sẽ thêm một trường mới vào lớp Indexer của mình: một ngăn xếp chứa một mục trên mỗi khối mà chúng ta đã thấy khi xử lý sự kiện chuyển nhượng Mỗi mục sẽ chứa số khối, mã
Trang 17băm và danh sách chuyển nó bao gồm Chúng tôi sẽ thêm các mục mới vào nó bất cứ khi nào chúng tôi giảm bớt một sự kiện mới
Liệt kê 6-11: Theo dõi các sự kiện chuyển giao trên mỗi khối Hàm này được gọi từ
ReduceEvent Lưu ý rằng hàm này phải được gọi theo thứ tự khi các sự kiện mới đang được xử lý để đảm bảo danh sách các khối vẫn được sắp xếp với khối gần đây nhất ở cuối
Liệt kê 6-12: Lùi lại danh sách các sự kiện đã xử lý và hoàn tác tất cả các lần chuyển
Hàm này phải trả về khối gần đây nhất chưa bị xóa trong quá trình tổ chức lại, để tập lệnh
có thể xử lý lại chuỗi từ đó Hàm undoTransfer tương tự với hàm được trình bày trong
Trang 18phần phụ đăng ký trước đó trong chương này
1.1.9 Kiểm thử đơn vị
Cho đến nay, chúng tôi đã bỏ qua một khía cạnh quan trọng của phát triển phần mềm: kiểm tra Mặc dù thử nghiệm trong Ethereum về cơ bản không khác biệt đáng kể so với các ứng dụng khác, chúng tôi sẽ sử dụng ví dụ về trình lập chỉ mục của mình để giới thiệu một số kỹ thuật hữu ích cụ thể cho thử nghiệm blockchain
1.1.10 Chọn một Node:
Quyết định đầu tiên nằm ở việc chọn nút nào để sử dụng cho các thử nghiệm của chúng tôi Nhớ lại từ các chương trước rằng chúng ta có thể làm việc với ganache, một trình mô phỏng blockchain hoặc trên một nút thực tế, chẳng hạn như Geth hoặc Parity, đang chạy trên chế độ phát triển Cái trước nhẹ hơn và cung cấp các phương pháp bổ sung để thao