From 1eb392d8ddac5c21c202a9c211e4c13b67189786 Mon Sep 17 00:00:00 2001 From: "yongen.loong" Date: Mon, 2 Sep 2024 21:10:14 +0800 Subject: [PATCH] docs: update aetherlink --- docs/resources/aetherLink/index.md | 278 ++++++++++++++++++----------- 1 file changed, 173 insertions(+), 105 deletions(-) diff --git a/docs/resources/aetherLink/index.md b/docs/resources/aetherLink/index.md index 9eed21c..90cf221 100644 --- a/docs/resources/aetherLink/index.md +++ b/docs/resources/aetherLink/index.md @@ -4,163 +4,231 @@ title: AetherLink description: Transfer tamper-proof data from off-chain to on-chain --- -# AetherLink +## 1. Background -## 1. Introduction +There is a growing need for decentralized applications (dApps) to access data feeds that are frequently updated, reliable, and secure. AetherLink Oracles is a leading oracle provider directly fulfilling this need. -A web3 oracle is essential for decentralized networks, enabling smart contracts to access real-world data like weather -updates or market prices. However, the security of oracles is a concern, as malicious actions can compromise contract -execution. Choosing reliable oracle services is crucial in web3 development. Moreover, oracles not only link blockchains -to real-world data but also enable the retrieval of information from other blockchain networks. +## 2. Target -![oracle](/img/oracle.png) +For developers of the AELF ecosystem, this article will provide a complete guide to accessing the AetherLink **VRF** and **Datafeeds** contracts. -## 2. aelf Oracle Services - AetherLink +## 3. Operational -Among the various products in aelf, some products may require information from other chains. For example, the [eBridge](https://ebridge.exchange/) -product needs to access lock-up information of NFTs on the Ethereum chain. This necessitates the use of oracle services -for data interchange. To expand the aelf ecosystem and enhance user services, it is essential to establish the -foundational services for oracle mechanisms. +### 3.1 Preparation -In this context, AetherLink, aelf's proprietary oracle service, has been developed. AetherLink primarily focuses on -providing Verified Random Function (VRF) capabilities and Data Feeds functionality. +#### 3.1.1 Import proto -## 3. What can AetherLink do? +First, you need to import oracle-related proto files into your contract csproj file. -### A. Random number generator +```xml + + + Protobuf\Proto\oracle_common_message.proto + + + + + Protobuf\Proto\oracle_contract.proto + + + + + Protobuf\Proto\request_interface.proto + + +``` -Generating random numbers directly on the blockchain is a complex and challenging problem. Due to the deterministic -nature of blockchain, the results of smart contract executions must be consistent across all nodes in the network. -Therefore, random number generation in smart contracts needs to be verifiable and replicable, ensuring that each node -obtains the same result when executing the same smart contract. +You can find the latest proto files through the following link: -However, traditional pseudo-random number generation methods, such as using block hashes, face challenges in this -environment. If block hashes are used, each node in the smart contract would generate the same random number using -identical inputs, making it impossible to achieve true randomness. +- https://github.com/AetherLinkProject/aetherLink-contracts/blob/master/protobuf/oracle_common_message.proto +- https://github.com/AetherLinkProject/aetherLink-contracts/blob/master/protobuf/oracle_contract.proto +- https://github.com/AetherLinkProject/aetherLink-contracts/blob/master/protobuf/request_interface.proto -AetherLink VRF introduces the concept of Verifiable Random Function (VRF), employing algorithms designed by -cryptographic experts to ensure that the generated random numbers on-chain are verifiable and unpredictable. AetherLink -VRF provides a secure, decentralized, and verifiable mechanism for generating random numbers in smart contracts, -delivering high-quality randomness without compromising security and usability. +#### 3.1.2 Protobuf file -The key advantages of using AetherLink VRF include: +Then you also need to introduce request_interface.proto in the proto file to inherit the oracle callback function to receive the oracle report -#### 1. Verifiability: +```protobuf +import "aelf/core.proto"; +import "aelf/options.proto"; +import "request_interface.proto"; +import "google/protobuf/empty.proto"; +import "google/protobuf/wrappers.proto"; +import "google/protobuf/timestamp.proto"; -Cryptographic proofs are used to demonstrate the authenticity of the random number generation process, allowing smart -contracts and users to verify the legitimacy of the generated random numbers. +service { + ... -#### 2. Unpredictability: + option (aelf.base) = "request_interface.proto"; -Utilizing VRF algorithms ensures that random numbers generated by AetherLink VRF are unpredictable, even under identical -input conditions. + ... +``` -#### 3. Decentralization: +#### 3.1.3 Set Oracle Address -AetherLink VRF operates across multiple nodes, enhancing the decentralization of random number generation and mitigating -risks associated with a single point of control. +Set the Oracle Contract Address in your contract state according to your operating environment. -```csharp title="Random number generator code segment" -{ - var random = State.ConsensusContract.GetRandomHash.Call(new Int64Value - { - Value = specificData.BlockNumber - }); +- MainNet **AELF** Address : `BGhrBNTPcLccaxPv6hHJrn4CHHzeMovTsrkhFse5o2nwfvQyG` +- MainNet **tDVV** Address : `BGhrBNTPcLccaxPv6hHJrn4CHHzeMovTsrkhFse5o2nwfvQyG` +- TestNet **AELF** Address : `21Fh7yog1B741yioZhNAFbs3byJ97jvBmbGAPPZKZpHHog5aEg` +- TestNet **tDVW** Address : `21Fh7yog1B741yioZhNAFbs3byJ97jvBmbGAPPZKZpHHog5aEg` - var alpha = HashHelper.ConcatAndCompute(random, specificData.PreSeed); +#### 3.1.4 Apply subscription ID - Context.ECVrfVerify(publicKey, alpha.ToByteArray(), report.Result.ToByteArray(), out var beta); - Assert(beta != null && beta.Length > 0, "Vrf verification fail."); +Before initiating a task to the oracle, you need to contact AetherLink to apply for a subscription number for your task. Later, you can manage the service fee based on this subscription id.Remember that you only have the right to use your own `subscription id`. - var randomHash = Hash.LoadFromByteArray(beta); +:::note - for (var i = 0; i < specificData.NumWords; i++) - { - response.Data.Add(HashHelper.ConcatAndCompute(randomHash, HashHelper.ComputeFrom(i))); - } +If you have prepared all the above work, we will explain the VRF and Datafeeds scenarios separately. You need to choose the appropriate contract as the entry point for your development scenario - return response; -} -``` +Currently, we provide two oracle capabilities: + +- VRF: VRF provides cryptographically secure randomness for your blockchain-based applications. +- Datafeeds: Provide data sources for Web2 asset prices for contracts. -The process involves obtaining a random hash from the consensus contract, verifying it through ECVRF with a public key -and an oracle-reported result, and then creating a set of random words based on the verified data. +::: -### B. DataFeeds +### 3.2 DataFeeds -The AetherLink Data Feeds Coordinator provides a quick and reliable connection for smart contracts to real-world data, -encompassing data types like asset prices, reserve balances, NFT floor prices, and L2 sequencer health. +First, you need to define how to initiate a Datafeeds oracle request in the contract. -Data feeds from the Coordinator include Price Feeds, Proof of Reserve Feeds, NFT Floor Price Feeds, Rate and Volatility -Feeds, and L2 Sequencer Uptime Feeds. For example, Price Feeds are crucial for real-time actions in applications like -decentralized finance (DeFi) platforms. These feeds aggregate data from multiple sources, ensuring reliability through -the Decentralized Data Model and Offchain Reporting. +```csharp +State.OracleContract.SendRequest.Send(new SendRequestInput +{ + SubscriptionId = SubscriptionId, + RequestTypeIndex = 1, + SpecificData = specificData, + TraceId = XXXXX // HASH +}); +``` + +- `OracleContract`: This is the target contract address, the oracle contract. +- `SendRequest`: This is the method name for sending the Datafeeds Request to the target contract. +- `SendRequestInput`: This is the input parameter of the method for sending transactions to the target contract + +| Param Name | Explanation | | +| ---------------- | ------------------------------------------------------------------ | --------------------------- | +| SubscriptionId | manage the service fee based on this subscription id | int32 | +| RequestTypeIndex | Task Type | int32, 1=Datafeeds \| 2=VRF | +| SpecificData | Detailed description of Datafeeds tasks | ByteString | +| TraceId | This ID can be used as a unique index to manage your oracle tasks. | Aelf.Hash | -Components of a data feed involve the Consumer (onchain or offchain applications using Data Feeds), Coordinator contract -(onchain coordinator pointing to the oracle), and Oracle contract (receiving periodic data updates from the oracle -network and storing aggregated data onchain). +#### 3.2.1 How to generate DataFeeds SpecificData -Different data feeds cater to specific use cases, such as Proof of Reserve Feeds indicating the status of reserves, NFT -Floor Price Feeds providing the lowest NFT prices, and Rate and Volatility Feeds offering interest rate curve data. L2 -sequencer uptime feeds track the last known status of the sequencer on Layer 2 networks. +Here we take the example of collecting ELF-USTD currency price pairs every 10 minutes. Note the red part: + +```json +{ + "Cron": "0 */10 * * * ?", + "DataFeedsJobSpec": { + "Type": "PriceFeeds", + "CurrencyPair": "ELF/USDT" + } +} +``` -## 4. AetherLink Contracts +After determining the task description, you need to convert it into a bystring type and then put it into the input parameter of the oracle request. -To achieve these functionalities, aelf has deployed 3 main contracts. Their names and their functionalities are: +```csharp +var jobSpec = "{\"Cron\": \"0 */10 * * * ?\",\"DataFeedsJobSpec\": {\"Type\": \"PriceFeeds\",\"CurrencyPair\": \"ELF/USDT\"}}"; -| Contract Type | Functions and Responsibilities | -| ------------------- | ----------------------------------------------------------------------------------------------------------------------- | -| Consumer Contract | 1. Task initiation and receipt of results
2. Result inquiry | -| Coordinate Contract | 1. Task management
2. VRF Proof verification and random number generation
3. Threshold signature verification | -| Oracle Contract | 1. Node management
2. Task event publication | +var specificData = new AetherLink.Contracts.DataFeeds.Coordinator.SpecificData +{ + Data = ByteString.CopyFromUtf8(jobSpec), + DataVersion = 0 +}.ToByteString() -### A. Consumer Contract +var sendRequestInput = new SendRequestInput +{ + SubscriptionId = 1, + RequestTypeIndex = 1, + SpecificData = specificData, + TraceId = HhfWg...Y9kao31 // HASH +} +``` -A contract deployed by the user, for which the official interface proto file is provided by the platform for task -initiation and result retrieval. Users are required to reference and implement this interface. The main functionalities -include: +#### 3.2.2 How to handle oracle pricefeeds callbacks -#### a. Task initiation: +Here you need to override the HandleOracleFulfillment method -Initiated by the user, subsequently invoking the Oracle contract to carry out subsequent operations. +```csharp +public override Empty HandleOracleFulfillment(HandleOracleFulfillmentInput input) +{ + ... -#### b. Result retrieval: + var priceList = LongList.Parser.ParseFrom(input.Response); -Callback function executed by the Oracle contract, writing the results back to the user contract. Users are responsible -for implementing the logic for data storage. + var longList = new LongList { Data = { priceList.Data } }; -### B. Coordinator Contract + var sortedList = longList.Data.ToList().OrderBy(l => l).ToList(); -A contract provided by the platform. Based on the current products, PriceFeeds and VRF, two corresponding Coordinator -contracts need to be deployed. The main functionalities include: + var round = State.LatestRound.Value.Add(1); -#### a. Task management: + var newPriceRoundData = new PriceRoundData + { + Price = sortedList[sortedList.Count / 2], + RoundId = round, + UpdatedAt = Context.CurrentBlockTime + }; + State.LatestPriceRoundData.Value = newPriceRoundData; + State.PriceRoundData[round] = newPriceRoundData; + State.LatestRound.Value = round; +} +``` -Generates a unique 1D for tasks along with task details, storing them in the contract. +The above code will parse the oracle callback and record each result in the contract, providing the latest and historical currency price query capabilities. -#### b. Threshold signature verification (for non-algorithmic verification thresholds) / VRF Proof verification: +### 3.3 VRF -After nodes submit task results, if it's a PriceFeeds-type task, the Coordinator contract is responsible for verifying -the submitted signatures through threshold signature verification. If it's a VRF-type task, the Coordinator contract -needs to reconstruct the random hash from the submitted proof. +First, you need to define how to initiate a VRF oracle request in the contract. -### C. Oracle Contract +```csharp +State.OracleContract.SendRequest.Send(new SendRequestInput +{ + SubscriptionId = SubscriptionId, + RequestTypeIndex = 2, + SpecificData = specificData, + TraceId = XXXXX // HASH +}); +``` -The official contract provided decouples Oracle nodes and Consumer contracts from business logic. It has three main -functionalities: +- `OracleContract`: This is the target contract address, the oracle contract. +- `SendRequest`: This is the method name for sending the VRF Request to the target contract. +- `SendRequestInput`: This is the input parameter of the method for sending transactions to the target contract -#### a. Subscription Feature: +| Param Name | Explanation | | +| ---------------- | ------------------------------------------------------------------ | --------------------------- | +| SubscriptionId | manage the service fee based on this subscription id | int32 | +| RequestTypeIndex | Task Type | int32, 1=Datafeeds \| 2=VRF | +| SpecificData | Detailed description of Datafeeds tasks | ByteString | +| TraceId | This ID can be used as a unique index to manage your oracle tasks. | Aelf.Hash | -Provides subscription management functionality for user contracts, enabling task initiation through subscriptions. +#### 3.3.1 How to generate VRF SpecificData -#### b. Node Management Feature: +First, you need to specify an oracle node to perform your random number generation task, -Implements the registration and role assignment of Oracle nodes, with configurable parameters for threshold signature. +```csharp +var keyHashs = State.OracleContract.GetProvingKeyHashes.Call(new Empty()); +var keyHash = keyHashs[0] +``` -#### c. Event-Driven Feature: +Then bind the oracle node Keyhash in your VRF task and specify the number of random numbers to be generated. -Oracle nodes need to listen to events from this contract, triggering corresponding operations when events are emitted. +```csharp +var specificData = new AetherLink.Contracts.VRF.Coordinator.SpecificData +{ + KeyHash = keyHash, + NumWords = 3, + RequestConfirmations = 1 +}.ToByteString() +``` -The whole project structure: +#### 3.3.2 How to handle oracle pricefeeds callbacks -![structure](/img/AetherLinkStructure.png) \ No newline at end of file +```csharp +public override Empty HandleOracleFulfillment(HandleOracleFulfillmentInput input) +{ + var randomHashList = HashList.Parser.ParseFrom(input.Response); + State.RandomHashes[input.RequestId] = randomHashList; +} +```