Merge pull request #1 from ethereum/swarm

getting up to date with upsteam
This commit is contained in:
Daniel A. Nagy 2016-08-29 15:19:59 +02:00 committed by GitHub
commit d9fb99c4b3
18 changed files with 1254 additions and 1344 deletions

View file

@ -117,27 +117,19 @@ web3._extend({
property: 'ens',
methods:
[
new web3._extend.Method({
name: 'deployRegistrar',
call: 'ens_deployRegistrar',
}),
new web3._extend.Method({
name: 'deployResolver',
call: 'ens_deployResolver',
}),
new web3._extend.Method({
name: 'register',
call: 'ens_register',
params: 2,
inputFormatter: [null, null]
params: 1,
inputFormatter: [null]
}),
new web3._extend.Method({
new web3._extend.Method({
name: 'setContentHash',
call: 'ens_setContentHash',
params: 2,
inputFormatter: [null, null]
}),
new web3._extend.Method({
new web3._extend.Method({
name: 'resolve',
call: 'ens_resolve',
params: 1,

View file

@ -21,7 +21,7 @@ const (
// by default ens root is north internal
var (
toyNetEnsRoot = common.HexToAddress("0x606aabab27f8aa98b772bf593b18e550ede87176")
toyNetEnsRoot = common.HexToAddress("0xd344889e0be3e9ef6c26b0f60ef66a32e83c1b69")
)
// separate bzz directories

View file

@ -0,0 +1,60 @@
{
"nonce": "0x42",
"gasLimit": "0x47e7c4",
"difficulty": "0x20000",
"alloc": {
"866b5394fe446751e932b7ef77280f4ab7ea3afe": {
"code": "",
"storage": {},
"balance": "01c51307a94a7800"
},
"0000000000000000000000000000000000000000": {
"code": "",
"storage": {},
"balance": "3aecf856b58800"
},
"0000000000000000000000000000000000000001": {
"code": "",
"storage": {},
"balance": "01"
},
"0000000000000000000000000000000000000002": {
"code": "",
"storage": {},
"balance": "01"
},
"0000000000000000000000000000000000000003": {
"code": "",
"storage": {},
"balance": "01"
},
"0000000000000000000000000000000000000004": {
"code": "",
"storage": {},
"balance": "01"
},
"cb7152b03774fd01a8480001b2bcdfebc4f04363": {
"code": "6060604052361561004b5760e060020a60003504632dff694181146100535780633b3b57de1461007557806341b9dc2b146100a0578063c3d014d614610139578063d5fa2b00146101b2575b61022b610002565b61022d6004356000818152600260205260408120549081141561027057610002565b61023f600435600081815260016020526040812054600160a060020a03169081141561027057610002565b61025c60043560243560007f6164647200000000000000000000000000000000000000000000000000000000821480156100f05750600083815260016020526040812054600160a060020a031614155b8061013257507f636f6e74656e740000000000000000000000000000000000000000000000000082148015610132575060008381526002602052604081205414155b9392505050565b61022b600435602435600080546040805160e060020a6302571be30281526004810186905290518593600160a060020a033381169416926302571be392602482810193602093839003909101908290876161da5a03f11561000257505060405151600160a060020a031691909114905061027557610002565b61022b600435602435600080546040805160e060020a6302571be30281526004810186905290518593600160a060020a033381169416926302571be392602482810193602093839003909101908290876161da5a03f11561000257505060405151600160a060020a03169190911490506102c157610002565b005b60408051918252519081900360200190f35b60408051600160a060020a03929092168252519081900360200190f35b604080519115158252519081900360200190f35b919050565b6000838152600260209081526040918290208490558151848152915185927f0424b6fe0d9c3bdbece0e7879dc241bb0c22e900be8b6c168b4ee08bd9bf83bc92908290030190a2505050565b600083815260016020908152604091829020805473ffffffffffffffffffffffffffffffffffffffff1916851790558151600160a060020a0385168152915185927f52d7d861f09ab3d26239d492e8968629f95e9e318cf0b73bfddc441522a15fd292908290030190a250505056",
"storage": {
"0000000000000000000000000000000000000000000000000000000000000000": "d344889e0be3e9ef6c26b0f60ef66a32e83c1b69"
},
"balance": ""
},
"d344889e0be3e9ef6c26b0f60ef66a32e83c1b69": {
"code": "606060405260e060020a60003504630178b8bf811461004757806302571be31461006e5780631896f70a14610091578063569cd595146100c55780635b0fc9c3146100fc575b005b610130600435600081815260208190526040902060010154600160a060020a03165b919050565b610130600435600081815260208190526040902054600160a060020a0316610069565b6100456004356024356000828152602081905260409020548290600160a060020a0390811633919091161461014d57610002565b6100456004356024356044356000838152602081905260408120548490600160a060020a039081163391909116146101bf57610002565b6100456004356024356000828152602081905260409020548290600160a060020a0390811633919091161461025957610002565b60408051600160a060020a03929092168252519081900360200190f35b60408051600160a060020a0384168152905184917f335721b01866dc23fbee8b6b2c7b1e14d6f05c28cd35a2c934239f94095602a0919081900360200190a2506000828152602081905260409020600101805473ffffffffffffffffffffffffffffffffffffffff1916821790555050565b60408051868152602081810187905282519182900383018220600160a060020a03871683529251929450869288927fce0457fe73731f824cc272376169235128c118b49d344817417c6d108d155e8292908290030190a382600060005060008460001916815260200190815260200160002060005060000160006101000a815481600160a060020a03021916908302179055505050505050565b60408051600160a060020a0384168152905184917fd4735d920b0f87494915f556dd9b54c8f309026070caea5c737245152564d266919081900360200190a2506000828152602081905260409020805473ffffffffffffffffffffffffffffffffffffffff191682179055505056",
"storage": {
"859ecef2e168dc10231b000bd53493b42bc9d944cac29d94582c1e1d43592131": "582c767cca9d78699b04ba8dd7c33071f2d74003"
},
"balance": ""
},
"582c767cca9d78699b04ba8dd7c33071f2d74003": {
"code": "606060405260e060020a6000350463d22057a9811461001b575b005b61001960043560243560025460408051918252602082810185905260008054835194859003840185207f02571be300000000000000000000000000000000000000000000000000000000865260048601819052935193949193600160a060020a03909116926302571be39260248181019391829003018187876161da5a03f11561000257505060405151915050600160a060020a0381166000148015906100d4575033600160a060020a031681600160a060020a031614155b156100de57610002565b60408051600080546002547f569cd59500000000000000000000000000000000000000000000000000000000845260048401526024830188905230600160a060020a039081166044850152935193169263569cd595926064818101939291829003018183876161da5a03f11561000257505060008054600154604080517f1896f70a00000000000000000000000000000000000000000000000000000000815260048101889052600160a060020a0392831660248201529051929091169350631896f70a926044828101939192829003018183876161da5a03f11561000257505060008054604080517f5b0fc9c300000000000000000000000000000000000000000000000000000000815260048101879052600160a060020a0388811660248301529151929091169350635b0fc9c3926044828101939192829003018183876161da5a03f115610002575050505050505056",
"storage": {
"0000000000000000000000000000000000000000000000000000000000000000": "d344889e0be3e9ef6c26b0f60ef66a32e83c1b69",
"0000000000000000000000000000000000000000000000000000000000000001": "cb7152b03774fd01a8480001b2bcdfebc4f04363",
"0000000000000000000000000000000000000000000000000000000000000002": "93cdeb708b7545dc668eb9280176169d1c33cfd8ed6f04690a0bcc88a93fc4ae"
},
"balance": ""
}
}
}

View file

@ -0,0 +1,103 @@
var Account = require('ethereumjs-account');
var async = require('async');
var fs = require('fs');
var rlp = require('rlp');
var solc = require('solc');
var Transaction = require('ethereumjs-tx');
var Trie = require('merkle-patricia-tree');
var utils = require('ethereumjs-util');
var VM = require('ethereumjs-vm');
var stateTrie = new Trie();
var vm = new VM(stateTrie);
var privatekey = utils.sha3("swarm");
var accountAddress = utils.privateToAddress(privatekey);
var accounts = {
"0000000000000000000000000000000000000001": "0x1",
"0000000000000000000000000000000000000002": "0x1",
"0000000000000000000000000000000000000003": "0x1",
"0000000000000000000000000000000000000004": "0x1",
};
accounts[accountAddress.toString('hex')] = "0x200000000000000";
var source = fs.readFileSync('../../services/ens/contract/ens.sol').toString();
var compiled = solc.compile(source, 1)
var deployer = "0x" + compiled.contracts['DeployENS'].bytecode;
var transactions = [
{
nonce: '0x00',
gasPrice: '0x4a817c800',
gasLimit: '0x3d0900',
value: '0x00',
data: deployer
}
];
function createAccounts(cb) {
async.each(Object.keys(accounts), function(addr, next) {
var account = new Account();
account.balance = accounts[addr];
stateTrie.put(new Buffer(addr, 'hex'), account.serialize(), next);
}, cb);
}
function runTx(cb) {
async.each(transactions, function(txdata, next) {
var tx = new Transaction(txdata);
tx.sign(privatekey);
vm.runTx({tx: tx}, next);
}, cb);
}
function dumpState(cb) {
var stream = stateTrie.createReadStream();
var accountList = [];
stream.on('data', function(data) {
accountList.push(data);
});
stream.on('end', function(err) {
var accountData = {};
async.each(accountList, function(data, next) {
var storage = {};
var account = new Account(data.value);
var storageTrie = stateTrie.copy();
storageTrie.root = account.stateRoot;
var storageStream = storageTrie.createReadStream();
storageStream.on('data', function(data) {
storage[data.key.toString('hex')] = rlp.decode(data.value).toString('hex')
});
storageStream.on('end', function(err) {
account.getCode(stateTrie, function(err, code) {
var address = data.key.toString('hex');
accountData[address] = {
code: code.toString('hex'),
storage: storage,
balance: account.balance.toString('hex')
};
next(err);
});
})
}, function(err) {
console.log(JSON.stringify({
nonce: '0x42',
gasLimit: '0x47e7c4',
difficulty: '0x20000',
alloc: accountData
}, null, 4));
});
});
}
async.series([
createAccounts,
runTx,
dumpState
], function(err) {
console.log("Error: " + err);
});

View file

@ -0,0 +1,15 @@
{
"name": "makegenesis",
"version": "0.0.0",
"dependencies": {
"async": "^2.0.1",
"ethereumjs-account": "^2.0.3",
"ethereumjs-block": "^1.2.2",
"ethereumjs-tx": "^1.1.2",
"ethereumjs-util": "^4.5.0",
"ethereumjs-vm": "^1.4.0",
"merkle-patricia-tree": "^2.1.2",
"rlp": "^2.0.0",
"solc": "0.3.5"
}
}

View file

@ -27,9 +27,11 @@ contract chequebook is mortal {
if(owner != ecrecover(hash, sig_v, sig_r, sig_s)) return;
// Attempt sending the difference between the cumulative amount on the cheque
// and the cumulative amount on the last cashed cheque to beneficiary.
if (beneficiary.send(amount - sent[beneficiary])) {
// Upon success, update the cumulative amount.
sent[beneficiary] = amount;
if (amount - sent[beneficiary] >= this.balance) {
if (beneficiary.send(amount - sent[beneficiary])) {
// Upon success, update the cumulative amount.
sent[beneficiary] = amount;
}
} else {
// Upon failure, punish owner for writing a bounced cheque.
// owner.sendToDebtorsPrison();

View file

@ -2,63 +2,33 @@
## Usage
Full documentation for the Ethereum Name Service [can be found as EIP]()
Full documentation for the Ethereum Name Service [can be found as EIP 137](https://github.com/ethereum/EIPs/issues/137)
Swarm offers a simple phase-one interface that streamlines the registration of swarm content hashes to arbitrary utf8 domain names.
The interface is offered through the ENS RPC API module under the `ens` namespace. The API can be used via the console, rpc or web3.js.
### `ens.deployRegistrar()`
### `ens.register(name)`
sends a contract creation transaction from your bzz account deploying an open registrar contract which can serve as ENS root resolver. A root resolver is deployed on the testnet and set as default for EnsRoot. Alternative can be given by changing the `ENSRoot` parameter in swarm `config.json` file.
Sends a transaction that registers a name as a top-level domain, giving ownership to the current account, and automatically deploying a simple resolver contract for it.
To deploy an alternative top-level domain root resolver:
```js
registrarAddr=ens.deployRegistrar()
// "0xa90b9572f094660f8f314b591a365985e98d2fd0"
eth.getCode(registrarAddr) // check if contract was successfully deployed
// "0x" // not mined yet
// miner.start(1) // to start mining on a private chain
// true
```
### `ens.deployResolver()`
sends a contract creation transaction from your bzz account deploying a simple personal resolver contract, that can be registered with a (sub)domain on the root resolver. As a result the root resolver will delegate all hostnames under that domain to the child resolver.
To deploy a personal resolver:
```js
resolverAddr = ens.deployResolver()
// "0x2ba72b924a7d654c54467f7bda035ddc2f6fb4eb"
eth.getCode(registrarAddr) // check if contract was successfully deployed
// "0x" // not mined yet
// miner.start(1) // to start mining on a private chain
// true
```
### `ens.register(name, address)`
Sends a transaction that registers a resolver contract with domain on the top-level resolver.
As a result the bzz account becomes the owner of that domain.
This line registers the (already deployed) personal resolver at address `resolverAddr` to the top-level domain `swarm`
This line registers the top-level domain `swarm`:
```
ens.register("swarm",resolverAddr)
ens.register("swarm")
// {}
```
### `ens.setContentHash(name, hash)`
sends a transaction that sets a content hash to a name using a (sub-domain) resolver:
Sends a transaction that sets a content hash to a name using a (sub-domain) resolver:
```js
ens.setContentHash("swarm","0x7420f14a28e276dd39da6a967dec332a932256717451155fbd3870b202b561c4")
// {}
```
The content hash argument is the bzz hash as returned by a swarm upload, e.g., using `bzz.upload`:
The name here will allow the name setting, if the top-level domain is 'swarm', it dispatches to the
resolver just registered.
To function, the domain must have a resolver deployed that supports the `setContent` function, and the sending account must have permission to call that function. `ens.register()` deploys a resolver for you that meets this requirement.
The content hash argument is the bzz hash as returned by a swarm upload, e.g., using `bzz.upload`. The name here will allow the name setting, if the top-level domain is 'swarm', it dispatches to the resolver just registered.
```js
bzz.upload("path/to/my/directory", "index.html")
@ -66,7 +36,7 @@ bzz.upload("path/to/my/directory", "index.html")
Here the second argument to `bzz.upload` is the relative path to the asset mapped on to the root hash of entire collection, effectively the landing page served on the bare hash (and therefore the root of the domain registered with that hash) as url.
The same resolver will allow setting subdomains:
`setContentHash` can also be used on subdomains:
```js
ens.setContentHash("album.swarm","7a59235e5f9c23bf74deb4838e24f75a77f786163f404c8004d79b5674625db0")
@ -88,20 +58,10 @@ This same backend method is used within swarm to resolve hostnames in urls, henc
## Development
The ABI and BIN files in contract subdirectory implement simple registrar and personal resolver contracts; they're used in tests, and can be used to deploy these contracts for your own purposes.
The SOL file in contract subdirectory implements the ENS root registry, a simple first-in-first-served registrar for the root namespace, and a simple resolver contract; they're used in tests, and can be used to deploy these contracts for your own purposes.
The solidity source code can be found at [github.com/arachnid/ens/](https://github.com/arachnid/ens/).
The ABI and BIN files in the contract subdirectory were generated by
```shell
solc -o `pwd` --optimise --abi --bin OpenRegistrar.sol
solc -o `pwd` --optimise --abi --bin PersonalResolver.sol
```
using the .sol files in [revision 1cbd90d0631e8e30e1c28a394c128e7503ea85c6](https://github.com/Arachnid/ens/commit/1cbd90d0631e8e30e1c28a394c128e7503ea85c6)
with solc version 0.3.2-e3c54185
The go bindings for ENS contracts are generated using `abigen` via the go generator:
```shell

View file

@ -1 +0,0 @@
[{"constant":false,"inputs":[{"name":"label","type":"bytes32"},{"name":"newOwner","type":"address"}],"name":"setOwner","outputs":[],"type":"function"},{"constant":true,"inputs":[{"name":"id","type":"bytes32"}],"name":"getExtended","outputs":[{"name":"data","type":"bytes"}],"type":"function"},{"constant":true,"inputs":[{"name":"nodeId","type":"bytes12"},{"name":"qtype","type":"bytes32"},{"name":"index","type":"uint16"}],"name":"resolve","outputs":[{"name":"rcode","type":"uint16"},{"name":"rtype","type":"bytes16"},{"name":"ttl","type":"uint32"},{"name":"len","type":"uint16"},{"name":"data","type":"bytes32"}],"type":"function"},{"constant":false,"inputs":[{"name":"label","type":"bytes32"},{"name":"resolver","type":"address"},{"name":"nodeId","type":"bytes12"}],"name":"register","outputs":[],"type":"function"},{"constant":true,"inputs":[{"name":"label","type":"bytes32"}],"name":"getOwner","outputs":[{"name":"","type":"address"}],"type":"function"},{"constant":true,"inputs":[{"name":"nodeId","type":"bytes12"},{"name":"label","type":"bytes32"}],"name":"findResolver","outputs":[{"name":"rcode","type":"uint16"},{"name":"ttl","type":"uint32"},{"name":"rnode","type":"bytes12"},{"name":"raddress","type":"address"}],"type":"function"}]

View file

@ -1 +0,0 @@
6060604052610348806100126000396000f3606060405236156100565760e060020a60003504635b0fc9c381146100585780638021061c1461007a578063a16fdafa14610097578063a1f8f8f0146100c0578063deb931a2146100e5578063edc0277c1461010b575b005b610056600435602435600081600160a060020a03166000141561023357610002565b6101516004356000606081905260a060405260809081525b919050565b6101bf6004356024356044356000808080808781146100b557600394505b939792965093509350565b610056600435602435604435600082600160a060020a03166000141561028057610002565b6101e5600435600081815260208190526040902060010154600160a060020a0316610092565b6102026004356024356000818152602081905260408120819081908190868214158061014357506001810154600160a060020a031682145b15610320576003945061033e565b60405180806020018281038252838181518152602001915080519060200190808383829060006004602084601f0104600f02600301f150905090810190601f1680156101b15780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b50505061ffff919091166060908152608082905260a082815260c083905260e092909252f35b60408051600160a060020a03929092168252519081900360200190f35b61ffff93909316606090815263ffffffff92909216608090815260a091909152600160a060020a039290921660c052f35b828152602081905260409020600181015433600160a060020a0390811691161461025c57610002565b600101805473ffffffffffffffffffffffffffffffffffffffff1916909117905550565b83815260208190526040812060018101549091600160a060020a03909116148015906102bd5750600181015433600160a060020a03908116911614155b156102c757610002565b60018101805460c0604052606085905260808490523360a0819052835460a060020a8087040273ffffffffffffffffffffffffffffffffffffffff199182168817600160a060020a031617855590911617905550505050565b8054610e10945060a060020a808204029350600160a060020a031691505b509295919450925056

View file

@ -1,366 +0,0 @@
// This file is an automatically generated Go binding. Do not modify as any
// change will likely be lost upon the next re-generation!
package contract
import (
"strings"
"github.com/ethereum/go-ethereum/accounts/abi"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
)
// OpenRegistrarABI is the input ABI used to generate the binding from.
const OpenRegistrarABI = `[{"constant":false,"inputs":[{"name":"label","type":"bytes32"},{"name":"newOwner","type":"address"}],"name":"setOwner","outputs":[],"type":"function"},{"constant":true,"inputs":[{"name":"id","type":"bytes32"}],"name":"getExtended","outputs":[{"name":"data","type":"bytes"}],"type":"function"},{"constant":true,"inputs":[{"name":"nodeId","type":"bytes12"},{"name":"qtype","type":"bytes32"},{"name":"index","type":"uint16"}],"name":"resolve","outputs":[{"name":"rcode","type":"uint16"},{"name":"rtype","type":"bytes16"},{"name":"ttl","type":"uint32"},{"name":"len","type":"uint16"},{"name":"data","type":"bytes32"}],"type":"function"},{"constant":false,"inputs":[{"name":"label","type":"bytes32"},{"name":"resolver","type":"address"},{"name":"nodeId","type":"bytes12"}],"name":"register","outputs":[],"type":"function"},{"constant":false,"inputs":[{"name":"label","type":"bytes32"},{"name":"resolver","type":"address"},{"name":"nodeId","type":"bytes12"}],"name":"setResolver","outputs":[],"type":"function"},{"constant":true,"inputs":[{"name":"label","type":"bytes32"}],"name":"getOwner","outputs":[{"name":"","type":"address"}],"type":"function"},{"constant":true,"inputs":[{"name":"nodeId","type":"bytes12"},{"name":"label","type":"bytes32"}],"name":"findResolver","outputs":[{"name":"rcode","type":"uint16"},{"name":"ttl","type":"uint32"},{"name":"rnode","type":"bytes12"},{"name":"raddress","type":"address"}],"type":"function"}]`
// OpenRegistrarBin is the compiled bytecode used for deploying new contracts.
const OpenRegistrarBin = `606060405261083b806100126000396000f36060604052361561007f576000357c0100000000000000000000000000000000000000000000000000000000900480635b0fc9c3146100815780638021061c146100a2578063a16fdafa14610126578063a1f8f8f0146101a5578063a9f2a1b2146101cf578063deb931a2146101f9578063edc0277c1461023b5761007f565b005b6100a060048080359060200190919080359060200190919050506102bc565b005b6100b86004808035906020019091905050610392565b60405180806020018281038252838181518152602001915080519060200190808383829060006004602084601f0104600f02600301f150905090810190601f1680156101185780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b61014e60048080359060200190919080359060200190919080359060200190919050506103c6565b604051808661ffff168152602001856fffffffffffffffffffffffffffffffff191681526020018463ffffffff1681526020018361ffff168152602001826000191681526020019550505050505060405180910390f35b6101cd600480803590602001909190803590602001909190803590602001909190505061041f565b005b6101f760048080359060200190919080359060200190919080359060200190919050506105ac565b005b61020f60048080359060200190919050506106c0565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b61025a600480803590602001909190803590602001909190505061070f565b604051808561ffff1681526020018463ffffffff1681526020018373ffffffffffffffffffffffffffffffffffffffff191681526020018273ffffffffffffffffffffffffffffffffffffffff16815260200194505050505060405180910390f35b600060008273ffffffffffffffffffffffffffffffffffffffff1614156102e257610002565b600060005060008460001916815260200190815260200160002060005090503373ffffffffffffffffffffffffffffffffffffffff168160010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614151561035f57610002565b818160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908302179055505b505050565b6020604051908101604052806000815260200150602060405190810160405280600081526020015090506103c1565b919050565b60006000600060006000600074010000000000000000000000000000000000000000028873ffffffffffffffffffffffffffffffffffffffff191614151561041357600394508450610414565b5b939792965093509350565b600060008373ffffffffffffffffffffffffffffffffffffffff16141561044557610002565b60006000506000856000191681526020019081526020016000206000509050600073ffffffffffffffffffffffffffffffffffffffff168160010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161415156104c357610002565b60606040519081016040528084815260200183815260200133815260200150600060005060008660001916815260200190815260200160002060005060008201518160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff0219169083021790555060208201518160000160146101000a8154816bffffffffffffffffffffffff0219169083740100000000000000000000000000000000000000009004021790555060408201518160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908302179055509050505b50505050565b600060008373ffffffffffffffffffffffffffffffffffffffff1614156105d257610002565b600060005060008560001916815260200190815260200160002060005090503373ffffffffffffffffffffffffffffffffffffffff168160010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614151561064f57610002565b828160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff02191690830217905550818160000160146101000a8154816bffffffffffffffffffffffff021916908374010000000000000000000000000000000000000000900402179055505b50505050565b6000600060005060008360001916815260200190815260200160002060005060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905061070a565b919050565b6000600060006000600060006000506000876000191681526020019081526020016000206000509050600074010000000000000000000000000000000000000000028773ffffffffffffffffffffffffffffffffffffffff19161415806107c65750600073ffffffffffffffffffffffffffffffffffffffff168160010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16145b156107d657600394508450610831565b610e10935083508060000160149054906101000a90047401000000000000000000000000000000000000000002925082508060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16915081505b509295919450925056`
// DeployOpenRegistrar deploys a new Ethereum contract, binding an instance of OpenRegistrar to it.
func DeployOpenRegistrar(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *OpenRegistrar, error) {
parsed, err := abi.JSON(strings.NewReader(OpenRegistrarABI))
if err != nil {
return common.Address{}, nil, nil, err
}
address, tx, contract, err := bind.DeployContract(auth, parsed, common.FromHex(OpenRegistrarBin), backend)
if err != nil {
return common.Address{}, nil, nil, err
}
return address, tx, &OpenRegistrar{OpenRegistrarCaller: OpenRegistrarCaller{contract: contract}, OpenRegistrarTransactor: OpenRegistrarTransactor{contract: contract}}, nil
}
// OpenRegistrar is an auto generated Go binding around an Ethereum contract.
type OpenRegistrar struct {
OpenRegistrarCaller // Read-only binding to the contract
OpenRegistrarTransactor // Write-only binding to the contract
}
// OpenRegistrarCaller is an auto generated read-only Go binding around an Ethereum contract.
type OpenRegistrarCaller struct {
contract *bind.BoundContract // Generic contract wrapper for the low level calls
}
// OpenRegistrarTransactor is an auto generated write-only Go binding around an Ethereum contract.
type OpenRegistrarTransactor struct {
contract *bind.BoundContract // Generic contract wrapper for the low level calls
}
// OpenRegistrarSession is an auto generated Go binding around an Ethereum contract,
// with pre-set call and transact options.
type OpenRegistrarSession struct {
Contract *OpenRegistrar // Generic contract binding to set the session for
CallOpts bind.CallOpts // Call options to use throughout this session
TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session
}
// OpenRegistrarCallerSession is an auto generated read-only Go binding around an Ethereum contract,
// with pre-set call options.
type OpenRegistrarCallerSession struct {
Contract *OpenRegistrarCaller // Generic contract caller binding to set the session for
CallOpts bind.CallOpts // Call options to use throughout this session
}
// OpenRegistrarTransactorSession is an auto generated write-only Go binding around an Ethereum contract,
// with pre-set transact options.
type OpenRegistrarTransactorSession struct {
Contract *OpenRegistrarTransactor // Generic contract transactor binding to set the session for
TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session
}
// OpenRegistrarRaw is an auto generated low-level Go binding around an Ethereum contract.
type OpenRegistrarRaw struct {
Contract *OpenRegistrar // Generic contract binding to access the raw methods on
}
// OpenRegistrarCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract.
type OpenRegistrarCallerRaw struct {
Contract *OpenRegistrarCaller // Generic read-only contract binding to access the raw methods on
}
// OpenRegistrarTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract.
type OpenRegistrarTransactorRaw struct {
Contract *OpenRegistrarTransactor // Generic write-only contract binding to access the raw methods on
}
// NewOpenRegistrar creates a new instance of OpenRegistrar, bound to a specific deployed contract.
func NewOpenRegistrar(address common.Address, backend bind.ContractBackend) (*OpenRegistrar, error) {
contract, err := bindOpenRegistrar(address, backend.(bind.ContractCaller), backend.(bind.ContractTransactor))
if err != nil {
return nil, err
}
return &OpenRegistrar{OpenRegistrarCaller: OpenRegistrarCaller{contract: contract}, OpenRegistrarTransactor: OpenRegistrarTransactor{contract: contract}}, nil
}
// NewOpenRegistrarCaller creates a new read-only instance of OpenRegistrar, bound to a specific deployed contract.
func NewOpenRegistrarCaller(address common.Address, caller bind.ContractCaller) (*OpenRegistrarCaller, error) {
contract, err := bindOpenRegistrar(address, caller, nil)
if err != nil {
return nil, err
}
return &OpenRegistrarCaller{contract: contract}, nil
}
// NewOpenRegistrarTransactor creates a new write-only instance of OpenRegistrar, bound to a specific deployed contract.
func NewOpenRegistrarTransactor(address common.Address, transactor bind.ContractTransactor) (*OpenRegistrarTransactor, error) {
contract, err := bindOpenRegistrar(address, nil, transactor)
if err != nil {
return nil, err
}
return &OpenRegistrarTransactor{contract: contract}, nil
}
// bindOpenRegistrar binds a generic wrapper to an already deployed contract.
func bindOpenRegistrar(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor) (*bind.BoundContract, error) {
parsed, err := abi.JSON(strings.NewReader(OpenRegistrarABI))
if err != nil {
return nil, err
}
return bind.NewBoundContract(address, parsed, caller, transactor), nil
}
// Call invokes the (constant) contract method with params as input values and
// sets the output to result. The result type might be a single field for simple
// returns, a slice of interfaces for anonymous returns and a struct for named
// returns.
func (_OpenRegistrar *OpenRegistrarRaw) Call(opts *bind.CallOpts, result interface{}, method string, params ...interface{}) error {
return _OpenRegistrar.Contract.OpenRegistrarCaller.contract.Call(opts, result, method, params...)
}
// Transfer initiates a plain transaction to move funds to the contract, calling
// its default method if one is available.
func (_OpenRegistrar *OpenRegistrarRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) {
return _OpenRegistrar.Contract.OpenRegistrarTransactor.contract.Transfer(opts)
}
// Transact invokes the (paid) contract method with params as input values.
func (_OpenRegistrar *OpenRegistrarRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) {
return _OpenRegistrar.Contract.OpenRegistrarTransactor.contract.Transact(opts, method, params...)
}
// Call invokes the (constant) contract method with params as input values and
// sets the output to result. The result type might be a single field for simple
// returns, a slice of interfaces for anonymous returns and a struct for named
// returns.
func (_OpenRegistrar *OpenRegistrarCallerRaw) Call(opts *bind.CallOpts, result interface{}, method string, params ...interface{}) error {
return _OpenRegistrar.Contract.contract.Call(opts, result, method, params...)
}
// Transfer initiates a plain transaction to move funds to the contract, calling
// its default method if one is available.
func (_OpenRegistrar *OpenRegistrarTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) {
return _OpenRegistrar.Contract.contract.Transfer(opts)
}
// Transact invokes the (paid) contract method with params as input values.
func (_OpenRegistrar *OpenRegistrarTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) {
return _OpenRegistrar.Contract.contract.Transact(opts, method, params...)
}
// FindResolver is a free data retrieval call binding the contract method 0xedc0277c.
//
// Solidity: function findResolver(nodeId bytes12, label bytes32) constant returns(rcode uint16, ttl uint32, rnode bytes12, raddress address)
func (_OpenRegistrar *OpenRegistrarCaller) FindResolver(opts *bind.CallOpts, nodeId [12]byte, label [32]byte) (struct {
Rcode uint16
Ttl uint32
Rnode [12]byte
Raddress common.Address
}, error) {
ret := new(struct {
Rcode uint16
Ttl uint32
Rnode [12]byte
Raddress common.Address
})
out := ret
err := _OpenRegistrar.contract.Call(opts, out, "findResolver", nodeId, label)
return *ret, err
}
// FindResolver is a free data retrieval call binding the contract method 0xedc0277c.
//
// Solidity: function findResolver(nodeId bytes12, label bytes32) constant returns(rcode uint16, ttl uint32, rnode bytes12, raddress address)
func (_OpenRegistrar *OpenRegistrarSession) FindResolver(nodeId [12]byte, label [32]byte) (struct {
Rcode uint16
Ttl uint32
Rnode [12]byte
Raddress common.Address
}, error) {
return _OpenRegistrar.Contract.FindResolver(&_OpenRegistrar.CallOpts, nodeId, label)
}
// FindResolver is a free data retrieval call binding the contract method 0xedc0277c.
//
// Solidity: function findResolver(nodeId bytes12, label bytes32) constant returns(rcode uint16, ttl uint32, rnode bytes12, raddress address)
func (_OpenRegistrar *OpenRegistrarCallerSession) FindResolver(nodeId [12]byte, label [32]byte) (struct {
Rcode uint16
Ttl uint32
Rnode [12]byte
Raddress common.Address
}, error) {
return _OpenRegistrar.Contract.FindResolver(&_OpenRegistrar.CallOpts, nodeId, label)
}
// GetExtended is a free data retrieval call binding the contract method 0x8021061c.
//
// Solidity: function getExtended(id bytes32) constant returns(data bytes)
func (_OpenRegistrar *OpenRegistrarCaller) GetExtended(opts *bind.CallOpts, id [32]byte) ([]byte, error) {
var (
ret0 = new([]byte)
)
out := ret0
err := _OpenRegistrar.contract.Call(opts, out, "getExtended", id)
return *ret0, err
}
// GetExtended is a free data retrieval call binding the contract method 0x8021061c.
//
// Solidity: function getExtended(id bytes32) constant returns(data bytes)
func (_OpenRegistrar *OpenRegistrarSession) GetExtended(id [32]byte) ([]byte, error) {
return _OpenRegistrar.Contract.GetExtended(&_OpenRegistrar.CallOpts, id)
}
// GetExtended is a free data retrieval call binding the contract method 0x8021061c.
//
// Solidity: function getExtended(id bytes32) constant returns(data bytes)
func (_OpenRegistrar *OpenRegistrarCallerSession) GetExtended(id [32]byte) ([]byte, error) {
return _OpenRegistrar.Contract.GetExtended(&_OpenRegistrar.CallOpts, id)
}
// GetOwner is a free data retrieval call binding the contract method 0xdeb931a2.
//
// Solidity: function getOwner(label bytes32) constant returns(address)
func (_OpenRegistrar *OpenRegistrarCaller) GetOwner(opts *bind.CallOpts, label [32]byte) (common.Address, error) {
var (
ret0 = new(common.Address)
)
out := ret0
err := _OpenRegistrar.contract.Call(opts, out, "getOwner", label)
return *ret0, err
}
// GetOwner is a free data retrieval call binding the contract method 0xdeb931a2.
//
// Solidity: function getOwner(label bytes32) constant returns(address)
func (_OpenRegistrar *OpenRegistrarSession) GetOwner(label [32]byte) (common.Address, error) {
return _OpenRegistrar.Contract.GetOwner(&_OpenRegistrar.CallOpts, label)
}
// GetOwner is a free data retrieval call binding the contract method 0xdeb931a2.
//
// Solidity: function getOwner(label bytes32) constant returns(address)
func (_OpenRegistrar *OpenRegistrarCallerSession) GetOwner(label [32]byte) (common.Address, error) {
return _OpenRegistrar.Contract.GetOwner(&_OpenRegistrar.CallOpts, label)
}
// Resolve is a free data retrieval call binding the contract method 0xa16fdafa.
//
// Solidity: function resolve(nodeId bytes12, qtype bytes32, index uint16) constant returns(rcode uint16, rtype bytes16, ttl uint32, len uint16, data bytes32)
func (_OpenRegistrar *OpenRegistrarCaller) Resolve(opts *bind.CallOpts, nodeId [12]byte, qtype [32]byte, index uint16) (struct {
Rcode uint16
Rtype [16]byte
Ttl uint32
Len uint16
Data [32]byte
}, error) {
ret := new(struct {
Rcode uint16
Rtype [16]byte
Ttl uint32
Len uint16
Data [32]byte
})
out := ret
err := _OpenRegistrar.contract.Call(opts, out, "resolve", nodeId, qtype, index)
return *ret, err
}
// Resolve is a free data retrieval call binding the contract method 0xa16fdafa.
//
// Solidity: function resolve(nodeId bytes12, qtype bytes32, index uint16) constant returns(rcode uint16, rtype bytes16, ttl uint32, len uint16, data bytes32)
func (_OpenRegistrar *OpenRegistrarSession) Resolve(nodeId [12]byte, qtype [32]byte, index uint16) (struct {
Rcode uint16
Rtype [16]byte
Ttl uint32
Len uint16
Data [32]byte
}, error) {
return _OpenRegistrar.Contract.Resolve(&_OpenRegistrar.CallOpts, nodeId, qtype, index)
}
// Resolve is a free data retrieval call binding the contract method 0xa16fdafa.
//
// Solidity: function resolve(nodeId bytes12, qtype bytes32, index uint16) constant returns(rcode uint16, rtype bytes16, ttl uint32, len uint16, data bytes32)
func (_OpenRegistrar *OpenRegistrarCallerSession) Resolve(nodeId [12]byte, qtype [32]byte, index uint16) (struct {
Rcode uint16
Rtype [16]byte
Ttl uint32
Len uint16
Data [32]byte
}, error) {
return _OpenRegistrar.Contract.Resolve(&_OpenRegistrar.CallOpts, nodeId, qtype, index)
}
// Register is a paid mutator transaction binding the contract method 0xa1f8f8f0.
//
// Solidity: function register(label bytes32, resolver address, nodeId bytes12) returns()
func (_OpenRegistrar *OpenRegistrarTransactor) Register(opts *bind.TransactOpts, label [32]byte, resolver common.Address, nodeId [12]byte) (*types.Transaction, error) {
return _OpenRegistrar.contract.Transact(opts, "register", label, resolver, nodeId)
}
// Register is a paid mutator transaction binding the contract method 0xa1f8f8f0.
//
// Solidity: function register(label bytes32, resolver address, nodeId bytes12) returns()
func (_OpenRegistrar *OpenRegistrarSession) Register(label [32]byte, resolver common.Address, nodeId [12]byte) (*types.Transaction, error) {
return _OpenRegistrar.Contract.Register(&_OpenRegistrar.TransactOpts, label, resolver, nodeId)
}
// Register is a paid mutator transaction binding the contract method 0xa1f8f8f0.
//
// Solidity: function register(label bytes32, resolver address, nodeId bytes12) returns()
func (_OpenRegistrar *OpenRegistrarTransactorSession) Register(label [32]byte, resolver common.Address, nodeId [12]byte) (*types.Transaction, error) {
return _OpenRegistrar.Contract.Register(&_OpenRegistrar.TransactOpts, label, resolver, nodeId)
}
// SetOwner is a paid mutator transaction binding the contract method 0x5b0fc9c3.
//
// Solidity: function setOwner(label bytes32, newOwner address) returns()
func (_OpenRegistrar *OpenRegistrarTransactor) SetOwner(opts *bind.TransactOpts, label [32]byte, newOwner common.Address) (*types.Transaction, error) {
return _OpenRegistrar.contract.Transact(opts, "setOwner", label, newOwner)
}
// SetOwner is a paid mutator transaction binding the contract method 0x5b0fc9c3.
//
// Solidity: function setOwner(label bytes32, newOwner address) returns()
func (_OpenRegistrar *OpenRegistrarSession) SetOwner(label [32]byte, newOwner common.Address) (*types.Transaction, error) {
return _OpenRegistrar.Contract.SetOwner(&_OpenRegistrar.TransactOpts, label, newOwner)
}
// SetOwner is a paid mutator transaction binding the contract method 0x5b0fc9c3.
//
// Solidity: function setOwner(label bytes32, newOwner address) returns()
func (_OpenRegistrar *OpenRegistrarTransactorSession) SetOwner(label [32]byte, newOwner common.Address) (*types.Transaction, error) {
return _OpenRegistrar.Contract.SetOwner(&_OpenRegistrar.TransactOpts, label, newOwner)
}
// SetResolver is a paid mutator transaction binding the contract method 0xa9f2a1b2.
//
// Solidity: function setResolver(label bytes32, resolver address, nodeId bytes12) returns()
func (_OpenRegistrar *OpenRegistrarTransactor) SetResolver(opts *bind.TransactOpts, label [32]byte, resolver common.Address, nodeId [12]byte) (*types.Transaction, error) {
return _OpenRegistrar.contract.Transact(opts, "setResolver", label, resolver, nodeId)
}
// SetResolver is a paid mutator transaction binding the contract method 0xa9f2a1b2.
//
// Solidity: function setResolver(label bytes32, resolver address, nodeId bytes12) returns()
func (_OpenRegistrar *OpenRegistrarSession) SetResolver(label [32]byte, resolver common.Address, nodeId [12]byte) (*types.Transaction, error) {
return _OpenRegistrar.Contract.SetResolver(&_OpenRegistrar.TransactOpts, label, resolver, nodeId)
}
// SetResolver is a paid mutator transaction binding the contract method 0xa9f2a1b2.
//
// Solidity: function setResolver(label bytes32, resolver address, nodeId bytes12) returns()
func (_OpenRegistrar *OpenRegistrarTransactorSession) SetResolver(label [32]byte, resolver common.Address, nodeId [12]byte) (*types.Transaction, error) {
return _OpenRegistrar.Contract.SetResolver(&_OpenRegistrar.TransactOpts, label, resolver, nodeId)
}

View file

@ -1 +0,0 @@
[{"constant":false,"inputs":[{"name":"newOwner","type":"address"}],"name":"setOwner","outputs":[],"type":"function"},{"constant":false,"inputs":[{"name":"rootNodeId","type":"bytes12"},{"name":"name","type":"bytes32[]"}],"name":"deletePrivateRR","outputs":[],"type":"function"},{"constant":true,"inputs":[],"name":"isPersonalResolver","outputs":[{"name":"","type":"bool"}],"type":"function"},{"constant":true,"inputs":[{"name":"id","type":"bytes32"}],"name":"getExtended","outputs":[{"name":"data","type":"bytes"}],"type":"function"},{"constant":false,"inputs":[{"name":"rootNodeId","type":"bytes12"},{"name":"name","type":"string"},{"name":"rtype","type":"bytes16"},{"name":"ttl","type":"uint32"},{"name":"len","type":"uint16"},{"name":"data","type":"bytes32"}],"name":"setRR","outputs":[],"type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"type":"function"},{"constant":false,"inputs":[{"name":"rootNodeId","type":"bytes12"},{"name":"name","type":"bytes32[]"},{"name":"rtype","type":"bytes16"},{"name":"ttl","type":"uint32"},{"name":"len","type":"uint16"},{"name":"data","type":"bytes32"}],"name":"setPrivateRR","outputs":[],"type":"function"},{"constant":true,"inputs":[{"name":"nodeId","type":"bytes12"},{"name":"qtype","type":"bytes32"},{"name":"index","type":"uint16"}],"name":"resolve","outputs":[{"name":"rcode","type":"uint16"},{"name":"rtype","type":"bytes16"},{"name":"ttl","type":"uint32"},{"name":"len","type":"uint16"},{"name":"data","type":"bytes32"}],"type":"function"},{"constant":false,"inputs":[{"name":"rootNodeId","type":"bytes12"},{"name":"name","type":"string"}],"name":"deleteRR","outputs":[],"type":"function"},{"constant":true,"inputs":[{"name":"nodeId","type":"bytes12"},{"name":"label","type":"bytes32"}],"name":"findResolver","outputs":[{"name":"rcode","type":"uint16"},{"name":"ttl","type":"uint32"},{"name":"rnode","type":"bytes12"},{"name":"raddress","type":"address"}],"type":"function"},{"inputs":[],"type":"constructor"}]

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load diff

View file

@ -1,31 +1,226 @@
/**
* ENS resolver interface.
* The ENS registry contract.
*/
contract Resolver {
bytes32 constant TYPE_STAR = "*";
contract ENS {
struct Record {
address owner;
address resolver;
}
// Response codes.
uint16 constant RCODE_OK = 0;
uint16 constant RCODE_NXDOMAIN = 3;
mapping(bytes32=>Record) records;
// These methods are shared by all resolvers
function findResolver(bytes12 nodeId, bytes32 label) constant
returns (uint16 rcode, uint32 ttl, bytes12 rnode, address raddress);
function resolve(bytes12 nodeId, bytes32 qtype, uint16 index) constant
returns (uint16 rcode, bytes16 rtype, uint32 ttl, uint16 len,
bytes32 data);
function getExtended(bytes32 id) constant returns (bytes data);
// Logged when the owner of a node assigns a new owner to a subnode.
event NewOwner(bytes32 indexed node, bytes32 indexed label, address owner);
// These methods are implemented by personal resolvers
function isPersonalResolver() constant returns (bool);
function setRR(bytes12 rootNodeId, string name, bytes16 rtype, uint32 ttl, uint16 len, bytes32 data);
function setPrivateRR(bytes12 rootNodeId, bytes32[] name, bytes16 rtype, uint32 ttl, uint16 len, bytes32 data);
function deleteRR(bytes12 rootNodeId, string name);
function deletePrivateRR(bytes12 rootNodeId, bytes32[] name);
// Logged when the owner of a node transfers ownership to a new account.
event Transfer(bytes32 indexed node, address owner);
// These methods are implemented by open registrar implementations.
function register(bytes32 label, address resolver, bytes12 nodeId);
function setOwner(bytes32 label, address newOwner);
function setResolver(bytes32 label, address resolver, bytes12 nodeId);
function getOwner(bytes32 label) constant returns (address);
// Logged when the owner of a node changes the resolver for that node.
event NewResolver(bytes32 indexed node, address resolver);
// Permits modifications only by the owner of the specified node.
modifier only_owner(bytes32 node) {
if(records[node].owner != msg.sender) throw;
_
}
/**
* Constructs a new ENS registrar, with the provided address as the owner of the root node.
*/
function ENS(address owner) {
records[0].owner = owner;
}
/**
* Returns the address that owns the specified node.
*/
function owner(bytes32 node) constant returns (address) {
return records[node].owner;
}
/**
* Returns the address of the resolver for the specified node.
*/
function resolver(bytes32 node) constant returns (address) {
return records[node].resolver;
}
/**
* Transfers ownership of a node to a new address. May only be called by the current
* owner of the node.
* @param node The node to transfer ownership of.
* @param owner The address of the new owner.
*/
function setOwner(bytes32 node, address owner) only_owner(node) {
Transfer(node, owner);
records[node].owner = owner;
}
/**
* Transfers ownership of a subnode sha3(node, label) to a new address. May only be
* called by the owner of the parent node.
* @param node The parent node.
* @param label The hash of the label specifying the subnode.
* @param owner The address of the new owner.
*/
function setOwner(bytes32 node, bytes32 label, address owner) only_owner(node) {
var subnode = sha3(node, label);
NewOwner(node, label, owner);
records[subnode].owner = owner;
}
/**
* Sets the resolver address for the specified node.
* @param node The node to update.
* @param resolver The address of the resolver.
*/
function setResolver(bytes32 node, address resolver) only_owner(node) {
NewResolver(node, resolver);
records[node].resolver = resolver;
}
}
/**
* A registrar that allocates subdomains to the first person to claim them. It also deploys
* a simple resolver contract and sets that as the default resolver on new names for
* convenience.
*/
contract FIFSRegistrar {
ENS ens;
PublicResolver defaultResolver;
bytes32 rootNode;
/**
* Constructor.
* @param ensAddr The address of the ENS registry.
* @param node The node that this registrar administers.
*/
function FIFSRegistrar(address ensAddr, bytes32 node) {
ens = ENS(ensAddr);
defaultResolver = new PublicResolver(ensAddr);
rootNode = node;
}
/**
* Register a name, or change the owner of an existing registration.
* @param subnode The hash of the label to register.
* @param owner The address of the new owner.
*/
function register(bytes32 subnode, address owner) {
var node = sha3(rootNode, subnode);
var currentOwner = ens.owner(node);
if(currentOwner != 0 && currentOwner != msg.sender)
throw;
// Temporarily set ourselves as the owner
ens.setOwner(rootNode, subnode, this);
// Set up the default resolver
ens.setResolver(node, defaultResolver);
// Set the owner to the real owner
ens.setOwner(node, owner);
}
}
contract Resolver {
event AddrChanged(bytes32 indexed node, address a);
event ContentChanged(bytes32 indexed node, bytes32 hash);
function has(bytes32 node, bytes32 kind) returns (bool);
function addr(bytes32 node) constant returns (address ret);
function content(bytes32 node) constant returns (bytes32 ret);
}
/**
* A simple resolver anyone can use; only allows the owner of a node to set its
* address.
*/
contract PublicResolver is Resolver {
ENS ens;
mapping(bytes32=>address) addresses;
mapping(bytes32=>bytes32) contents;
modifier only_owner(bytes32 node) {
if(ens.owner(node) != msg.sender) throw;
_
}
/**
* Constructor.
* @param ensAddr The ENS registrar contract.
*/
function PublicResolver(address ensAddr) {
ens = ENS(ensAddr);
}
/**
* Fallback function.
*/
function() {
throw;
}
/**
* Returns true if the specified node has the specified record type.
* @param node The ENS node to query.
* @param kind The record type name, as specified in EIP137.
* @return True if this resolver has a record of the provided type on the
* provided node.
*/
function has(bytes32 node, bytes32 kind) returns (bool) {
return (kind == "addr" && addresses[node] != 0) ||
(kind == "content" && contents[node] != 0);
}
/**
* Returns the address associated with an ENS node.
* @param node The ENS node to query.
* @return The associated address.
*/
function addr(bytes32 node) constant returns (address ret) {
ret = addresses[node];
if(ret == 0)
throw;
}
/**
* Returns the content hash associated with an ENS node.
* @param node The ENS node to query.
* @return The associated content hash.
*/
function content(bytes32 node) constant returns (bytes32 ret) {
ret = contents[node];
if(ret == 0)
throw;
}
/**
* Sets the address associated with an ENS node.
* May only be called by the owner of that node in the ENS registry.
* @param node The node to update.
* @param addr The address to set.
*/
function setAddr(bytes32 node, address addr) only_owner(node) {
addresses[node] = addr;
AddrChanged(node, addr);
}
/**
* Sets the content hash associated with an ENS node.
* May only be called by the owner of that node in the ENS registry.
* @param node The node to update.
* @param hash The content hash to set.
*/
function setContent(bytes32 node, bytes32 hash) only_owner(node) {
contents[node] = hash;
ContentChanged(node, hash);
}
}
contract DeployENS {
function DeployENS() {
var ens = new ENS(this);
var registrar = new FIFSRegistrar(ens, 0);
ens.setOwner(0, registrar);
selfdestruct(msg.sender);
}
}

View file

@ -1,8 +1,9 @@
//go:generate abigen --sol contract/ens.sol --pkg contract --out contract/ens.go
//go:generate abigen --sol contract/ENS.sol --pkg contract --out contract/ens.go
package ens
import (
"fmt"
"math/big"
"strings"
"github.com/ethereum/go-ethereum/accounts/abi/bind"
@ -13,182 +14,150 @@ import (
"github.com/ethereum/go-ethereum/swarm/storage"
)
var qtypeChash = [32]byte{0x43, 0x48, 0x41, 0x53, 0x48}
var rtypeChash = [16]byte{0x43, 0x48, 0x41, 0x53, 0x48}
// swarm domain name registry and resolver
// the ENS instance can be directly wrapped in rpc.Api
type ENS struct {
transactOpts *bind.TransactOpts
*contract.ENSSession
contractBackend bind.ContractBackend
rootAddress common.Address
}
func NewENS(transactOpts *bind.TransactOpts, contractAddr common.Address, contractBackend bind.ContractBackend) *ENS {
return &ENS{
transactOpts: transactOpts,
contractBackend: contractBackend,
rootAddress: contractAddr,
}
}
func (self *ENS) DeployRegistrar() (common.Address, error) {
addr, _, _, err := contract.DeployOpenRegistrar(self.transactOpts, self.contractBackend)
if err != nil {
return common.Address{}, err
}
return addr, nil
}
func (self *ENS) DeployResolver() (common.Address, error) {
addr, _, _, err := contract.DeployPersonalResolver(self.transactOpts, self.contractBackend)
if err != nil {
return common.Address{}, err
}
return addr, nil
}
func (self *ENS) newResolver(contractAddr common.Address) (*contract.ResolverSession, error) {
resolver, err := contract.NewResolver(contractAddr, self.contractBackend)
// NewENS creates a struct exposing convenient high-level operations for interacting with
// the Ethereum Name Service.
func NewENS(transactOpts *bind.TransactOpts, contractAddr common.Address, contractBackend bind.ContractBackend) (*ENS, error) {
ens, err := contract.NewENS(contractAddr, contractBackend)
if err != nil {
return nil, err
}
return &contract.ResolverSession{
Contract: resolver,
TransactOpts: *self.transactOpts,
return &ENS{
&contract.ENSSession{
Contract: ens,
TransactOpts: *transactOpts,
},
contractBackend,
}, nil
}
// resolve is a non-tranasctional call, returns hash as storage.Key
func (self *ENS) Resolve(name string) (storage.Key, error) {
return self.resolveName(self.rootAddress, name)
}
func (self *ENS) nextResolver(resolver *contract.ResolverSession, nodeId [12]byte, label string) (*contract.ResolverSession, [12]byte, error) {
hash := crypto.Sha3Hash([]byte(label))
ret, err := resolver.FindResolver(nodeId, hash)
if err != nil {
err = fmt.Errorf("error resolving label '%v': %v", label, err)
return nil, [12]byte{}, err
}
if ret.Rcode != 0 {
err = fmt.Errorf("error resolving label '%v': got response code %v", label, ret.Rcode)
return nil, [12]byte{}, err
}
nodeId = ret.Rnode
resolver, err = self.newResolver(ret.Raddress)
if err != nil {
return nil, [12]byte{}, err
}
return resolver, nodeId, nil
}
func (self *ENS) findResolver(rootAddress common.Address, host string) (*contract.ResolverSession, [12]byte, error) {
resolver, err := self.newResolver(self.rootAddress)
if err != nil {
return nil, [12]byte{}, err
}
if len(host) == 0 {
return resolver, [12]byte{}, nil
}
labels := strings.Split(host, ".")
var nodeId [12]byte
for i := len(labels) - 1; i >= 0; i-- {
var err error
resolver, nodeId, err = self.nextResolver(resolver, nodeId, labels[i])
if err != nil {
return nil, [12]byte{}, err
}
}
return resolver, nodeId, nil
}
func (self *ENS) resolveName(rootAddress common.Address, host string) (storage.Key, error) {
resolver, nodeId, err := self.findResolver(rootAddress, host)
// DeployENS deploys an instance of the ENS nameservice, with a 'first in first served' root registrar.
func DeployENS(transactOpts *bind.TransactOpts, contractBackend bind.ContractBackend) (*ENS, error) {
// Deploy the ENS registry
ensAddr, _, _, err := contract.DeployENS(transactOpts, contractBackend, transactOpts.From)
if err != nil {
return nil, err
}
ret, err := resolver.Resolve(nodeId, qtypeChash, 0)
ens, err := NewENS(transactOpts, ensAddr, contractBackend)
if err != nil {
return nil, fmt.Errorf("error looking up RR on '%v': %v", host, err)
return nil, err
}
if ret.Rcode != 0 {
return nil, fmt.Errorf("error looking up RR on '%v': got response code %v", host, ret.Rcode)
// Deploy the registrar
regAddr, _, _, err := contract.DeployFIFSRegistrar(transactOpts, contractBackend, ensAddr, [32]byte{})
if err != nil {
return nil, err
}
return storage.Key(ret.Data[:]), nil
// Set the registrar as owner of the ENS root
_, err = ens.SetOwner([32]byte{}, regAddr)
if err != nil {
return nil, err
}
return ens, nil
}
/**
* Registers a new domain name for the caller, making them the owner of the new name.
*/
func (self *ENS) Register(name string, resolverAddress common.Address) (*types.Transaction, error) {
// Find the resolver that we should register with (the one that controls the parent domain)
func ensParentNode(name string) (common.Hash, common.Hash) {
parts := strings.SplitN(name, ".", 2)
baseName := ""
if len(parts) > 1 {
baseName = parts[1]
}
resolver, nodeId, err := self.findResolver(self.rootAddress, baseName)
if err != nil {
return nil, err
}
if nodeId != [12]byte{} {
return nil, fmt.Errorf("cannot register domains on %v: not a root node", baseName)
}
// Send it a register transaction
hash := crypto.Sha3Hash([]byte(parts[0]))
return resolver.Register(hash, resolverAddress, [12]byte{})
}
/**
* Steps through name components until it finds a PersonalResolver contract.
* Returns the resolver, the node ID, and the remaining name components.
*/
func (self *ENS) findPersonalResolver(name string) (*contract.ResolverSession, [12]byte, string, error) {
var nodeId [12]byte
resolver, err := self.newResolver(self.rootAddress)
if err != nil {
return nil, [12]byte{}, "", err
}
labels := strings.Split(name, ".")
for i := len(labels) - 1; i >= 0; i-- {
if personal, _ := resolver.IsPersonalResolver(); personal {
return resolver, nodeId, strings.Join(labels[0:i+1], "."), nil
}
resolver, nodeId, err = self.nextResolver(resolver, nodeId, labels[i])
if err != nil {
return nil, [12]byte{}, "", err
}
}
if personal, _ := resolver.IsPersonalResolver(); !personal {
return nil, [12]byte{}, "", fmt.Errorf("Personal resolver not found in any name component")
label := crypto.Keccak256Hash([]byte(parts[0]))
if len(parts) == 1 {
return [32]byte{}, label
} else {
return resolver, nodeId, "", nil
parentNode, parentLabel := ensParentNode(parts[1])
return crypto.Keccak256Hash(parentNode[:], parentLabel[:]), label
}
}
/**
* Sets the content hash associated with a name.
*/
func (self *ENS) SetContentHash(name string, hash common.Hash) (*types.Transaction, error) {
resolver, nodeId, name, err := self.findPersonalResolver(name)
func ensNode(name string) common.Hash {
parentNode, parentLabel := ensParentNode(name)
return crypto.Keccak256Hash(parentNode[:], parentLabel[:])
}
func (self *ENS) getResolver(node [32]byte) (*contract.PublicResolverSession, error) {
resolverAddr, err := self.Resolver(node)
if err != nil {
return nil, err
}
return resolver.SetRR(nodeId, name, rtypeChash, 3600, 20, [32]byte(hash))
resolver, err := contract.NewPublicResolver(resolverAddr, self.contractBackend)
if err != nil {
return nil, err
}
return &contract.PublicResolverSession{
Contract: resolver,
TransactOpts: self.TransactOpts,
}, nil
}
func (self *ENS) getRegistrar(node [32]byte) (*contract.FIFSRegistrarSession, error) {
registrarAddr, err := self.Owner(node)
if err != nil {
return nil, err
}
registrar, err := contract.NewFIFSRegistrar(registrarAddr, self.contractBackend)
if err != nil {
return nil, err
}
return &contract.FIFSRegistrarSession{
Contract: registrar,
TransactOpts: self.TransactOpts,
}, nil
}
// Resolve is a non-transactional call that returns the content hash associated with a name.
func (self *ENS) Resolve(name string) (storage.Key, error) {
node := ensNode(name)
resolver, err := self.getResolver(node)
if err != nil {
return nil, err
}
ret, err := resolver.Content(node)
if err != nil {
return nil, err
}
return storage.Key(ret[:]), nil
}
// Register registers a new domain name for the caller, making them the owner of the new name.
// Only works if the registrar for the parent domain implements the FIFS registrar protocol.
func (self *ENS) Register(name string) (*types.Transaction, error) {
parentNode, label := ensParentNode(name)
registrar, err := self.getRegistrar(parentNode)
if err != nil {
return nil, err
}
opts := self.TransactOpts
opts.GasLimit = big.NewInt(200000)
return registrar.Contract.Register(&opts, label, self.TransactOpts.From)
}
// SetContentHash sets the content hash associated with a name. Only works if the caller
// owns the name, and the associated resolver implements a `setContent` function.
func (self *ENS) SetContentHash(name string, hash common.Hash) (*types.Transaction, error) {
node := ensNode(name)
resolver, err := self.getResolver(node)
if err != nil {
return nil, err
}
opts := self.TransactOpts
opts.GasLimit = big.NewInt(200000)
return resolver.Contract.SetContent(&opts, node, hash)
}

View file

@ -1,5 +1,3 @@
//go:generate abigen --abi contract/OpenRegistrar.abi --bin contract/OpenRegistrar.bin --pkg contract --type OpenRegistrar --out contract/OpenRegistrar.go
//go:generate abigen --abi contract/PersonalResolver.abi --bin contract/PersonalResolver.bin --pkg contract --type PersonalResolver --out contract/PersonalResolver.go
package ens
import (
@ -8,7 +6,6 @@ import (
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/accounts/abi/bind/backends"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/crypto"
)
@ -23,21 +20,16 @@ var (
func TestENS(t *testing.T) {
contractBackend := backends.NewSimulatedBackend(core.GenesisAccount{addr, big.NewInt(1000000000)})
transactOpts := bind.NewKeyedTransactor(key)
ens := NewENS(transactOpts, common.Address{}, contractBackend)
registrarAddr, err := ens.DeployRegistrar()
// Workaround for bug estimating gas in the call to Register
transactOpts.GasLimit = big.NewInt(1000000)
ens, err := DeployENS(transactOpts, contractBackend)
if err != nil {
t.Fatalf("expected no error, got %v", err)
}
contractBackend.Commit()
ens = NewENS(transactOpts, registrarAddr, contractBackend)
resolverAddr, err := ens.DeployResolver()
if err != nil {
t.Fatalf("expected no error, got %v", err)
}
contractBackend.Commit()
_, err = ens.Register(name, resolverAddr)
_, err = ens.Register(name)
if err != nil {
t.Fatalf("expected no error, got %v", err)
}
@ -56,5 +48,4 @@ func TestENS(t *testing.T) {
if vhost.Hex() != hash.Hex()[2:] {
t.Fatalf("resolve error, expected %v, got %v", hash.Hex(), vhost)
}
}

View file

@ -138,8 +138,11 @@ func NewSwarm(ctx *node.ServiceContext, config *api.Config, swapEnabled, syncEna
// set up high level api
transactOpts := bind.NewKeyedTransactor(self.privateKey)
// backend := ethereum.ContractBackend()
self.dns = ens.NewENS(transactOpts, config.EnsRoot, self.backend)
self.dns, err = ens.NewENS(transactOpts, config.EnsRoot, self.backend)
if err != nil {
return nil, err
}
glog.V(logger.Debug).Infof("[BZZ] -> Swarm Domain Name Registrar @ address %v", config.EnsRoot.Hex())
self.api = api.NewApi(self.dpa, self.dns)