Building an “Oracle” for an Ethereum contract

What is an Oracle?

Smart contracts, by their nature, are able to run algorithmic calculations and store and retrieve data. Because every node runs every calculation, it’s not practical (and presently impossible) to make arbitrary network requests from an Ethereum contract. Oracles fill this void by watching the blockchain for events and responding to them by publishing the results of a query back to the contract. In this way, contracts can interact with the off-chain world.

The Tinypay.co DNS Oracle

The oracle for Tinypay (described in more detail here) has to do three simple things:

  • Verify DNS records using the data from the event
  • Send a ‘ConfirmClient’ transaction to the contract once the domain is confirmed

You can use RPC directly… but you probably shouldn’t

The first time I wrote the oracle, I used Go. I tried to do all of the communication with the Ethereum node using the RPC APIs directly.

Web3 is a good abstraction

For the second iteration I switched to node.js and used the web3 library for communicating with the geth node. This gave me built in abstractions for event watching, data extraction and formatting, and generally made life a lot easier.

var Web3 = require('web3');
var web3 = new Web3();
var contracts = require(path.join(__dirname, 'gen_contracts.json'));// First we instruct web3 to use the RPC provider
web3.setProvider(
new web3.providers.HttpProvider(
'http://' + opts.rpc_host + ':' + opts.rpc_port));
// This isn't strictly necessary here, but goes to show the step required to "unlock" the account before sending transactions.
if (!web3.personal.unlockAccount(
web3.eth.coinbase, opts.wallet_password)) {
console.error('Could not unlock');
process.exit();
}
// Here we register the filter with the ethereum node, and then begin polling for updates.
function runLoop(o) {
var filter = web3.eth.filter({address: o.contract_address});
filter.watch(function (err, results) {
if (err) {
console.log('WATCH ERROR: ', err);
process.exit();
}
console.debug(results);
});
}
// If the contract isn't deployed yet, we deploy it here
if (!opts.contract_address) {
// This block of code loads the ABI for interpreting contract data.
var dmC = web3.eth.contract(JSON.parse(contracts.DomainMicropay.abi));
var x = {
from: web3.eth.coinbase,
data: contracts.DomainMicropay.bin,
gas: 1000000
};
// send the transaction for installing the contract.
dmC.new(x, function (err, resp) {
if (err) {
console.error('Loading contract', err);
process.exit();
}
var addr = resp.address;
if (!addr) {
console.log('Pending tx: ', resp.transactionHash);
} else {
console.log('Deployed Address: ', addr);
opts.contract_address = addr;
runLoop(opts);
}
});
} else {
runLoop(opts); // in either case, start the polling event loop.
}

Truffle is what you want to use though

Finally, for the third iteration, I gave up trying to roll it all myself. We were already using the excellent tool, truffle, from ConsenSys in our web front end. I just copied the generated artifacts into my node.js project, and included it directly, and I was in business.

// This code extract shows the whole event loop abstracted behind the actual event name: ClientConfirmed and ClientCreated.
startWatcher: function (rpcUrl, unlockPass) {
password = unlockPass || password;
web3.setProvider(new web3.providers.HttpProvider(rpcUrl));
DomainMicropay.setProvider(web3.currentProvider);
contract.ClientConfirmed({}, eventOpts(), function (err, data) {
if (err) {
console.log('Error ClientConfirmed: ', err);
return;
}
console.log('Event ClientConfirmed: ', data.args.domain);
});
contract.ClientCreated({}, eventOpts(), function (err, data) {
if (err) {
console.log('Error ClientCreated: ', err);
return;
}
console.log('Event ClientCreated: ', data.args.domain);
contract.getPaymentContractForDomain
.call(data.args.domain)
.then(beginDomainVerification(data))
.catch(errFn('Unhandled Error: '));
});
}

--

--

World Class Engineers and Designers Helping You Ship Lovable Web and Mobile Technology.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Lovable Technology

World Class Engineers and Designers Helping You Ship Lovable Web and Mobile Technology.