Как контракт Ethereum может получить данные с веб-сайта?

Какой процесс/рабочий процесс стоит за процессом, когда контракт Ethereum получает некоторые данные с веб-сайта?

Ответы (7)

Вы можете использовать Oracle . Оракул — это любое устройство или объект, который связывает данные реального мира с блокчейном.

Есть несколько примеров технологий оракула. Chainlink и Provable (ранее Oraclize) — два примера, которые делают именно это.

Здесь есть несколько примеров кода, а также документация нашего Solidity API .

Oraclize доступен как в основной , так и в тестовой сети, поэтому разобраться с ним должно быть легко, однако, если вам нужна поддержка, не стесняйтесь спрашивать — у нас даже есть канал gitter здесь .

Как видите, получить данные с веб-сайта так же просто, как использовать функцию oraclize_query .

Наше хорошее поведение подтверждено доказательством TLSNotary и может быть легко проверено с помощью этого сетевого монитора на стороне клиента .

Например, чтобы получить цену ETHXBT из тикера Kraken:

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
    }
} 
Я понятия не имел, что кто-то уже использует TLS Notary для этого. Нечего и говорить - с ума сошел. Если вы все делаете правильно, это должно позволить передавать ненадежную информацию в сеть Ethereum. (Ненадежный, пока вы доверяете серверу.)
Планируется ли выпуск Oraclize с открытым исходным кодом? (Основное программное обеспечение, а не интерфейс.)
Мы планируем открыть исходный код многих инструментов, которые мы создаем в Oraclize, но не планируем открывать исходный код нашего внутреннего движка.
У меня полно вопросов об Oraclize! Я спросил одного из них здесь .
Сколько эфира будет стоить такая операция?
@Rémi, вы можете найти информацию о ценах в нашем специальном разделе на docs.oraclize.it.
Правильно ли я рассчитал, что 1 звонок через Oraclize ( docs.oraclize.it/#ethereum-custom-gas ) будет стоить 200000*0,2337= 46000? Я взял цену на газ с ethgasstation.info
можно ли использовать в частном блокчейне?

Вы не можете сделать это напрямую; Контракты Ethereum не могут обращаться к URL-адресам, потому что Ethereum нуждается в том, чтобы каждый мог независимо проверять результат выполнения любого конкретного контракта, и вы не можете гарантировать, что все они получат одинаковый результат от любого заданного URL-адреса.

Что вы можете сделать, так это попросить третью сторону или комбинацию третьих сторон нажать на URL-адрес для вас и сообщить вам, что они нашли. Они могут сделать это либо подписав данные, чтобы ваш контракт мог проверить подпись (это то, что мы делаем в Reality Keys ), либо отправив данные из своего контракта в ваш контракт (это то, что делает Oraclize).

Взгляните на Etheropt на GitHub для рабочего примера.

Недостатком этого подхода является то, что ваши пользователи должны доверять сервису, который переходит по URL-адресу. Если эта служба повреждена или взломана, это приведет к SFYL. (Oraclize предоставляет нотариальное подтверждение TLS того, что данные, которые они предоставили, были данными, которые они предоставили вам, действительно были предоставлены URL-адресом, но это на самом деле не помогает с реальной угрозой безопасности. Обнаружение того, что они дали вам неправильный ответ, легко, проблема в том, что ваш контракт все равно примет их ответ, хотя все знают, что они лгут...)

Есть несколько потенциальных альтернативных подходов к этой проблеме, которые не зависят от репутации; Самым известным из них является Augur, который заставляет участников рынка голосовать за результат и имеет систему стимулов, которая, как они надеются, заставит людей голосовать честно. Есть также несколько интересных предложений между полностью доверенными сервисами и чистым голосованием пользователей, например , «окончательный оракул» Мартина Коппельманна .

Ключи от реальности выглядят как раз то, что мне нужно. Есть ли у вас примеры контрактов Solidity, которые вызывают один из ваших бесплатных API?
Здесь есть пример кода Solidity: github.com/edmundedgar/realitykeys-examples-ethereum ... который кто-то превращает в правильное веб-приложение здесь: github.com/drupalnomad/runkeeper-oracle Еще немного пояснений здесь: realitykeys.com /developers/resources Не стесняйтесь обращаться к нам, если не можете разобраться. Единственный спортивный API, который у нас есть прямо сейчас, предназначен для результатов футбола, но легко добавить другие API, если вы можете указать нам что-то с нужными вам данными, к которым поставщик данных разрешит нам доступ.
Есть ли способ для смарт-контракта Solidity взаимодействовать с учетными записями Twitter или API Twitter, чтобы распознавать количество «соответствующих тегов» твитов, сделанных этой учетной записью? Например, монета ERC-20 начисляется каждому пользователю Твиттера за твит о «#EventA» X раз.

Для клиента Python Ethereum (pyethapp) написано подробное руководство о том, как контракт может получать данные:

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

Одной из самых мощных отличительных особенностей pyethapp является его способность легко создавать встроенные пользовательские сервисы: сценарии, написанные на python, которые запускаются вместе с pyethapp и запускают код при запуске и каждый раз, когда вы получаете новый блок. Это позволяет создавать «серверные демоны» для приложений, которым требуется периодическая автоматизированная поддержка, таких как RANDAO, потоки данных, приложения «децентрализованные папки», будильники, децентрализованные службы облачных вычислений и т. д.

Pyethapp предоставляет on_startхуки on_block, которые позволяют запускать код при запуске и обработке блока. Пример кода из учебника:

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'

В учебнике объясняется:

По сути, экземпляр этой службы, управляемой доверенной стороной, позволяет контрактам Ethereum получать доступ к любому потоку данных, доступному через REST API через Интернет.

Есть ли способ для смарт-контракта Solidity взаимодействовать с учетными записями Twitter или API Twitter, чтобы распознавать количество «соответствующих тегов» твитов, сделанных этой учетной записью? Например, монета ERC-20 начисляется каждому пользователю Твиттера за твит о «#EventA» X раз.
@user610620 user610620 Я вижу, вы пытались задать этот вопрос как вопрос, который был закрыт как дубликат этого. Я не уверен, что могу добавить: у смарт-контракта может быть функция rewardTweeter(uint numberOfTweets, address tweeter). Оракул должен был вызвать эту функцию.
Какие предварительные требования к оборудованию необходимы смарт-контракту Ethereum для доступа к данным Twitter, не говоря уже о поиске информации в Интернете? учетная запись Twitter с поддержкой API Twitter? Если да, то как смарт-контракт вызывает API Twitter для получения данных?
@user610620 user610620 Запрос предварительных требований к оборудованию имеет смысл для оракула (сервиса). Ответы здесь пытались объяснить, что контракты не вызывают API: оракул вызывает API и вызывает контракты (возможно, с данными, полученными оракулом от API).

Как уже говорили другие, вы должны использовать Oracle. Некоторые проекты, такие как ChainLink и Oracleize , сделают это за вас.

Чтобы настроить оракул самостоятельно, процесс выглядит так:

  1. Создайте смарт-контракт
  2. Настройте сервер, прослушивающий какое-либо внешнее событие, например, спортивную игру.
  3. Как только определенное условие будет выполнено, например, одна команда победит, ваш сервер отправит транзакцию на ваш контракт Ethereum, обновив его с результатом события.

Попробуйте этот пример в Javascript (на основе оракулов в Ethereum ):

Договор

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

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))
})
Есть ли способ для смарт-контракта Solidity взаимодействовать с учетными записями Twitter или API Twitter, чтобы распознавать количество «соответствующих тегов» твитов, сделанных этой учетной записью? Например, монета ERC-20 начисляется каждому пользователю Твиттера за твит о «#EventA» X раз.

