Trong lĩnh vực blockchain, oracle là hệ thống có thể cung cấp thông tin bên ngoài cho các hợp đồng thông minh Chuỗi chuỗi. Là phần mềm trung gian kết nối các hợp đồng thông minh và thế giới bên ngoài blockchain, oracle đóng nhân vật cơ sở hạ tầng cực kỳ quan trọng. Chức năng chính của chúng là cung cấp dữ liệu cho các hợp đồng thông minh trong blockchain .
Ví dụ, nếu chúng ta tạo một hợp đồng thông minh trên mạng Ethereum và hợp đồng này cần truy cập vào dữ liệu khối lượng giao dịch dầu thô vào một ngày cụ thể. Tuy nhiên, bản thân các hợp đồng thông minh không thể thu thập được dữ liệu thực tế ngoài Chuỗi này, do đó chúng cần được triển khai thông qua oracle. Trong trường hợp này, hợp đồng thông minh sẽ ghi khối lượng giao dịch dầu thô vào ngày cần thiết vào nhật ký sự kiện. Sau đó, một quy trình sẽ được bắt đầu ngoài Chuỗi để theo dõi và đăng ký nhật ký sự kiện này. Khi phát hiện yêu cầu trong giao dịch, quy trình sẽ gửi giao dịch trên Chuỗi, gọi phương pháp có liên quan của hợp đồng và tải thông tin khối lượng giao dịch dầu thô vào ngày đã chỉ định lên hợp đồng thông minh.

Dữ liệu từ https://defillama.com/oracles
Chainlink
Trong blockchain, Chainlink oracle chiếm thị phần lớn nhất. Chainlink là một dự án oracle phi tập trung có vai trò cung cấp dữ liệu được tạo ra trong thế giới thực cho blockchain theo cách an toàn nhất. Dựa trên việc triển khai các nguyên tắc cơ bản oracle , Chainlink đã thiết lập một hệ sinh thái chu kỳ lành mạnh xung quanh token LINK thông qua khích lệ kinh tế. Oracle Chainlink cần được kích hoạt bằng cách chuyển token LINK. LINK là hợp đồng ERC 677 trên mạng Ethereum. Chức năng oracle dựa trên token LINK ERC 677 thuộc trong đó độ yêu cầu/phản hồi.
transferAndCall trong token ERC 677

Về cơ bản, oracle là bên cung cấp dịch vụ. Khi Chainlink thiết kế nền tảng oracle, điều đầu tiên họ nghĩ đến là làm thế nào để người dùng oracle có thể trả phí dịch vụ cho oracle cung cấp dịch vụ. Tuy nhiên, do hợp đồng mã thông báo đồng nhất chuẩn ERC 20 không đáp ứng được nhu cầu cung cấp dịch vụ sau khi thanh toán nên Chainlink đã đề xuất một tiêu chuẩn phù hợp với các tình huống dịch vụ oracle- ERC 677.
Như bạn có thể thấy từ đoạn mã trên, ERC 677 thực chất chỉ thêm phương pháp transferAndCall dựa trên chuẩn ERC 20. Phương pháp này kết hợp thanh toán và yêu cầu dịch vụ thành một, đáp ứng nhu cầu của các tình huống việc kinh doanh Oracle .

Khi người dùng thực hiện lệnh transferAndCall, ngoài việc chuyển tiền ERC 20, lệnh này cũng sẽ xác định xem địa chỉ đến có phải là địa chỉ hợp đồng hay không. Nếu vậy, phương pháp onTokenTransfer của địa chỉ đến sẽ được gọi. (Ở đây, ERC 677 Receiver chỉ có một phương pháp: onTokenTransfer)
Chúng ta cũng có thể vào Etherscan để xem mã nguồn hợp đồng của token LINK: https://etherscan.io/address/0x514910771af9ca656af840dff83e8264ecf986ca#code

Có thể thấy rằng ngoài nhiều lần xác minh địa chỉ _to trong quá trình triển khai, LINK Token thực sự kế thừa phương pháp transferAndCall của ERC 677. Lưu ý: Trước khi yêu cầu dịch vụ oracle, hãy đảm bảo rằng oracle đó đáng tin cậy, vì oracle yêu cầu thanh toán trước khi cung cấp dịch vụ cho người dùng. (Bất kỳ ai cũng có thể cung cấp dịch vụ oracle)

Phân loại độ tin cậy oracle
Yêu cầu oracle trên Chuỗi
Chúng ta hãy xem phương pháp onTokenTransfer của hợp đồng oracle được triển khai như thế nào:

