Wie kann ein Ethereum-Vertrag Daten von einer Website erhalten?

Was ist der Prozess/Workflow hinter dem Prozess, bei dem ein Ethereum-Vertrag einige Daten von einer Website erhält?

Antworten (7)

Sie können ein Orakel verwenden . Ein Orakel ist ein beliebiges Gerät oder eine Entität, die reale Daten mit der Blockchain verbindet.

Es gibt mehrere Beispiele für Oracle-Technologien. Chainlink und Provable (ehemals Oraclize) sind zwei Beispiele, die genau das tun.

Hier finden Sie einige Codebeispiele sowie die Dokumentation unserer Solidity-API .

Oraclize ist sowohl im Mainnet als auch im Testnet verfügbar , also sollte es einfach sein, damit herumzustöbern, aber wenn Sie Unterstützung benötigen, fragen Sie einfach – wir haben hier sogar einen Gitter-Kanal .

Wie Sie sehen können, ist das Abrufen von Daten von einer Website so einfach wie die Verwendung der oraclize_query- Funktion.

Unser gutes Benehmen wird durch den TLSNotary- Nachweis gewährt und kann mit diesem webbasierten clientseitigen Netzwerkmonitor einfach überprüft werden .

Um beispielsweise den ETHXBT-Preis aus dem Kraken-Ticker abzurufen:

import "dev.oraclize.it/api.sol";

