diff --git a/erazhu31/TLS Notary DOracle/Dockerfile b/erazhu31/TLS Notary DOracle/Dockerfile new file mode 100644 index 00000000..83c98c71 --- /dev/null +++ b/erazhu31/TLS Notary DOracle/Dockerfile @@ -0,0 +1,9 @@ +FROM node:11-alpine + +COPY src/oracle.js /src/oracle.js + + +RUN npm i https ethers fs get-ssl-certificate +ENTRYPOINT ["node", "src/oracle.js"] + + diff --git a/erazhu31/TLS Notary DOracle/smart-contract/.gitignore b/erazhu31/TLS Notary DOracle/smart-contract/.gitignore new file mode 100644 index 00000000..20d2fe75 --- /dev/null +++ b/erazhu31/TLS Notary DOracle/smart-contract/.gitignore @@ -0,0 +1,6 @@ +node_modules +build + +package-lock.json +yarn.lock + diff --git a/erazhu31/TLS Notary DOracle/smart-contract/README.md b/erazhu31/TLS Notary DOracle/smart-contract/README.md new file mode 100644 index 00000000..893dfb85 --- /dev/null +++ b/erazhu31/TLS Notary DOracle/smart-contract/README.md @@ -0,0 +1,75 @@ +iExec Dencentralized Oracle System +================================== + +About iExec +----------- + +Thanks to iExec, it is possible to achieve onchain consensus about the result of an offchain application. Applications are represented by smart contracts and execution results can be made available onchain with all the necessary proof. + +Building an oracle application +------------------------------ + +iExec applications produce different outputs. +* The consensus is achieved based on a deterministic value describing the application output. By default this is the hash of the result archive, but can be overriden by the content of `/iexec_out/determinism.iexec`. Upon successful verification, this is stored onchain in the `task.resultDigest` field. +* The actual result. By default this is the IPFS address of a (potentially encrypted) archive containing the outputs, but can be overridden by the content of `/iexec_out/callback.iexec`. Upon successful verification, this is stored onchain in the `task.results` field. + +An iExec oracle application such as the one used in the price-oracle example uses these 2 elements to produce verified results to the blockchain. + +Given a set of parameters, the application produces a self-describing result, encodes it in a way that can be interpreted onchain, stores it in `/iexec_out/callback.iexec` so that is can be accessed onchain, and stores the hash of this encoded value to perform the consensus. + +For example, given the parameters "BTC USD 9 2019-04-11T13:08:32.605Z" the price-oracle application will: + +1. Retreive the price of BTC in USD at 2019-04-11T13:08:32.605Z +2. Multiply this value by 10e9 (to capture price value more accurately as it will be represented by an integer onchain) +3. encode the date, the description ("btc-usd-9") and the value using `abi.encode` +4. Store this result in `/iexec_out/callback.iexec` +5. hash the result and store it in `/iexec_out/determinism.iexec` + +iExec will then achieve PoCo consensus on the `/iexec_out/determinism.iexec` value, and will store both the `/iexec_out/determinism.iexec` and the `/iexec_out/callback.iexec` onchain. + +Given a taskID, it is possible to retrieve all the details of the computation as described above. The oracle smart contract just needs to retrieve the information, verify the validity of the execution and process the encoded result. Thanks to the PoCo consensus, anyone can require a computation and ask the oracle to update itself in a trustless manner. + +How to setup an oracle contract +------------------------------- + +1. Record the address of the iExec Hub and Clerk contracts + +2. Register the requirements needed for a result to be processed + * Which application (single, any, whitelist?) + * Which dataset (single, any, whitelist?) + * Which workerpool (single, any, whitelist?) + * Minimum level of trust + * Mandatory tag + +How to update an oracle contract +-------------------------------- + +1. Send the taskID of a valid execution to the oracle smart contract. +2. The oracle smart contract retrieves details about this task from the iexec's smart contracts. +3. The oracle smart contract verifies the execution is valid (authorized app, dataset, workerpool, trust level and tags). +4. The oracle smart contract verifies the hash of the results correspond to the resultDigest that achieved consensus, thus verifying the validity of the result field. +5. The oracle smart contract decodes the results using `abi.decode`. +6. The oracle smart contract processes the results. In the case of the price oracle, this means storing the value if it is more recent than the one currently recorded. + +How to read price from the iExec price oracle +--------------------------------------------- + +Just query the oracle `values` field with the id of the requested field. For example, to get the most recent price of BTC in USD with 9 place precision (as described above), query `values(keccak256(bytes("BTC-USD-9")))` and this will return a structure containing the value, the associate date, and the details of the request. + +Deployed addresses +------------------ + +1. **Kovan:** + + price oracle: `https://kovan.etherscan.io/address/0x3b9f1a9aecb1991f3818f45bd4cc735f4bee93ac` + + app whitelist: `https://kovan.etherscan.io/address/0x651a09cdff5a6669ea8bf05be11eff4aa9cbfdaf` + + whitelist contains: + + * `0xf92f39545340ce2fd6f4248a689fca4f660ae42f` + * `0xe01bccbcab54c42f999b6ce88d63d3a5e96cfdb7` + + Whitelist is administered by: + + * `0x7bd4783FDCAD405A28052a0d1f11236A741da593` diff --git a/erazhu31/TLS Notary DOracle/smart-contract/contracts/Migrations.sol b/erazhu31/TLS Notary DOracle/smart-contract/contracts/Migrations.sol new file mode 100644 index 00000000..85e11e6e --- /dev/null +++ b/erazhu31/TLS Notary DOracle/smart-contract/contracts/Migrations.sol @@ -0,0 +1,24 @@ +pragma solidity ^0.5.8; + +import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; + +contract Migrations is Ownable +{ + uint256 public lastCompletedMigration; + + constructor() + public + { + } + + function setCompleted(uint completed) public onlyOwner + { + lastCompletedMigration = completed; + } + + function upgrade(address newAddress) public onlyOwner + { + Migrations upgraded = Migrations(newAddress); + upgraded.setCompleted(lastCompletedMigration); + } +} diff --git a/erazhu31/TLS Notary DOracle/smart-contract/contracts/TlsNotaryOracle.sol b/erazhu31/TLS Notary DOracle/smart-contract/contracts/TlsNotaryOracle.sol new file mode 100644 index 00000000..6104218b --- /dev/null +++ b/erazhu31/TLS Notary DOracle/smart-contract/contracts/TlsNotaryOracle.sol @@ -0,0 +1,59 @@ +pragma solidity ^0.5.8; +pragma experimental ABIEncoderV2; + +import "openzeppelin-solidity/contracts/ownership/Ownable.sol"; +import "iexec-doracle-base/contracts/IexecDoracle.sol"; + +contract TlsNotaryOracle is Ownable, IexecDoracle +{ + struct TimedValue + { + bytes32 oracleCallID; + string result; + } + + mapping(bytes32 => TimedValue) public values; + + event ValueUpdated( + bytes32 indexed id, + bytes32 indexed oracleCallID, + string oldResult, + string newResult + ); + + // Use _iexecHubAddr to force use of custom iexechub, leave 0x0 for autodetect + constructor(address _iexecHubAddr) + public IexecDoracle(_iexecHubAddr) + {} + + function updateEnv( + address _authorizedApp + , address _authorizedDataset + , address _authorizedWorkerpool + , bytes32 _requiredtag + , uint256 _requiredtrust + ) + public onlyOwner + { + _iexecDoracleUpdateSettings(_authorizedApp, _authorizedDataset, _authorizedWorkerpool, _requiredtag, _requiredtrust); + } + + function decodeResults(bytes memory results) + public pure returns(string memory) + { return abi.decode(results, (string)); } + + function processResult(bytes32 _oracleCallID) + public + { + string memory result; + + // Parse results + result = decodeResults(_iexecDoracleGetVerifiedResult(_oracleCallID)); + + // Process results + bytes32 id = keccak256(bytes(result)); + emit ValueUpdated(id, _oracleCallID, values[id].result, result); + values[id].oracleCallID = _oracleCallID; + values[id].result = result; + } +} diff --git a/erazhu31/TLS Notary DOracle/smart-contract/daemon/Dockerfile b/erazhu31/TLS Notary DOracle/smart-contract/daemon/Dockerfile new file mode 100644 index 00000000..741c1478 --- /dev/null +++ b/erazhu31/TLS Notary DOracle/smart-contract/daemon/Dockerfile @@ -0,0 +1,25 @@ +FROM node:8-alpine + +# changing user +USER root + +# add necessary packages +RUN apk add --no-cache git python make g++ + +# create a work directory inside the container +RUN mkdir /app +WORKDIR /app + +# copy project files +COPY . . + +# install utilities +RUN npm install -g yarn ts-node typescript + +# install dependencies +RUN yarn + +# making entrypoint executable +RUN chmod +x entrypoint.sh + +ENTRYPOINT ["./entrypoint.sh"] diff --git a/erazhu31/TLS Notary DOracle/smart-contract/daemon/daemon.ts b/erazhu31/TLS Notary DOracle/smart-contract/daemon/daemon.ts new file mode 100644 index 00000000..78f7fe6b --- /dev/null +++ b/erazhu31/TLS Notary DOracle/smart-contract/daemon/daemon.ts @@ -0,0 +1,145 @@ +import { ethers } from 'ethers'; +import * as utils from './utils'; + +const IexecHub = require('iexec-poco/build/contracts/IexecHub.json'); +const IexecClerk = require('iexec-poco/build/contracts/IexecClerk.json'); +const IERC734 = require('iexec-poco/build/contracts/IERC734.json'); +// const PriceOracle = require('../build/contracts/PriceOracle.json'); + +// Mainnet & Kovan deployment use the old ABI +const PriceOracle = { abi:[{"constant":true,"inputs":[{"name":"_identity","type":"address"},{"name":"_hash","type":"bytes32"},{"name":"_signature","type":"bytes"}],"name":"verifySignature","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_authorizedApp","type":"address"},{"name":"_authorizedDataset","type":"address"},{"name":"_authorizedWorkerpool","type":"address"},{"name":"_requiredtag","type":"bytes32"},{"name":"_requiredtrust","type":"uint256"}],"name":"updateEnv","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"m_authorizedApp","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"results","type":"bytes"}],"name":"decodeResults","outputs":[{"name":"","type":"uint256"},{"name":"","type":"string"},{"name":"","type":"uint256"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":false,"inputs":[{"name":"_doracleCallId","type":"bytes32"},{"name":"","type":"bytes"}],"name":"receiveResult","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"renounceOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"m_authorizedDataset","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"isOwner","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"m_iexecClerk","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"m_iexecHub","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"m_authorizedWorkerpool","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"bytes32"}],"name":"values","outputs":[{"name":"oracleCallID","type":"bytes32"},{"name":"date","type":"uint256"},{"name":"value","type":"uint256"},{"name":"details","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"m_requiredtrust","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_oracleCallID","type":"bytes32"}],"name":"processResult","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"m_requiredtag","outputs":[{"name":"","type":"bytes32"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[{"name":"_iexecHubAddr","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"name":"id","type":"bytes32"},{"indexed":true,"name":"oracleCallID","type":"bytes32"},{"indexed":false,"name":"oldDate","type":"uint256"},{"indexed":false,"name":"oldValue","type":"uint256"},{"indexed":false,"name":"newDate","type":"uint256"},{"indexed":false,"name":"newValue","type":"uint256"}],"name":"ValueChange","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"doracleCallId","type":"bytes32"}],"name":"ResultReady","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"previousOwner","type":"address"},{"indexed":true,"name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"}]}; + +export default class Daemon +{ + address: string; + wallet: ethers.Wallet; + doracle: ethers.Contract; + iexechub: ethers.Contract; + iexecclerk: ethers.Contract; + requester: string; + + settings: + { + authorizedApp: string, + authorizedDataset: string, + authorizedWorkerpool: string, + requiredtag: string, + requiredtrust: number, + GROUPMEMBER_PURPOSE: number, + }; + + constructor(address: string, wallet: ethers.Wallet, requester: string = null) + { + this.address = address; + this.wallet = wallet; + this.requester = requester; + } + + async start(listener: boolean = true) : Promise + { + console.log(`Connecting to contracts`); + this.doracle = new ethers.Contract(this.address, PriceOracle.abi, this.wallet); + console.log(`- doracle ${this.doracle.address}`); + this.iexechub = new ethers.Contract(await this.doracle.m_iexecHub(), IexecHub.abi, this.wallet.provider); + console.log(`- iexechub ${this.iexechub.address}`); + this.iexecclerk = new ethers.Contract(await this.doracle.m_iexecClerk(), IexecClerk.abi, this.wallet.provider); + console.log(`- iexecclerk ${this.iexecclerk.address}`); + + console.log(`Retrieving doracle settings:`); + this.settings = { + authorizedApp: await this.doracle.m_authorizedApp(), + authorizedDataset: await this.doracle.m_authorizedDataset(), + authorizedWorkerpool: await this.doracle.m_authorizedWorkerpool(), + requiredtag: await this.doracle.m_requiredtag(), + requiredtrust: await this.doracle.m_requiredtrust(), + GROUPMEMBER_PURPOSE: await this.iexecclerk.GROUPMEMBER_PURPOSE(), + } + console.log(`- authorizedApp: ${this.settings.authorizedApp}` ); + console.log(`- authorizedDataset: ${this.settings.authorizedDataset}` ); + console.log(`- authorizedWorkerpool: ${this.settings.authorizedWorkerpool}`); + console.log(`- requiredtag: ${this.settings.requiredtag}` ); + console.log(`- requiredtrust: ${this.settings.requiredtrust}` ); + console.log(`- GROUPMEMBER_PURPOSE: ${this.settings.GROUPMEMBER_PURPOSE}` ); + + if (listener) + { + console.log(`Starting event listener.`) + this.doracle.on("ResultReady(bytes32)", this.trigger.bind(this)); + console.log(`====== Daemon is running ======`); + } + else + { + console.log(`====== Daemon is ready ======`); + } + } + + async checkIdentity(identity: string, candidate: string, purpose: number): Promise + { + try + { + return identity == candidate || await (new ethers.Contract(identity, IERC734.abi, this.wallet.provider)).keyHasPurpose(utils.addrToKey(candidate), purpose); + } + catch + { + console.log(identity, candidate) + return false; + } + } + + async getVerifiedResult(doracleCallId: string) : Promise + { + let task = await this.iexechub.viewTask(doracleCallId); + let deal = await this.iexecclerk.viewDeal(task.dealid); + + if (this.requester) + { + utils.require(deal.requester == this.requester, "requester filtered (this is not an error)"); + } + + utils.require(task.status == 3, "result-not-available"); + utils.require(task.resultDigest == ethers.utils.keccak256(task.results), "result-not-validated-by-consensus"); + utils.require(this.settings.authorizedApp == ethers.constants.AddressZero || await this.checkIdentity(this.settings.authorizedApp, deal.app.pointer, this.settings.GROUPMEMBER_PURPOSE), "unauthorized-app"); + utils.require(this.settings.authorizedDataset == ethers.constants.AddressZero || await this.checkIdentity(this.settings.authorizedDataset, deal.dataset.pointer, this.settings.GROUPMEMBER_PURPOSE), "unauthorized-dataset"); + utils.require(this.settings.authorizedWorkerpool == ethers.constants.AddressZero || await this.checkIdentity(this.settings.authorizedWorkerpool, deal.workerpool.pointer, this.settings.GROUPMEMBER_PURPOSE), "unauthorized-workerpool"); + utils.require(this.settings.requiredtrust <= deal.trust, "invalid-trust"); + + // Check tag - must be done byte by byte. + let [ ta, rta ] = [ deal.tag, this.settings.requiredtag ].map(ethers.utils.arrayify); + for (var i in ta) utils.require((rta[i] & ~ta[i]) == 0, "invalid-tag"); + + return task.results; + } + + async checkData(data: string) : Promise + { + let [ date, details, value ] = ethers.utils.defaultAbiCoder.decode(["uint256", "string", "uint256"], data); + let entry = await this.doracle.values(ethers.utils.solidityKeccak256(["string"],[details])); + utils.require(entry.date < date, "new-value-is-too-old"); + } + + trigger(doracleCallId: string, event: {}) + { + process.stdout.write(`${new Date().toISOString()} | processing ${doracleCallId} ... `); + this.getVerifiedResult(doracleCallId) + .then(data => { + this.checkData(data) + .then(() => { + this.doracle.processResult(doracleCallId) + .then(tx => { + process.stdout.write(`success\n`); + }) + .catch(e => { + const txHash = e.transactionHash; + const data = e.data[txHash]; + process.stdout.write(`Error: ${data.error} (${data.reason})\n`); + }); + }) + .catch(reason => { + process.stdout.write(`Invalid results (${reason})\n`); + }); + }) + .catch(reason => { + process.stdout.write(`Failled to verify results (${reason})\n`); + }); + } +} diff --git a/erazhu31/TLS Notary DOracle/smart-contract/daemon/docker-compose.yml b/erazhu31/TLS Notary DOracle/smart-contract/daemon/docker-compose.yml new file mode 100644 index 00000000..44a8ad9a --- /dev/null +++ b/erazhu31/TLS Notary DOracle/smart-contract/daemon/docker-compose.yml @@ -0,0 +1,10 @@ +version: '2' +services: + doracle-daemon: + image: iexechub/iexec-doracle-daemon:latest + environment: + - DORACLE_ADDR=xxx + - MNEMONIC=xxxx + - PROVIDER=xxx + - REQUESTER=xxxx + restart: unless-stopped diff --git a/erazhu31/TLS Notary DOracle/smart-contract/daemon/entrypoint.sh b/erazhu31/TLS Notary DOracle/smart-contract/daemon/entrypoint.sh new file mode 100644 index 00000000..9a2c9d0a --- /dev/null +++ b/erazhu31/TLS Notary DOracle/smart-contract/daemon/entrypoint.sh @@ -0,0 +1,3 @@ +#!/bin/sh +echo "[INFO] Launching DOracle Daemon" +/usr/local/bin/ts-node launch.ts diff --git a/erazhu31/TLS Notary DOracle/smart-contract/daemon/launch.ts b/erazhu31/TLS Notary DOracle/smart-contract/daemon/launch.ts new file mode 100644 index 00000000..1896f256 --- /dev/null +++ b/erazhu31/TLS Notary DOracle/smart-contract/daemon/launch.ts @@ -0,0 +1,14 @@ +import { ethers } from 'ethers'; +import Daemon from './daemon'; + +// mainnet 0xed4a0189511859427c33dcc7c85fdd36575ae946 +// kovan 0x3b9F1a9aeCb1991f3818f45bd4CC735f4BEE93Ac + +let doracle_addr: string = process.env.DORACLE_ADDR; +let private_key: string = process.env.MNEMONIC; +let provider: ethers.providers.Provider = ethers.getDefaultProvider(process.env.PROVIDER); + +let wallet: ethers.Wallet = new ethers.Wallet(private_key, provider); +let daemon: Daemon = new Daemon(doracle_addr, wallet, process.env.REQUESTER); + +daemon.start(); diff --git a/erazhu31/TLS Notary DOracle/smart-contract/daemon/package.json b/erazhu31/TLS Notary DOracle/smart-contract/daemon/package.json new file mode 100644 index 00000000..20757f0b --- /dev/null +++ b/erazhu31/TLS Notary DOracle/smart-contract/daemon/package.json @@ -0,0 +1,31 @@ +{ + "name": "price-feed-doracle", + "version": "0.0.1", + "description": "Contracts and tools for the iExec based price feed DOracle", + "repository": { + "type": "git", + "url": "git+https://github.com/iExecBlockchainComputing/price-feed-doracle.git" + }, + "bugs": { + "url": "https://github.com/iExecBlockchainComputing/price-feed-doracle.git/issues" + }, + "files": [ + "/build", + "/contracts", + "daemon" + ], + "author": "iExec", + "license": "ISC", + "homepage": "https://github.com/iExecBlockchainComputing/price-feed-doracle.git#readme", + "dependencies": { + "chai": "^4.2.0", + "ethereumjs-util": "^5.2.0", + "iexec-doracle-base": "^0.0.4", + "iexec-poco": "^3.0.35", + "iexec-solidity": "^0.0.7", + "multiaddr": "^6.0.6", + "openzeppelin-solidity": "^2.2.0", + "openzeppelin-test-helpers": "^0.1.5", + "rlc-faucet-contract": "^2.0.0" + } +} diff --git a/erazhu31/TLS Notary DOracle/smart-contract/daemon/utils/addrToKey.ts b/erazhu31/TLS Notary DOracle/smart-contract/daemon/utils/addrToKey.ts new file mode 100644 index 00000000..a194f9af --- /dev/null +++ b/erazhu31/TLS Notary DOracle/smart-contract/daemon/utils/addrToKey.ts @@ -0,0 +1,6 @@ +import { ethers } from 'ethers'; + +export default function(addr: string) : string +{ + return ethers.utils.hexZeroPad(addr, 32).toString().toLowerCase(); +} diff --git a/erazhu31/TLS Notary DOracle/smart-contract/daemon/utils/index.ts b/erazhu31/TLS Notary DOracle/smart-contract/daemon/utils/index.ts new file mode 100644 index 00000000..a9767469 --- /dev/null +++ b/erazhu31/TLS Notary DOracle/smart-contract/daemon/utils/index.ts @@ -0,0 +1,2 @@ +export { default as require } from "./require"; +export { default as addrToKey } from "./addrToKey"; diff --git a/erazhu31/TLS Notary DOracle/smart-contract/daemon/utils/require.ts b/erazhu31/TLS Notary DOracle/smart-contract/daemon/utils/require.ts new file mode 100644 index 00000000..56eadba2 --- /dev/null +++ b/erazhu31/TLS Notary DOracle/smart-contract/daemon/utils/require.ts @@ -0,0 +1,4 @@ +export default function(value: boolean, reason: string = "") : void +{ + if (!value) throw Error(reason); +} diff --git a/erazhu31/TLS Notary DOracle/smart-contract/migrations/1_initial_migration.js b/erazhu31/TLS Notary DOracle/smart-contract/migrations/1_initial_migration.js new file mode 100644 index 00000000..66673a2e --- /dev/null +++ b/erazhu31/TLS Notary DOracle/smart-contract/migrations/1_initial_migration.js @@ -0,0 +1,5 @@ +var Migrations = artifacts.require("./tools/Migrations.sol"); + +module.exports = function(deployer) { + deployer.deploy(Migrations, {gas: 500000}); +}; diff --git a/erazhu31/TLS Notary DOracle/smart-contract/migrations/2_deploy_contracts.js b/erazhu31/TLS Notary DOracle/smart-contract/migrations/2_deploy_contracts.js new file mode 100644 index 00000000..4b68320c --- /dev/null +++ b/erazhu31/TLS Notary DOracle/smart-contract/migrations/2_deploy_contracts.js @@ -0,0 +1,9 @@ +var TlsNotaryOracle = artifacts.require("TlsNotaryOracle"); + +module.exports = async function(deployer, network, accounts) +{ + await deployer.deploy(TlsNotaryOracle, "0x0000000000000000000000000000000000000000", { gas: 2500000 }); + TlsNotaryOracleInstance = await TlsNotaryOracle.deployed(); + console.log("TlsNotaryOracle deployed at address: " + TlsNotaryOracleInstance.address); + +}; diff --git a/erazhu31/TLS Notary DOracle/smart-contract/package.json b/erazhu31/TLS Notary DOracle/smart-contract/package.json new file mode 100644 index 00000000..cecad941 --- /dev/null +++ b/erazhu31/TLS Notary DOracle/smart-contract/package.json @@ -0,0 +1,28 @@ +{ + "name": "price-feed-doracle", + "version": "0.0.1", + "description": "Contracts and tools for the iExec based price feed DOracle", + "repository": { + "type": "git", + "url": "git+https://github.com/iExecBlockchainComputing/price-feed-doracle.git" + }, + "bugs": { + "url": "https://github.com/iExecBlockchainComputing/price-feed-doracle.git/issues" + }, + "files": [ + "/build", + "/contracts", + "daemon" + ], + "author": "iExec", + "license": "ISC", + "homepage": "https://github.com/iExecBlockchainComputing/price-feed-doracle.git#readme", + "dependencies": { + "iexec-doracle-base": "^0.0.6", + "iexec-poco": "^3.0.35", + "iexec-solidity": "^0.0.7", + "openzeppelin-solidity": "^2.2.0", + "truffle": "^5.0.25", + "truffle-hdwallet-provider": "^1.0.12" + } +} diff --git a/erazhu31/TLS Notary DOracle/smart-contract/truffle-config.js b/erazhu31/TLS Notary DOracle/smart-contract/truffle-config.js new file mode 100644 index 00000000..7fc54e77 --- /dev/null +++ b/erazhu31/TLS Notary DOracle/smart-contract/truffle-config.js @@ -0,0 +1,107 @@ +/** + * Use this file to configure your truffle project. It's seeded with some + * common settings for different networks and features like migrations, + * compilation and testing. Uncomment the ones you need or modify + * them to suit your project as necessary. + * + * More information about configuration can be found at: + * + * truffleframework.com/docs/advanced/configuration + * + * To deploy via Infura you'll need a wallet provider (like truffle-hdwallet-provider) + * to sign your transactions before they're sent to a remote public node. Infura accounts + * are available for free at: infura.io/register. + * + * You'll also need a mnemonic - the twelve word phrase the wallet uses to generate + * public/private key pairs. If you're publishing your code to GitHub make sure you load this + * phrase from a file you've .gitignored so it doesn't accidentally become public. + * + */ + +// const HDWalletProvider = require('truffle-hdwallet-provider'); +// const infuraKey = "fj4jll3k....."; +// +// const fs = require('fs'); +// const mnemonic = fs.readFileSync(".secret").toString().trim(); + +var HDWalletProvider = require("truffle-hdwallet-provider"); + +module.exports = { + /** + * Networks define how you connect to your ethereum client and let you set the + * defaults web3 uses to send transactions. If you don't specify one truffle + * will spin up a development blockchain for you on port 9545 when you + * run `develop` or `test`. You can ask a truffle command to use a specific + * network from the command line, e.g + * + * $ truffle test --network + */ + + networks: { + // Useful for testing. The `development` name is special - truffle uses it by default + // if it's defined here and no other network is specified at the command line. + // You should run a client (like ganache-cli, geth or parity) in a separate terminal + // tab if you use this network and you must also set the `host`, `port` and `network_id` + // options below to some value. + // + // development: { + // host: "127.0.0.1", // Localhost (default: none) + // port: 8545, // Standard Ethereum port (default: none) + // network_id: "*", // Any network (default: none) + // }, + + // Another network with more advanced options... + // advanced: { + // port: 8777, // Custom port + // network_id: 1342, // Custom network + // gas: 8500000, // Gas sent with each transaction (default: ~6700000) + // gasPrice: 20000000000, // 20 gwei (in wei) (default: 100 gwei) + // from:
, // Account to send txs from (default: accounts[0]) + // websockets: true // Enable EventEmitter interface for web3 (default: false) + // }, + + // Useful for deploying to a public network. + // NB: It's important to wrap the provider as a function. + // ropsten: { + // provider: () => new HDWalletProvider(mnemonic, `https://ropsten.infura.io/v3/YOUR-PROJECT-ID`), + // network_id: 3, // Ropsten's id + // gas: 5500000, // Ropsten has a lower block limit than mainnet + // confirmations: 2, // # of confs to wait between deployments. (default: 0) + // timeoutBlocks: 200, // # of blocks before a deployment times out (minimum/default: 50) + // skipDryRun: true // Skip dry run before migrations? (default: false for public nets ) + // }, + + // Useful for private networks + // private: { + // provider: () => new HDWalletProvider(mnemonic, `https://network.io`), + // network_id: 2111, // This network is yours, in the cloud. + // production: true // Treats this network as if it was a public net. (default: false) + // } + + kovan: { + provider: () => new HDWalletProvider(process.env.MNEMONIC, "https://kovan.infura.io/v3/0fcbbdc72ccb436bbe963c59912b12d9"), + network_id: '*', + gasPrice: 1000000000, //1Gwei + } + }, + + // Set default mocha options here, use special reporters etc. + mocha: { + // timeout: 100000 + }, + + // Configure your compilers + compilers: { + solc: { + version: "0.5.8", // Fetch exact version from solc-bin (default: truffle's version) + docker: true, // Use "0.5.1" you've installed locally with docker (default: false) + settings: { // See the solidity docs for advice about optimization and evmVersion + optimizer: { + enabled: true, + runs: 200 + }, + evmVersion: "byzantium" + } + } + } +} diff --git a/erazhu31/TLS Notary DOracle/src/oracle.js b/erazhu31/TLS Notary DOracle/src/oracle.js new file mode 100644 index 00000000..279b6996 --- /dev/null +++ b/erazhu31/TLS Notary DOracle/src/oracle.js @@ -0,0 +1,43 @@ +const https = require('https'); +const ethers = require('ethers'); +const fs = require('fs'); + +const sslCertificate = require('get-ssl-certificate') + + +const root = 'iexec_out'; +const determinismFilePath = `${root}/determinism.iexec`; +const callbackFilePath = `${root}/callback.iexec`; +const errorFilePath = `${root}/error.iexec`; + + + + + +/***************************************************************************** + * ARGUMENTS * + *****************************************************************************/ +let URL = process.argv.slice(2); + + + + +/***************************************************************************** + * EXECUTE * + *****************************************************************************/ + +sslCertificate.get(`${URL}`).then(function (certificate) { + + + let res= JSON.stringify(certificate) + + let iexecCallback = ethers.utils.defaultAbiCoder.encode(['string'], [res]); + let iexecDeterminism = ethers.utils.keccak256(iexecCallback); + fs.writeFile(callbackFilePath, iexecCallback , (err) => {}); + fs.writeFile(determinismFilePath, iexecDeterminism, (err) => {}); + + + console.log(certificate) + +}); +