Khi người dùng oracle sử dụng phương pháp transferAndCall để thanh toán phí và yêu cầu dịch vụ của oracle, thì địa chỉ ở đây là địa chỉ của oracle được yêu cầu. Phương pháp onTokenTransfer trong oracle trước tiên sẽ xác minh xem giao dịch chuyển tiền có phải là token LINK (chỉ LINK) hay không, trên thực tế là để xác định xem msg.sender có phải là địa chỉ của hợp đồng token Link hay không. Sau đó, nó sẽ xác định xem độ dài của _data có vượt quá giới hạn tối đa hay không. Cuối cùng, nó sẽ xác định xem có bộ chọn hàm bắt đầu bằng "oracleRequest" trong _data hay không. Tất nhiên, bộ chọn chức năng ở đây có thể được tùy chỉnh theo các dịch vụ do oracle cung cấp. Không nhất thiết phải là "oracleRequest". Điều này phụ thuộc vào loại giao diện mà oracle sử dụng.
Khi tất cả các trình sửa đổi này được thông qua, hãy kiểm tra xem trình gọi hàm hiện tại và số tiền chuyển có giống với những hàm trong _data hay không. Sau khi tất cả các bước kiểm tra bảo mật này được thông qua, hợp đồng oracle hiện tại sẽ được gọi thông qua lệnh delegatecall. Tất nhiên, vì chúng ta đã kiểm tra bộ chọn hàm trong _data, nên thực tế là phương pháp oracleRequest được gọi.

Đầu tiên, người yêu cầu oracle và nonce do người đó gửi được nối lại và băm thành requestId cho yêu cầu lần, và ánh xạ cam kết được kiểm tra để xem liệu đó có phải là id duy nhất hay không. Nếu mọi thứ đều ổn, hãy đặt thời gian hết hạn, thêm requestId vào cam kết và nối _payment, _callbackAddress, _callbackFunctionId và expiration làm giá trị. Điều quan trọng nhất là phát hành sự kiện OracleRequest, chứa dữ liệu yêu cầu _data, là dữ liệu Biểu diễn đối tượng nhị phân súc tích (CBOR). Định dạng mã hóa này nhẹ và ngắn gọn, có thể hiểu đơn giản là định dạng JSON nhị phân. Dữ liệu này có thể ở nhiều dạng khác nhau, tùy thuộc vào cách thiết kế nút ngoài Chuỗi .
Ví dụ: một Aggregator Chainlink: ETH/USD có một giao dịch chứa sự kiện OracleRequest:

Ví dụ về sự kiện OracleRequest
Từ sự kiện này, chúng ta có thể thấy rằng bộ tổng hợp giá ETH/USD 0xF79D6aFBb6dA890132F9D7c355e3015f15F3406F là bộ gửi yêu cầu dữ liệu giá đến oracle: 0x7e94a8a23687d8c7058ba5625db2ce358bcbd244. Nếu oracle trả về dữ liệu được yêu cầu, bạn có thể tìm ra địa chỉ hợp đồng được trả về: 0xF79D6aFBb6dA890132F9D7c355e3015f15F3406F, ID phương pháp cần gọi: 6 A 9705 B 4 và thời gian hết hạn: 1618185924.
Phản hồi nút ngoài Chuỗi
3.1 Gọi off- Chuỗi fulfillmentOracleRequest