contract KrakenPriceTicker is usingOraclize {
    string public ETHXBT;

    function PriceTicker() {
        oraclize_setNetwork(networkID_testnet);
        oraclize_setProof(proofType_TLSNotary | proofStorage_IPFS);
        oraclize_query("URL", "json(https://api.kraken.com/0/public/Ticker?pair=ETHXBT).result.XETHXXBT.c.0");
    }

    function __callback(bytes32 myid, string result, bytes proof) {
        if (msg.sender != oraclize_cbAddress()) throw;
        ETHXBT = result;
        // do something with ETHXBT
    }
} 
Ich hatte keine Ahnung, dass jemand dafür bereits TLS Notary verwendet. Unnötig zu sagen - überwältigt. Wenn Sie dies richtig machen, sollte es die Weitergabe vertrauenswürdiger Informationen an das Ethereum-Netzwerk ermöglichen. (Vertrauenslos, solange Sie dem Server vertrauen.)
Gibt es Pläne, Oracle Open Source zu machen? (Die Kernsoftware, nicht die Schnittstelle.)
Wir planen, viele der Tools, die wir bei Oraclize entwickeln, zu öffnen, aber es gibt keinen Plan, unsere interne Engine zu öffnen
Ich bin voller Fragen zu Oraclize! Ich habe hier einen gefragt .
Wie viel Äther würde eine solche Operation kosten?
@Rémi Informationen zu den Preisen finden Sie in unserem speziellen Bereich unter docs.oraclize.it
Liege ich in meinen Berechnungen richtig, dass 1 Anruf über Oraclize ( docs.oraclize.it/#ethereum-custom-gas ) 200000 * 0,2337 = 46000 kostet? Ich habe den Benzinpreis von ethgasstation.info genommen
ist es möglich, in einer privaten Blockchain verwendet zu werden?

Sie können dies nicht direkt tun; Ethereum-Verträge können keine URLs treffen, da Ethereum jeden in der Lage sein muss, das Ergebnis der Ausführung eines bestimmten Vertrags unabhängig zu validieren, und Sie können nicht garantieren, dass sie alle das gleiche Ergebnis von einer bestimmten URL erhalten.

Was Sie tun können, ist, einen Drittanbieter oder eine Kombination von Drittanbietern dazu zu bringen, die URL für Sie zu finden und Ihnen mitzuteilen, was sie gefunden haben. Sie können dies entweder tun, indem sie die Daten signieren, damit Ihr Vertrag die Signatur überprüfen kann (das machen wir bei Reality Keys ) oder indem sie die Daten aus ihrem Vertrag an Ihren Vertrag senden (das macht Oraclize).

Werfen Sie einen Blick auf Etheropt auf GitHub für ein funktionierendes Beispiel.

Der Nachteil dieses Ansatzes besteht darin, dass Ihre Benutzer dem Dienst vertrauen müssen, der auf die URL zugreift. Wenn dieser Dienst beschädigt oder gehackt wird, führt dies zu SFYL. (Oraclize liefert einen TLS-Notarbeweis, dass die von ihnen bereitgestellten Daten die Daten waren, die sie Ihnen tatsächlich von der URL bereitgestellt haben, aber das hilft nicht wirklich beim tatsächlichen Sicherheitsrisiko; es ist einfach zu erkennen, dass sie Ihnen die falsche Antwort gegeben haben Das Problem ist, dass Ihr Vertrag immer noch ihre Antwort akzeptiert, obwohl jeder weiß, dass sie lügen ...)

Es gibt einige potenzielle alternative Ansätze für dieses Problem, die sich nicht auf die Reputation verlassen; Das bekannteste ist Augur, das die Marktteilnehmer dazu bringt, über das Ergebnis abzustimmen, und über ein System von Anreizen verfügt, von dem sie hoffen, dass die Menschen wahrheitsgemäß abstimmen. Es gibt auch einige interessante Vorschläge zwischen vollständig vertrauenswürdigen Diensten und reinem Benutzervoting, wie Martin Koeppelmanns "ultimatives Orakel" .

Reality Keys sieht aus wie genau das, was ich brauche. Haben Sie Beispiele für Soliditätsverträge, die eine Ihrer kostenlosen APIs aufrufen?
Hier gibt es einen Beispiel-Solidity-Code: github.com/edmundedgar/realitykeys-examples-ethereum ... den jemand hier in eine richtige Web-App verwandelt: github.com/drupalnomad/runkeeper-oracle Ein bisschen mehr Erklärung hier: realitykeys.com /developers/resources Fühlen Sie sich frei, sich mit uns in Verbindung zu setzen, wenn Sie es nicht herausfinden können. Die einzige Sport-API, die wir derzeit haben, ist für Fußballergebnisse, aber es ist einfach, andere APIs hinzuzufügen, wenn Sie uns auf etwas mit gewünschten Daten verweisen können, auf das uns der Datenanbieter Zugriff gewähren würde.
Gibt es eine Möglichkeit für einen Smart Contract von Solidity, sich mit Twitter-Konten oder der Twitter-API zu verbinden, um die Anzahl der „relevant getaggten“ Tweets zu erkennen, die dieses Konto erstellt hat? Zum Beispiel wird jedem Twitter-Nutzer eine ERC-20-Münze dafür verliehen, dass er X-mal über „#EventA“ twittert

Für den Python-Ethereum-Client (pyethapp) wurde ein ausführliches Tutorial geschrieben, wie ein Vertrag Daten erhalten kann:

https://github.com/ethereum/pyethapp/wiki/Making-a-User-Service:-Tutorial

Eines der stärksten Unterscheidungsmerkmale von pyethapp ist seine Fähigkeit, integrierte Benutzerdienste einfach zu erstellen: in Python geschriebene Skripte, die neben pyethapp ausgeführt werden und beim Start und jedes Mal, wenn Sie einen neuen Block erhalten, Code ausführen. Auf diese Weise können Sie „Server-Daemons“ für Anwendungen erstellen, die regelmäßig automatisierte Unterstützung benötigen, wie z. B. RANDAO, Datenfeeds, „dezentrale Dropbox“-Apps, Wecker, dezentrale Cloud-Computing-Dienste usw.

Pyethapp stellt Hooks bereit, mit denen Code ausgeführt werden kann, wenn es gestartet wird und wenn es einen Block verarbeitet on_start. on_blockBeispielcode aus dem Tutorial:

https://github.com/ethereum/pyethapp/blob/develop/examples/urlfetcher.py

import json, re
import random
import sys
import ethereum.blocks
import ethereum.utils
import ethereum.abi
import rlp
try:
    from urllib.request import build_opener 
except:
    from urllib2 import build_opener

my_privkey = ethereum.utils.sha3('qwufqhwiufyqwiugxqwqcwrqwrcqr')
my_address = ethereum.utils.privtoaddr(my_privkey).encode('hex')
print 'My address', my_address
# Address of the main proxy contract
my_contract_address = ethereum.utils.normalize_address('0xd53096b3cf64d4739bb774e0f055653e7f2cd710')

# Makes a request to a given URL (first arg) and optional params (second arg)
def make_request(*args):
    opener = build_opener()
    opener.addheaders = [('User-agent',
                          'Mozilla/5.0'+str(random.randrange(1000000)))]
    try: 
        return opener.open(*args).read().strip()
    except Exception as e:
        try:
            p = e.read().strip()
        except:
            p = e
        raise Exception(p)


true, false = True, False
# ContractTranslator object for the main proxy contract
ct = ethereum.abi.ContractTranslator([{"constant": false, "type": "function", "name": "get(string)", "outputs": [{"type": "int256", "name": "out"}], "inputs": [{"type": "string", "name": "url"}]}, {"inputs": [{"indexed": false, "type": "string", "name": "url"}, {"indexed": false, "type": "address", "name": "callback"}, {"indexed": false, "type": "uint256", "name": "responseId"}, {"indexed": false, "type": "uint256", "name": "fee"}], "type": "event", "name": "GetRequest(string,address,uint256,uint256)"}])
# ContractTranslator object for the contract that is used for testing the main contract
ct2 = ethereum.abi.ContractTranslator([{"constant": false, "type": "function", "name": "callback(bytes,uint256)", "outputs": [], "inputs": [{"type": "bytes", "name": "response"}, {"type": "uint256", "name": "responseId"}]}])

app, my_nonce, chainservice = None, None, None

# Called once on startup
def on_start(_app):
    print 'Starting URL translator service'
    global app, my_nonce, chainservice
    app = _app
    chainservice = app.services.chain
    my_nonce = chainservice.chain.head.get_nonce(my_address)


# Called every block
def on_block(blk):
    global my_nonce, chainservice
    for receipt in blk.get_receipts():
        for _log in receipt.logs:
            # Get all logs to the proxy contract address of the right type
            if _log.address == my_contract_address:
                log = ct.listen(_log)
                if log and log["_event_type"] == "GetRequest":
                    print 'fetching: ', log["url"]
                    # Fetch the response
                    try:
                        response = make_request(log["url"])
                    except:
                        response = ''
                    print 'response: ', response
                    # Create the response transaction
                    txdata = ct2.encode('callback', [response, log["responseId"]])
                    tx = ethereum.transactions.Transaction(my_nonce, 60 * 10**9, min(100000 + log["fee"] / (60 * 10**9), 2500000), log["callback"], 0, txdata).sign(my_privkey)
                    print 'txhash: ', tx.hash.encode('hex')
                    print 'tx: ', rlp.encode(tx).encode('hex')
                    # Increment the nonce so the next transaction is also valid
                    my_nonce += 1
                    # Send it
                    success = chainservice.add_transaction(tx, broadcast_only=True)
                    assert success
                    print 'sent tx'

Das Tutorial erklärt:

Im Wesentlichen ermöglicht eine Instanz dieses Dienstes, die von einer vertrauenswürdigen Partei betrieben wird, Ethereum-Verträgen den Zugriff auf alle Daten-Feeds, die über eine REST-API über das Internet verfügbar sind.

Gibt es eine Möglichkeit für einen Smart Contract von Solidity, sich mit Twitter-Konten oder der Twitter-API zu verbinden, um die Anzahl der „relevant getaggten“ Tweets zu erkennen, die dieses Konto erstellt hat? Zum Beispiel wird jedem Twitter-Nutzer eine ERC-20-Münze dafür verliehen, dass er X-mal über „#EventA“ twittert
@ user610620 Ich sehe, Sie haben versucht, dies als eine Frage zu stellen, die als Duplikat dieser Frage geschlossen wurde. Ich bin mir nicht sicher, was ich hinzufügen kann: Der Smart Contract könnte eine Funktion haben rewardTweeter(uint numberOfTweets, address tweeter). Ein Orakel müsste diese Funktion aufrufen.
Welche Hardware-Voraussetzungen benötigt ein Ethereum Smart Contract, um auf Twitter-Daten zugreifen zu können, geschweige denn, Dinge online nachzuschlagen? ein Twitter-API-fähiges Twitter-Konto? Wenn ja, wie ruft ein Smart Contract die Twitter-API für Daten auf?
@ user610620 Die Abfrage der Hardwarevoraussetzungen wäre für das Orakel (Dienst) sinnvoll. Die Antworten hier haben versucht zu erklären, dass Verträge keine APIs aufrufen: Ein Orakel ruft APIs auf und ruft Verträge auf (möglicherweise mit Daten, die das Orakel von APIs erhalten hat).

Wie andere gesagt haben, müssen Sie ein Orakel verwenden. Einige Projekte wie ChainLink und Oracleize erledigen dies für Sie.

Um ein Orakel in Eigenregie einzurichten, sieht der Prozess wie folgt aus:

  1. Erstellen Sie einen intelligenten Vertrag
  2. Richten Sie einen Server ein, der auf ein externes Ereignis wartet, z. B. ein Sportspiel
  3. Sobald eine bestimmte Bedingung erfüllt ist, zB ein Team gewinnt, sendet Ihr Server eine Transaktion an Ihren Ethereum-Vertrag und aktualisiert ihn mit dem Ergebnis des Ereignisses

Versuchen Sie dieses Beispiel in Javascript (basierend auf Oracles in Ethereum ):

Vertrag

pragma solidity ^0.4.17;

contract GamescoreOracle {
  address public owner;
  string public gameWinner;
  event CallbackGetGameWinner();

  constructor() public {
    owner = msg.sender;
  }

  function updateGameWinner() public {
    emit CallbackGetGameWinner();
  }

  function setWinningTeam(string teamname) public {
    require(msg.sender == owner, "Err: Not Authorized");
    gameWinner = teamname;
  }

  function getGameWinner() public view returns (string) {
    return gameWinner;
  }
}

Oracle-Server

const fetch = require("fetch");
const OracleContract = require("./build/contracts/GamescoreOracle.json");
const contract = require("truffle-contract");

const Web3 = require("web3");
const web3 = new Web3(new Web3.providers.HttpProvider('http://localhost:8545'));

const oracleContract = contract(OracleContract);
oracleContract.setProvider(web3.currentProvider);

web3.eth.getAccounts((err, accounts) => {
  oracleContract.deployed()
    .then((oracleInstance) => {
      // watch event, respond to event with callback
      oracleInstance.CallbackGetGameWinner()
        .watch((err, event) => {
          fetch.fetchUrl('http://www.mocky.io/v2/5baadacb3000002b00a68532', (err, m, response) => {
            const games = JSON.parse(response.toString());
            const winner = games.competitors.filter(team => team.isWinner)[0].team.nickname;

            // Send data back contract on-chain
            console.log(`Running contract.setWinningTeam(${winner})`)
            oracleInstance.setWinningTeam(winner, { from: accounts[0] })
          })
        })
    })
    .catch(err => console.log(err))
})
Gibt es eine Möglichkeit für einen Smart Contract von Solidity, sich mit Twitter-Konten oder der Twitter-API zu verbinden, um die Anzahl der „relevant getaggten“ Tweets zu erkennen, die dieses Konto erstellt hat? Zum Beispiel wird jedem Twitter-Nutzer eine ERC-20-Münze dafür verliehen, dass er X-mal über „#EventA“ twittert

Ein Orakel kann ein manuell gesteuertes menschliches Konto sein, das Daten zeitnah einspeist, oder besser ein automatisierter Haufen von Bots auf traditionellen Servern, die eine Website abkratzen und Daten über das Konto einspeisen. Sie müssten eine Vertragsadresse als Orakel wahrer Werte für Ihr Programm fest in Ihren Vertrag codieren. Der private Schlüssel wird privat gehalten, im Gegensatz zu einem Smart Contract, wo jeder ihn sehen kann. Für einen vollständig redundanten, zuverlässigen Betrieb ist möglicherweise eine Möglichkeit zum Deduplizieren und Konsensieren erforderlich.

Sie müssen ein Orakel verwenden .

Ein Orakel ist jedes Gerät, das Off-Chain-Daten an eine Blockchain sendet.

Es gibt viele Orakeldienste, die Ihnen helfen können, Daten innerhalb des Ethereum-Frameworks von Off-Chain zu On-Chain zu übertragen. Es ist wichtig zu beachten, dass jeder es sehr unterschiedlich macht, was zu vielen Überlegungen führt, warum/wie Sie ihre Technologie implementieren würden. Hier sind einige der beliebtesten:

  1. Kettenglied
  2. Teller
  3. Nachweisbar
  4. BandChain

Und hier ist ein Beispiel für das Abrufen von Daten über einen Chainlink-Knoten :

pragma solidity ^0.6.0;

import "github.com/smartcontractkit/chainlink/evm-contracts/src/v0.6/ChainlinkClient.sol";

// MyContract inherits the ChainlinkClient contract to gain the
// functionality of creating Chainlink requests
contract ChainlinkExample is ChainlinkClient {
  // Stores the answer from the Chainlink oracle
  uint256 public currentPrice;
  address public owner;
  
    // The address of an oracle - you can find node addresses on https://market.link/search/nodes
  address ORACLE_ADDRESS = 0xB36d3709e22F7c708348E225b20b13eA546E6D9c;
  // The address of the http get job - you can find job IDs on https://market.link/search/jobs
  string constant JOBID = "628eded7db7f4f799dbf69538dec7ff2";
  // 17 0s = 0.1 LINK 
  // 18 0s = 1 LINK 
  uint256 constant private ORACLE_PAYMENT = 100000000000000000;

  constructor() public {
    setPublicChainlinkToken();
    owner = msg.sender;
  }

  // Creates a Chainlink request with the uint256 multiplier job
  // Ideally, you'd want to pass the oracle payment, address, and jobID as 
  function requestEthereumPrice() 
    public
    onlyOwner
  {
    // newRequest takes a JobID, a callback address, and callback function as input
    Chainlink.Request memory req = buildChainlinkRequest(stringToBytes32(JOBID), address(this), this.fulfill.selector);
    // Adds a URL with the key "get" to the request parameters
    req.add("get", "https://min-api.cryptocompare.com/data/price?fsym=ETH&tsyms=USD");
    // Uses input param (dot-delimited string) as the "path" in the request parameters
    req.add("path", "USD");
    // Adds an integer with the key "times" to the request parameters
    req.addInt("times", 100);
    // Sends the request with the amount of payment specified to the oracle
    sendChainlinkRequestTo(ORACLE_ADDRESS, req, ORACLE_PAYMENT);
  }

  // fulfill receives a uint256 data type
  function fulfill(bytes32 _requestId, uint256 _price)
    public
    // Use recordChainlinkFulfillment to ensure only the requesting oracle can fulfill
    recordChainlinkFulfillment(_requestId)
  {
    currentPrice = _price;
  }
  
  // withdrawLink allows the owner to withdraw any extra LINK on the contract
  function withdrawLink()
    public
    onlyOwner
  {
    LinkTokenInterface link = LinkTokenInterface(chainlinkTokenAddress());
    require(link.transfer(msg.sender, link.balanceOf(address(this))), "Unable to transfer");
  }
  
  modifier onlyOwner() {
    require(msg.sender == owner);
    _;
  }
  
   // A helper funciton to make the string a bytes32
  function stringToBytes32(string memory source) private pure returns (bytes32 result) {
    bytes memory tempEmptyStringTest = bytes(source);
    if (tempEmptyStringTest.length == 0) {
      return 0x0;
    }
    assembly { // solhint-disable-line no-inline-assembly
      result := mload(add(source, 32))
    }
  }
}

Sie können Aktien-, Krypto-, ETF- usw. Daten aus dem Smart Contract von OrFeed.org abrufen :

Beispiele:

Devisen:

uint price = orfeed.getExchangeRate("JPY", "USD", "DEFAULT", 100000);

Aktie:

uint price = orfeed.getExchangeRate("AAPL", "USD", "PROVIDER1", 1);

oder in Echtzeit von einem DEX:uint price = orfeed.getExchangeRate("BTC", "DAI", "SELL-UNISWAP-EXCHANGE", 100);