Оракул может быть управляемой вручную учетной записью человека, которая своевременно передает данные, или, что еще лучше, автоматизированной группой ботов на традиционных серверах, которые очищают веб-сайт и передают данные через учетную запись. Вам нужно будет жестко закодировать адрес контракта в свой контракт как оракул правдивых значений для вашей программы. Закрытый ключ хранится в тайне, в отличие от смарт-контракта, где каждый может его увидеть. Может потребоваться какой-то способ дедупликации и формирования консенсуса для надежной работы с полным резервированием.

Вы должны использовать оракул .

Оракул — это любое устройство, которое отправляет данные вне сети в блокчейн.

Существует множество сервисов оракулов, которые могут помочь вам передавать данные из офчейна в цепочку в рамках Ethereum. Важно отметить, что каждый из них делает это по-разному, что приводит к множеству соображений о том, почему и как вы будете реализовывать их технологию. Вот некоторые из самых популярных:

  1. Звено цепи
  2. Теллор
  3. Доказуемый
  4. BandChain

А вот пример получения данных через узел Chainlink :

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))
    }
  }
}

Вы можете получить данные об акциях, криптовалютах, ETF и т. д. из смарт- контракта OrFeed.org :

Примеры:

Форекс:

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

Запас:

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

или в реальном времени с DEX:uint price = orfeed.getExchangeRate("BTC", "DAI", "SELL-UNISWAP-EXCHANGE", 100);