Kiểm tra đầu tiên:
onlyAuthorizedNode: Người gọi hàm (msg.sender) phải là chủ sở hữu của hợp đồng hoặc nằm trong danh sách được ủy quyền;
isValidRequest: vẫn kiểm tra xem requestId có tồn tại trong ánh xạ cam kết hay không;
Nối payment, callbackAddress, _callbackFunctionId và expiration và kiểm tra xem chúng có phải là giá trị tương ứng của requestId trong bản đồ cam kết hay không.
Nếu tất cả các bước kiểm tra này đều vượt qua, chi phí của yêu cầu lần sẽ được cộng vào withdrawalableTokens để ghi lại số tiền có thể rút được. Sau đó, _requestId sẽ bị xóa khỏi bản đồ cam kết. Cuối cùng, hãy tính toán lượng gas còn lại để xem liệu nó có lớn hơn MINIMUM_CONSUMER_GAS_LIMIT hay không, tức là lượng gas tối thiểu cần thiết để thực hiện hàm điều chỉnh hồi của hợp đồng đã điều chỉnh hồi yêu cầu.
Nếu tất cả các bước kiểm tra trên đều thành công, hàm điều chỉnh hồi của hợp đồng người yêu cầu có thể được gọi chính thức dưới dạng lệnh gọi.
Phản hồi cho yêu cầu phải nhanh nhất có thể, vì vậy bạn nên sử dụng dịch vụ nút của ZAN ( https://zan.top/home/node-service?chInfo=ch_WZ ) để cải thiện tốc độ phản hồi. Bạn có thể tìm liên kết RPC tương ứng trong bảng điều khiển dịch vụ nút để tăng tốc độ gửi giao dịch ra khỏi Chuỗi.

3.2 Hàm điều chỉnh hồi
Trước đó chúng ta đã biết từ oracleRequest rằng hàm điều chỉnh hồi id là 6 A 9705 B 4 và phương pháp là "chainlinkCallback(bytes 32, int 256"


validateChainlinkCallback là một hàm có thể tùy chỉnh, sau đây là một trình sửa đổi:

Kiểm tra trong pendingRequests xem _requestId có khớp với oracle được yêu cầu hay không. Và phát ra sự kiện ChainlinkFulfilled:

Nếu tất cả các bước kiểm tra đều đạt, các phản hồi có thể được xử lý thêm, trong đó bản đồ câu trả lời được cập nhật. Nếu là một oracle về giá, dữ liệu giá sẽ được gán cho currentPrice để cập nhật giá cho phù hợp:

Trên đây là toàn bộ quy trình của dịch vụ oracle nói chung.
Chúng ta hãy lấy phương pháp “requestEthereumPrice” trong hợp đồng “TestnetConsumer” do Chainlink cung cấp làm ví dụ để giải thích ngắn gọn về quy trình phản hồi yêu cầu của price oracle. Hàm này được định nghĩa như sau:

Chức năng mà nó thực hiện là lấy giá giao dịch của ETH/USD từ API được chỉ định (cryptocompare). Các tham số được truyền vào hàm là địa chỉ oracle và jobId được chỉ định. Sau khi thiết lập một loạt các tham số yêu cầu, hãy gọi phương pháp "sendChainlinkRequestTo" để gửi yêu cầu. "sendChainlinkRequestTo" là một phương pháp giao diện được định nghĩa trong thư viện do Chainlink cung cấp và được định nghĩa như sau:

Sau khi nhận được lệnh chuyển, hợp đồng Oracle sẽ kích hoạt phương pháp"onTokenTransfer"phương pháp kiểm tra tính hợp lệ của lệnh chuyển và ghi lại thông tin dữ liệu chi tiết hơn bằng cách phát hành sự kiện "OracleRequest".
Nhật ký này có thể được tìm thấy trong nhật ký của hợp đồng oracle. Nút trong Chuỗi sẽ đăng ký nhật ký của chủ đề. Sau khi có được thông tin nhật ký đã ghi lại, nút sẽ phân tích thông tin cụ thể của yêu cầu và lấy kết quả của yêu cầu thông qua lệnh gọi API mạng. Sau đó, bằng cách gửi giao dịch, hãy gọi phương pháp"fulfillOracleRequest" trong hợp đồng Oracle để gửi dữ liệu tới Chuỗi .
Sau khi thực hiện sê-ri kiểm tra, phương pháp này sẽ trả kết quả về hợp đồng người tiêu dùng thông qua địa chỉ điều chỉnh hồi và hàm điều chỉnh hồi đã ghi lại trước đó.
Là một nhà phát triển, tôi chỉ muốn sử dụng giá cặp tiền tệ hiện có mà không cần tự mình chỉ định các URL này. Có thể như vậy được không?
Câu trả lời là có. Cách đầu tiên để chính thức dụng như sau:

Đầu tiên, mỗi cặp giao dịch có một Nguồn cấp giá riêng, còn gọi là Aggregator, thực chất là AggregatorProxy, như được hiển thị bên dưới:

Việc triển khai cụ thể của giao diện này tương đối đơn giản, bạn có thể tham khảo cặp Aave/ETH: https://etherscan.io/address/0x6Df09E975c830ECae5bd4eD9d90f3A95a4f88012#code
Tổng cộng có 5 phương pháp truy vấn:
decimals(): Số chữ số có độ chính xác của dữ liệu giá được trả về, thường là 8 hoặc 18
description(): thường là tên cặp giao dịch, chẳng hạn như ETH/USD
version(): Chủ yếu được sử dụng để xác định loại Aggregator mà Proxy trỏ tới
getRoundData(_roundId): Lấy dữ liệu giá hiện tại dựa trên ID vòng
latestRoundData(): Lấy dữ liệu giá mới nhất
Trong hầu hết các tình huống ứng dụng, hợp đồng có thể chỉ cần đọc giá mới nhất, nghĩa là gọi phương pháp cuối cùng và câu trả lời trong tham số trả về là giá mới nhất.
Ngoài ra, hầu hết các ứng dụng đều sử dụng USD làm đơn vị đo lường để đọc mã thông báo. Nếu vậy, bạn sẽ thấy rằng độ chính xác của cặp tiền được định giá bằng USD đều là 8 chữ số, do đó nhìn chung không cần phải xử lý các vấn đề về độ chính xác khác nhau cho các mã thông báo khác nhau.
Bài viết này được viết bởi XiG (tài khoản X @SHXiGi ) của ZAN Team (tài khoản X @zan_team ).

