From 010b5e7d91fe83704a449d39160af89e8143d8da Mon Sep 17 00:00:00 2001 From: Nikhil Date: Sat, 30 Nov 2019 02:59:21 +0530 Subject: [PATCH 1/2] flight delay oracle --- flight-delay/.DS_Store | Bin 0 -> 6148 bytes flight-delay/app/Dockerfile | 7 + flight-delay/app/entrypoint.sh | 2 + flight-delay/app/flightDelay.js | 63 ++++++++ flight-delay/chain.json | 29 ++++ flight-delay/deployed.json | 5 + flight-delay/iexec.json | 35 +++++ flight-delay/orders.json | 15 ++ flight-delay/smart-contract/.DS_Store | Bin 0 -> 8196 bytes flight-delay/smart-contract/.gitignore | 6 + flight-delay/smart-contract/README.md | 75 +++++++++ .../contracts/FlightDelayOracle.sol | 68 ++++++++ .../smart-contract/contracts/Migrations.sol | 24 +++ flight-delay/smart-contract/daemon/Dockerfile | 25 +++ flight-delay/smart-contract/daemon/daemon.ts | 145 ++++++++++++++++++ .../smart-contract/daemon/docker-compose.yml | 10 ++ .../smart-contract/daemon/entrypoint.sh | 3 + flight-delay/smart-contract/daemon/launch.ts | 14 ++ .../smart-contract/daemon/package.json | 31 ++++ .../smart-contract/daemon/utils/addrToKey.ts | 6 + .../smart-contract/daemon/utils/index.ts | 2 + .../smart-contract/daemon/utils/require.ts | 4 + .../migrations/1_initial_migration.js | 5 + .../migrations/2_deploy_contracts.js | 8 + flight-delay/smart-contract/package.json | 28 ++++ flight-delay/smart-contract/truffle.js | 62 ++++++++ 26 files changed, 672 insertions(+) create mode 100644 flight-delay/.DS_Store create mode 100644 flight-delay/app/Dockerfile create mode 100644 flight-delay/app/entrypoint.sh create mode 100644 flight-delay/app/flightDelay.js create mode 100644 flight-delay/chain.json create mode 100644 flight-delay/deployed.json create mode 100644 flight-delay/iexec.json create mode 100644 flight-delay/orders.json create mode 100644 flight-delay/smart-contract/.DS_Store create mode 100644 flight-delay/smart-contract/.gitignore create mode 100644 flight-delay/smart-contract/README.md create mode 100644 flight-delay/smart-contract/contracts/FlightDelayOracle.sol create mode 100644 flight-delay/smart-contract/contracts/Migrations.sol create mode 100644 flight-delay/smart-contract/daemon/Dockerfile create mode 100644 flight-delay/smart-contract/daemon/daemon.ts create mode 100644 flight-delay/smart-contract/daemon/docker-compose.yml create mode 100644 flight-delay/smart-contract/daemon/entrypoint.sh create mode 100644 flight-delay/smart-contract/daemon/launch.ts create mode 100644 flight-delay/smart-contract/daemon/package.json create mode 100644 flight-delay/smart-contract/daemon/utils/addrToKey.ts create mode 100644 flight-delay/smart-contract/daemon/utils/index.ts create mode 100644 flight-delay/smart-contract/daemon/utils/require.ts create mode 100644 flight-delay/smart-contract/migrations/1_initial_migration.js create mode 100644 flight-delay/smart-contract/migrations/2_deploy_contracts.js create mode 100644 flight-delay/smart-contract/package.json create mode 100644 flight-delay/smart-contract/truffle.js diff --git a/flight-delay/.DS_Store b/flight-delay/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..4dc40adc6072819c649852d888c73a80124e71be GIT binary patch literal 6148 zcmeHKJ5Iwu5S>XU2Rl#=e zo~(M~U%dHrrPsv^(!P7W?a$LBODC}48>1GDXo~q>Qc6d3Mc0&3TAKM2;#OzAOEHbH z!UVAk)Z(g4-Y;dgFwU6nprgv1`%+FDqs-libIh({j{H%|Les<;Fb0f)tuY|yDWuu< zXr(b=3>X7T2IPDQpn{=d;n5u(DBKeO*nrsy>h9+s7>EHFDi$7Lfv`^n`c&2@2J72_ zeLDQ1#upxaIkIP_?xF<=a=Gf?-S0NGw{9#>?%Du4fQm?5;c=OQio1#tD_8LW)Cuf?RDhvk;Sm;y{RlW3tS|<) G%D@+m#&WFy literal 0 HcmV?d00001 diff --git a/flight-delay/app/Dockerfile b/flight-delay/app/Dockerfile new file mode 100644 index 00000000..aac1ee4e --- /dev/null +++ b/flight-delay/app/Dockerfile @@ -0,0 +1,7 @@ +FROM node:11-alpine +COPY flightDelay.js /src/flightDelay.js +COPY entrypoint.sh /entrypoint.sh +RUN npm i axios ethers fs +RUN mkdir iexec_out +RUN chmod +x /entrypoint.sh +ENTRYPOINT ["/entrypoint.sh"] \ No newline at end of file diff --git a/flight-delay/app/entrypoint.sh b/flight-delay/app/entrypoint.sh new file mode 100644 index 00000000..cb36ad47 --- /dev/null +++ b/flight-delay/app/entrypoint.sh @@ -0,0 +1,2 @@ +#!/bin/sh +node src/flightDelay.js $@ \ No newline at end of file diff --git a/flight-delay/app/flightDelay.js b/flight-delay/app/flightDelay.js new file mode 100644 index 00000000..0ce87220 --- /dev/null +++ b/flight-delay/app/flightDelay.js @@ -0,0 +1,63 @@ +const ethers = require('ethers'); +const fs = require('fs'); +const axios = require('axios'); + + +const root = 'iexec_out'; +const determinismFilePath = `${root}/determinism.iexec`; +const callbackFilePath = `${root}/callback.iexec`; +const errorFilePath = `${root}/error.iexec`; + + +/***************************************************************************** + * ARGUMENTS * + *****************************************************************************/ + +var [id , timestamp] = process.argv.slice(2).map(s => s); + +// var timestampInMili = new Date().getTime(); +// var timestamp = parseInt(timestampInMili/1000) +// console.log(longi); +// console.log(lati); +// console.log(timestamp); +/***************************************************************************** + * HTTP QUERY * + *****************************************************************************/ + +let url = `https://iexec-flight-data.herokuapp.com/delay/${id},${timestamp}`; +/***************************************************************************** + * EXECUTE * + *****************************************************************************/ +axios.get(url) +.then(res=>{ + // console.log(res); + var result = res.data; + if(result.status == "found") + { + var delay = parseInt(result.delay); + console.log(delay); + var iexeccallback = ethers.utils.defaultAbiCoder.encode(['uint256', 'uint256', 'uint256'], [timestamp, id, delay]); + var iexecconsensus = ethers.utils.keccak256(iexeccallback); + fs.writeFile(callbackFilePath, iexeccallback , (err) => {}); + fs.writeFile(determinismFilePath, iexecconsensus, (err) => {}); + } + else + { + throw 'ivalid id'; + } + +}) +.catch(err=>{ + fs.writeFile( + errorFilePath, + err.toString(), + (error) => {} + ); + fs.writeFile( + determinismFilePath, + ethers.utils.solidityKeccak256(['string'],[err.toString()]), + (error) => {} + ); + throw new Error(err); +}) + diff --git a/flight-delay/chain.json b/flight-delay/chain.json new file mode 100644 index 00000000..700ab0e4 --- /dev/null +++ b/flight-delay/chain.json @@ -0,0 +1,29 @@ +{ + "default": "kovan", + "chains": { + "dev": { + "host": "http://localhost:8545", + "sms": "http://localhost:5000", + "id": "17", + "hub": "0x60E25C038D70A15364DAc11A042DB1dD7A2cccBC" + }, + "ropsten": { + "host": "https://ropsten.infura.io/v3/f3e0664e01504f5ab2b4360853ce0dc7", + "id": "3" + }, + "rinkeby": { + "host": "https://rinkeby.infura.io/v3/f3e0664e01504f5ab2b4360853ce0dc7", + "id": "4" + }, + "kovan": { + "host": "https://kovan.infura.io/v3/f3e0664e01504f5ab2b4360853ce0dc7", + "id": "42", + "sms": "https://sms-kovan.iex.ec" + }, + "mainnet": { + "host": "https://mainnet.infura.io/v3/f3e0664e01504f5ab2b4360853ce0dc7", + "id": "1", + "sms": "https://sms-mainnet.iex.ec" + } + } +} \ No newline at end of file diff --git a/flight-delay/deployed.json b/flight-delay/deployed.json new file mode 100644 index 00000000..d6a966d9 --- /dev/null +++ b/flight-delay/deployed.json @@ -0,0 +1,5 @@ +{ + "app": { + "42": "0x70A4ffB9aa9106f4E604D8E2Db77178FdB8CfD1a" + } +} \ No newline at end of file diff --git a/flight-delay/iexec.json b/flight-delay/iexec.json new file mode 100644 index 00000000..e3b7cfb1 --- /dev/null +++ b/flight-delay/iexec.json @@ -0,0 +1,35 @@ +{ + "description": "My iExec ressource description, must be at least 150 chars long in order to pass the validation checks. Describe your application, dataset or workerpool to your users", + "license": "MIT", + "author": "?", + "social": { + "website": "?", + "github": "?" + }, + "logo": "logo.png", + "buyConf": { + "params": "", + "tag": "0x0000000000000000000000000000000000000000000000000000000000000000", + "trust": "0", + "callback": "0x0000000000000000000000000000000000000000" + }, + "app": { + "owner": "0xf3Ba773Af9e30B8187E2Abbd0B4F3218273127D0", + "name": "flightDelay", + "type": "DOCKER", + "multiaddr": "registry.hub.docker.com/nikhil3000/flight-delay:1.0.0", + "checksum": "0xa3277ff23fcb7fac1562f385b8570b67595cd115f0c125e8d428ef29c44335aa", + "mrenclave": "" + }, + "order": { + "apporder": { + "app": "0x70A4ffB9aa9106f4E604D8E2Db77178FdB8CfD1a", + "appprice": "0", + "volume": "1000000", + "tag": "0x0000000000000000000000000000000000000000000000000000000000000000", + "datasetrestrict": "0x0000000000000000000000000000000000000000", + "workerpoolrestrict": "0x0000000000000000000000000000000000000000", + "requesterrestrict": "0x0000000000000000000000000000000000000000" + } + } +} \ No newline at end of file diff --git a/flight-delay/orders.json b/flight-delay/orders.json new file mode 100644 index 00000000..f33fb5f0 --- /dev/null +++ b/flight-delay/orders.json @@ -0,0 +1,15 @@ +{ + "42": { + "apporder": { + "app": "0x70A4ffB9aa9106f4E604D8E2Db77178FdB8CfD1a", + "appprice": "0", + "volume": "1000000", + "tag": "0x0000000000000000000000000000000000000000000000000000000000000000", + "datasetrestrict": "0x0000000000000000000000000000000000000000", + "workerpoolrestrict": "0x0000000000000000000000000000000000000000", + "requesterrestrict": "0x0000000000000000000000000000000000000000", + "salt": "0x4a944d1d291c4bc73a77af5622f396a61e4d2a03a5f2259741a3fc78614f5725", + "sign": "0xb55a27276356637f2fbb62379c4215f5e7db9656a2edc6d33b423cf1212f9f695a48ab8e9ab16e89efe9c445d022191a768c6737c8aadd160cc219537db6b9b31b" + } + } +} \ No newline at end of file diff --git a/flight-delay/smart-contract/.DS_Store b/flight-delay/smart-contract/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..212c5412b0ff3fbbdb052eb39a86e59cba54a296 GIT binary patch literal 8196 zcmeHMF>ezw6#kqPlm>)gfl4f=c448YGeWvn*MWhBY)D8n353#1E@~6zTlfPYbzose zEUb(m_7407{sJ?6&$b%-a!192sCcgI?_|H{ci(5`^|x+1xD v!uo_&irAG7tqU8QjuY(<0pjUD40)Z TimedValue) public values; + + event ValueUpdated( + bytes32 indexed id, + bytes32 indexed oracleCallID, + uint256 oldDate, + uint256 oldDelay, + uint256 newDate, + uint256 newDelay + ); + + // 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(uint256, uint256 , uint256) + { return abi.decode(results, (uint256, uint256 , uint256 )); } + + function processResult(bytes32 _oracleCallID) + public + { + uint256 date; + uint256 flightId; + uint256 delay; //correct to 3 decimal places + + // Parse results + (date, flightId, delay) = decodeResults(_iexecDoracleGetVerifiedResult(_oracleCallID)); + + // Process results + bytes32 id = keccak256(abi.encode(flightId)); + require(values[id].date < date, "new-value-is-too-old"); + emit ValueUpdated(id, _oracleCallID, values[id].date, values[id].delay, date, delay); + values[id].oracleCallID = _oracleCallID; + values[id].date = date; + values[id].flightId = flightId; + values[id].delay = delay; + } +} diff --git a/flight-delay/smart-contract/contracts/Migrations.sol b/flight-delay/smart-contract/contracts/Migrations.sol new file mode 100644 index 00000000..85e11e6e --- /dev/null +++ b/flight-delay/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/flight-delay/smart-contract/daemon/Dockerfile b/flight-delay/smart-contract/daemon/Dockerfile new file mode 100644 index 00000000..741c1478 --- /dev/null +++ b/flight-delay/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/flight-delay/smart-contract/daemon/daemon.ts b/flight-delay/smart-contract/daemon/daemon.ts new file mode 100644 index 00000000..78f7fe6b --- /dev/null +++ b/flight-delay/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/flight-delay/smart-contract/daemon/docker-compose.yml b/flight-delay/smart-contract/daemon/docker-compose.yml new file mode 100644 index 00000000..44a8ad9a --- /dev/null +++ b/flight-delay/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/flight-delay/smart-contract/daemon/entrypoint.sh b/flight-delay/smart-contract/daemon/entrypoint.sh new file mode 100644 index 00000000..9a2c9d0a --- /dev/null +++ b/flight-delay/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/flight-delay/smart-contract/daemon/launch.ts b/flight-delay/smart-contract/daemon/launch.ts new file mode 100644 index 00000000..1896f256 --- /dev/null +++ b/flight-delay/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/flight-delay/smart-contract/daemon/package.json b/flight-delay/smart-contract/daemon/package.json new file mode 100644 index 00000000..20757f0b --- /dev/null +++ b/flight-delay/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/flight-delay/smart-contract/daemon/utils/addrToKey.ts b/flight-delay/smart-contract/daemon/utils/addrToKey.ts new file mode 100644 index 00000000..a194f9af --- /dev/null +++ b/flight-delay/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/flight-delay/smart-contract/daemon/utils/index.ts b/flight-delay/smart-contract/daemon/utils/index.ts new file mode 100644 index 00000000..a9767469 --- /dev/null +++ b/flight-delay/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/flight-delay/smart-contract/daemon/utils/require.ts b/flight-delay/smart-contract/daemon/utils/require.ts new file mode 100644 index 00000000..56eadba2 --- /dev/null +++ b/flight-delay/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/flight-delay/smart-contract/migrations/1_initial_migration.js b/flight-delay/smart-contract/migrations/1_initial_migration.js new file mode 100644 index 00000000..66673a2e --- /dev/null +++ b/flight-delay/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/flight-delay/smart-contract/migrations/2_deploy_contracts.js b/flight-delay/smart-contract/migrations/2_deploy_contracts.js new file mode 100644 index 00000000..af37388e --- /dev/null +++ b/flight-delay/smart-contract/migrations/2_deploy_contracts.js @@ -0,0 +1,8 @@ +var FlightDelayOracle = artifacts.require("FlightDelayOracle"); + +module.exports = async function(deployer, network, accounts) +{ + await deployer.deploy(FlightDelayOracle, "0x0000000000000000000000000000000000000000", { gas: 2500000 }); + FlightDelayOracleInstance = await FlightDelayOracle.deployed(); + console.log("FlightDelayOracle deployed at address: " + FlightDelayOracleInstance.address); +}; diff --git a/flight-delay/smart-contract/package.json b/flight-delay/smart-contract/package.json new file mode 100644 index 00000000..cecad941 --- /dev/null +++ b/flight-delay/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/flight-delay/smart-contract/truffle.js b/flight-delay/smart-contract/truffle.js new file mode 100644 index 00000000..4f36088b --- /dev/null +++ b/flight-delay/smart-contract/truffle.js @@ -0,0 +1,62 @@ +var HDWalletProvider = require("truffle-hdwallet-provider"); + +module.exports = +{ + networks: + { + docker: + { + host: "iexec-geth-local", + port: 8545, + network_id: "*", // Match any network id, + gasPrice: 22000000000, //22Gwei + }, + development: + { + host: "localhost", + port: 8545, + network_id: "*", // Match any network id, + gasPrice: 22000000000, //22Gwei + }, + coverage: + { + host: "localhost", + port: 8555, // <-- If you change this, also set the port option in .solcover.js. + network_id: "*", + gas: 0xFFFFFFFFFFF, // <-- Use this high gas value + gasPrice: 0x01 // <-- Use this low gas price + }, + mainnet: + { + provider: () => new HDWalletProvider(process.env.MNEMONIC, "https://mainnet.infura.io/v3/f3e0664e01504f5ab2b4360853ce0dc7"), + network_id: '1', + gasPrice: 22000000000, //22Gwei + }, + ropsten: + { + provider: () => new HDWalletProvider(process.env.MNEMONIC, "https://ropsten.infura.io/v3/f3e0664e01504f5ab2b4360853ce0dc7"), + network_id: '3', + gasPrice: 22000000000, //22Gwei + }, + kovan: { + provider: () => new HDWalletProvider(process.env.MNEMONIC, "https://kovan.infura.io/v3/f3e0664e01504f5ab2b4360853ce0dc7"), + network_id: '42', + gasPrice: 1000000000, //1Gwei + } + }, + compilers: { + solc: { + version: "0.5.10", + settings: { + optimizer: { + enabled: true, + runs: 200 + } + } + } + }, + mocha: + { + enableTimeouts: false + } +}; From 04ff0bb799e1a4e283bf41700c8f919c1477d3a8 Mon Sep 17 00:00:00 2001 From: Nikhil Date: Tue, 3 Dec 2019 17:46:07 +0530 Subject: [PATCH 2/2] changed the api --- .DS_Store | Bin 14340 -> 14340 bytes flight-delay/app/flightDelay.js | 27 ++++++++++++--------------- flight-delay/deployed.json | 2 +- flight-delay/iexec.json | 6 +++--- flight-delay/orders.json | 6 +++--- 5 files changed, 19 insertions(+), 22 deletions(-) diff --git a/.DS_Store b/.DS_Store index 89183c668c7022992e51475a4f953b5fbeff1f5c..613098212b98be7ebe0d7810c7719e66d9af6d14 100644 GIT binary patch literal 14340 zcmeHNO^6&t6n;HB`b>eFqF~#6agb;e5%u8YvVS=)FA^2F6bC=&v*GB#odD+h>7>Q7XsXF`<%(G=CDtHZb z7|0mN7|0mN7-*9LUVCx$EDOu*nlX?ukTGBxVE<6S$>mT~E{3IX9k_4^&(Ar8HwS(r z4>0!%Q8^Tqi(zS0p<`50hN?l7Vg#W&?iW}bMBnTj@mr`_QjXlwMFg;T%G;&!i7s8Z*9MhqTN?mY8|}aVR77X9wyLD z;FNbmCb4%hkFtpWj)KWKa5;fL=5-7*GY+3$K=*{;v*mgem(+Kp9UCN%@AQ6F=dtCs zr>ilCOVL;SnY}3LrF~#%$}sg1*eX#`Gu82+!<0uubF%SwXn3R~`Zo?=uA}!##yFED zHKLPfm{v6+!g$z)Q80y>S9Q?64-GjEQnWSFH8;}Rlc;}rz@koRNA`5fWbj?#^ju=ze&d9x+4Os7bRF{Lr2qlCeF{TgKXGU$VEf z8Z?syW^$GBBi zJaVyzNs`mZ3uu!1XcVi>06OhbM9&#{N`Zs>S#Rcb~meAVp{u}oe$nRW&fth zYHXVrTOL>{yk6?QG0}(g1y)XDShYshA??0+uk8z~D{b{X_t@79?&r-6Jc4pN?WUcM zrC8UM*Yap+o4c;TW{;G#{@o8P>t4xtEG0{N5Ut?%IQZj;WeVep*{=cHtUIQ79ahK^ zG&RCL?%4!siS*o7+fRuaG2+%VH1Yyl)QdQ640!R*$-I%O(IMTJ9ax(cVvmMKnm_BW zS0X(9h(+kBPmalC$y7uf;a4;wv!==@URz)^G@_0V8W0&NiRhk@CWs=*xUZ5Wy@>V$ z#W?N7npZ<_&AMKjc%9RT8Z;b4Ck>(oDT(OZ6*1pDk};xWNsY*OxIQ{&)}SKB+yLSs zPsE#JA0jb%brh=3%jKeHxF zWF8HLi#ne2*DFz-`bzay7-3oq3WT@jSNF_gvf8kE)S(g!@X*(jnM+Hw`*=!aFHD8|1aU$5;F6ly*N+v357q zB}Y+`oWc<-qDk~{G+s>nc?@I6iTpW}QAj)*8cX-1{(2>vx4*V%JoQOD$&v~Y70|Fn z6z*wE0g*F?IG6Dv5*iv&{#Jjz649UEH6Rl8Nkqw#9z4yL(ieL)wEfFIiF(1QSE4v|-Jkd=030wJBqCIlCAgylZw$tT9dXG&-}EHkFka#TuC)ANN`- z@(ORbt~Rav=;&;vT&+x^H+To8+vKeC7@Zt(*0dkw3{H(tM_O}0ryJ{&$gkz?n+K;J z*|W{16w1(B^wUm^QqI69vD$FvJp~jMdJK2w@SiV&I3apBRbM0Q`34A6btLBTzDxB; zq6NLU*W1z4ynG20@uuo9ZKf?4=i^|chLyBx=JNo4FPPEKQ9ef+4R5MUtRXpSt1ivg z=8<-7k=%9PX2(lgHptPm)H*b$XPDC!*eT^0yp*|}yFzv2hyyL5IS~-P^av#Y$B!;g0Y!6#qX|eCQvM=-kD>1rf z?A#x~@9>QnuQbkzYvLg}x)XIZj;_~%BT-&rTQ_X6rRc=7zEvF$2kN_U?Zr*RBrz*l zjWKr=7}ax$>D(@h$&raM)Mffnk<8n*P3CREg7Cy5f7cdu{QLQTCqu!v|I2XM(fs>= zBa~e-1~LZzn+yc`;nCr3z{Y{I@8ECk3OJv^$uj40@`2w*1sC%<9!m2$9{%Ca@wOPD z=z?cM{1fG3SmGCsfBZv0vk!$>aSl7~*jJG2Kyp?uSMX#>&pKA$PY~I+UOBS-zrL3s Yd!$)zFZ-gIOp{)4@^sw`|DXK-Z_we9zW@LL delta 1680 zcmcgsO>7fK6dr>!8M~X*iJkRNlFi!Lm;`L&*nvn@TM2?9aj2Tgs69X%+i~Q$v3D)U zsa;Y-gmR!(i;_M?3K1Zh1L_Zrs8A850tv*yy`)gl!Z8wRPp!nE%BiBA*|oiPrC#x2 z{k`vd@6F7oP)UH$oPKGANmy8IDXTne58Leh7{jTMSe*!dZW>J%ExZ zh4LBY$dPzjiBq2ZbM?;jw+|1tu57nmZzY7lQ-3eq_ZP|co+qY_wY!JF67X~;>iKng z+b_aepoohjED!ko0@2{zLo3T}h;{rxejls0h<5m3qLXVTmOIN>+W#vn7Oj#F9T2x} z5~YXInu)CKXEHus%~-SrpxDJV6SulH@o%&0)?_}YLkTMU4RYpGb!YF{ zdAMLVV~v2T_A6xdt!m$Z!_{!`2HF9a9BF*-Q?8in?a}94LSv71qC89xkgheM0 z7S{$@U9YYxx&(OQ;+hF_cNzP>RC}&>OEq}Edjo%QLuJ!F644;-DfIBL*;B?l1$DjG zdnKYlsy(CHVy_iG7p!nbNZ^l8t2uuN644;dxg_uq=*ta`SF}A*FSMW{wNH*ZB$-k4 ziE9~9=^I}^go7TgKO6HcFb`9)oYHWH3*qR_IwE}Zrd&tf>$kl z1~oX1Lh-^}wrboT4gc zEslkSaQJ{v43CVKeB#3BXwWB)gb$WVCSo5Le(h*9^Wn*bk4mS`v*RFSVAqiSUe^BV z&vlB_1M(=8PHI<|iQLxCl?JKt9ktIsU>RyvI|_Xe$;oL&PEyJMQTG}?u&NIHxjR5K zNCzHui*U?S#$Ro!T6@0({`PQsxa19f$CT>irqDdKLb}linhrPnKf`a_R+~&n9v$*< zPAcQSQjeMcg#n3ZkS_f|;vqUv#uEiqdp02H&;cQD5#L%;m1|z11|NAZ;7`6**~@zz zaBdH$hx_2^;4C?Nlc}_QaL5Ml51Fw>z{#NscAx)+?P77S7v#O19zMt4Y^yyh`$E8V zaC-QNT>O*O(0*p0U~4>gqd>nNZD8 s); +var [id, timestamp] = process.argv.slice(2).map(s => s); + +var appId = '0ddf43fd'; +var appKey = 'c8663643d1b8d907717810f38f97ffb1'; // var timestampInMili = new Date().getTime(); // var timestamp = parseInt(timestampInMili/1000) // console.log(longi); // console.log(lati); // console.log(timestamp); +//flightID = 1023084433 /***************************************************************************** * HTTP QUERY * *****************************************************************************/ -let url = `https://iexec-flight-data.herokuapp.com/delay/${id},${timestamp}`; +let url = `https://api.flightstats.com/flex/flightstatus/rest/v2/json/flight/status/${id}?appId=${appId}&appKey=${appKey}`; /***************************************************************************** * EXECUTE * *****************************************************************************/ @@ -32,19 +36,12 @@ axios.get(url) .then(res=>{ // console.log(res); var result = res.data; - if(result.status == "found") - { - var delay = parseInt(result.delay); - console.log(delay); - var iexeccallback = ethers.utils.defaultAbiCoder.encode(['uint256', 'uint256', 'uint256'], [timestamp, id, delay]); - var iexecconsensus = ethers.utils.keccak256(iexeccallback); - fs.writeFile(callbackFilePath, iexeccallback , (err) => {}); - fs.writeFile(determinismFilePath, iexecconsensus, (err) => {}); - } - else - { - throw 'ivalid id'; - } + var delay = parseInt(result.flightStatus.delays.departureGateDelayMinutes); + console.log(delay); + var iexeccallback = ethers.utils.defaultAbiCoder.encode(['uint256', 'uint256', 'uint256'], [timestamp, id, delay]); + var iexecconsensus = ethers.utils.keccak256(iexeccallback); + fs.writeFile(callbackFilePath, iexeccallback , (err) => {}); + fs.writeFile(determinismFilePath, iexecconsensus, (err) => {}); }) .catch(err=>{ diff --git a/flight-delay/deployed.json b/flight-delay/deployed.json index d6a966d9..19f87fcc 100644 --- a/flight-delay/deployed.json +++ b/flight-delay/deployed.json @@ -1,5 +1,5 @@ { "app": { - "42": "0x70A4ffB9aa9106f4E604D8E2Db77178FdB8CfD1a" + "42": "0x2bEe1A8d963D9f3d8Da6Db5A5e23aA4dB537811B" } } \ No newline at end of file diff --git a/flight-delay/iexec.json b/flight-delay/iexec.json index e3b7cfb1..18294047 100644 --- a/flight-delay/iexec.json +++ b/flight-delay/iexec.json @@ -17,13 +17,13 @@ "owner": "0xf3Ba773Af9e30B8187E2Abbd0B4F3218273127D0", "name": "flightDelay", "type": "DOCKER", - "multiaddr": "registry.hub.docker.com/nikhil3000/flight-delay:1.0.0", - "checksum": "0xa3277ff23fcb7fac1562f385b8570b67595cd115f0c125e8d428ef29c44335aa", + "multiaddr": "registry.hub.docker.com/nikhil3000/flight-delay:1.0.1", + "checksum": "0x866f12aee5381b2ab2b029b678f0c2dbc125ee06db7f045eeaefcb0998a589f5", "mrenclave": "" }, "order": { "apporder": { - "app": "0x70A4ffB9aa9106f4E604D8E2Db77178FdB8CfD1a", + "app": "0x2bEe1A8d963D9f3d8Da6Db5A5e23aA4dB537811B", "appprice": "0", "volume": "1000000", "tag": "0x0000000000000000000000000000000000000000000000000000000000000000", diff --git a/flight-delay/orders.json b/flight-delay/orders.json index f33fb5f0..2d7438d5 100644 --- a/flight-delay/orders.json +++ b/flight-delay/orders.json @@ -1,15 +1,15 @@ { "42": { "apporder": { - "app": "0x70A4ffB9aa9106f4E604D8E2Db77178FdB8CfD1a", + "app": "0x2bEe1A8d963D9f3d8Da6Db5A5e23aA4dB537811B", "appprice": "0", "volume": "1000000", "tag": "0x0000000000000000000000000000000000000000000000000000000000000000", "datasetrestrict": "0x0000000000000000000000000000000000000000", "workerpoolrestrict": "0x0000000000000000000000000000000000000000", "requesterrestrict": "0x0000000000000000000000000000000000000000", - "salt": "0x4a944d1d291c4bc73a77af5622f396a61e4d2a03a5f2259741a3fc78614f5725", - "sign": "0xb55a27276356637f2fbb62379c4215f5e7db9656a2edc6d33b423cf1212f9f695a48ab8e9ab16e89efe9c445d022191a768c6737c8aadd160cc219537db6b9b31b" + "salt": "0x0285178da87007386921c7dc76fc009fa47ac4ab76986949d3234c6494c909cd", + "sign": "0xc2097916b26007f2b26a824aa4690901d86c79e21158bae2426054397474c0384ddf3c3be20ff065a2b64c96cb02af4ef25f7f0d6213704db98c769c6875a51c1c" } } } \ No newline at end of file