2

I created a contract using go-ethereum console, I want to deploy registrar in private network. I found out a way to compile and deploy in https://github.com/ethereum/dapp-bin/tree/master/registrar

But I don't know how to compile contract: Registrar.sol.

1 Answer 1

3

You will have to compile and deploy the code from github.com/ethereum/dapp-bin/.../registrar.

Registrar.sol only contains a class with the interface functions.

GlobalRegistrar.sol implements the Registrar.sol interface.

So here is a step-by-step guide to deploying and using the GlobalRegistrar contract.

Following is the source code for GlobalRegistrar.sol. Save it to GlobalRegistrar.sol in your working subdirectory:

//sol

contract NameRegister {
    function addr(string _name) constant returns (address o_owner);
    function name(address _owner) constant returns (string o_name);
}

contract Registrar is NameRegister {
    event Changed(string indexed name);
    event ReverseChanged(address indexed addr, string indexed name);

    function owner(string _name) constant returns (address o_owner);
    function addr(string _name) constant returns (address o_address);
    function subRegistrar(string _name) constant returns (address o_subRegistrar);
    function content(string _name) constant returns (bytes32 o_content);
    
    function name(address _owner) constant returns (string o_name);
}

contract AuctionSystem {
    event AuctionEnded(string indexed _name, address _winner);
    event NewBid(string indexed _name, address _bidder, uint _value);

    /// Function that is called once an auction ends.
    function onAuctionEnd(string _name) internal;

    function bid(string _name, address _bidder, uint _value) internal {
        var auction = m_auctions[_name];
        if (auction.endDate > 0 && now > auction.endDate)
        {
            AuctionEnded(_name, auction.highestBidder);
            onAuctionEnd(_name);
            delete m_auctions[_name];
            return;
        }
        if (msg.value > auction.highestBid)
        {
            // new bid on auction
            auction.secondHighestBid = auction.highestBid;
            auction.sumOfBids += _value;
            auction.highestBid = _value;
            auction.highestBidder = _bidder;
            auction.endDate = now + c_biddingTime;

            NewBid(_name, _bidder, _value);
        }
    }

    uint constant c_biddingTime = 7 days;

    struct Auction {
        address highestBidder;
        uint highestBid;
        uint secondHighestBid;
        uint sumOfBids;
        uint endDate;
    }
    mapping(string => Auction) m_auctions;
}

contract GlobalRegistrar is Registrar, AuctionSystem {
    struct Record {
        address owner;
        address primary;
        address subRegistrar;
        bytes32 content;
        uint renewalDate;
    }

    uint constant c_renewalInterval = 1 years;
    uint constant c_freeBytes = 12;

    function Registrar() {
        // TODO: Populate with hall-of-fame.
    }

    function() {
        // prevent people from just sending funds to the registrar
        throw;
    }

    function onAuctionEnd(string _name) internal {
        var auction = m_auctions[_name];
        var record = m_toRecord[_name];
        if (record.owner != 0)
            record.owner.send(auction.sumOfBids - auction.highestBid / 100);
        else
            auction.highestBidder.send(auction.highestBid - auction.secondHighestBid);
        record.renewalDate = now + c_renewalInterval;
        record.owner = auction.highestBidder;
        Changed(_name);
    }

    function reserve(string _name) external {
        if (bytes(_name).length == 0)
            throw;
        bool needAuction = requiresAuction(_name);
        if (needAuction)
        {
            if (now < m_toRecord[_name].renewalDate)
                throw;
            bid(_name, msg.sender, msg.value);
        }
        else
        {
            Record record = m_toRecord[_name];
            if (record.owner != 0)
                throw;
            m_toRecord[_name].owner = msg.sender;
            Changed(_name);
        }
    }

    function requiresAuction(string _name) internal returns (bool) {
        return bytes(_name).length < c_freeBytes;
    }

    modifier onlyrecordowner(string _name) { if (m_toRecord[_name].owner == msg.sender) _ }

    function setOwner(string _name, address _newOwner) onlyrecordowner(_name) {
        m_toRecord[_name].owner = _newOwner;
        Changed(_name);
    }

    function disown(string _name) onlyrecordowner(_name) {
        if (stringsEqual(m_toName[m_toRecord[_name].primary], _name))
        {
            ReverseChanged(m_toRecord[_name].primary, "");
            m_toName[m_toRecord[_name].primary] = "";
        }
        delete m_toRecord[_name];
        Changed(_name);
    }

    function setName(string _name) {
        if (m_toRecord[_name].primary == msg.sender)
        {
            ReverseChanged(msg.sender, _name);
            m_toName[msg.sender] = _name;
        }
    }
    function setAddress(string _name, address _a) onlyrecordowner(_name) {
        m_toRecord[_name].primary = _a;
        Changed(_name);
    }
    function setSubRegistrar(string _name, address _registrar) onlyrecordowner(_name) {
        m_toRecord[_name].subRegistrar = _registrar;
        Changed(_name);
    }
    function setContent(string _name, bytes32 _content) onlyrecordowner(_name) {
        m_toRecord[_name].content = _content;
        Changed(_name);
    }

    function stringsEqual(string storage _a, string memory _b) internal returns (bool) {
        bytes storage a = bytes(_a);
        bytes memory b = bytes(_b);
        if (a.length != b.length)
            return false;
        // @todo unroll this loop
        for (uint i = 0; i < a.length; i ++)
            if (a[i] != b[i])
                return false;
        return true;
    }

    function owner(string _name) constant returns (address) { return m_toRecord[_name].owner; }
    function addr(string _name) constant returns (address) { return m_toRecord[_name].primary; }
    function subRegistrar(string _name) constant returns (address) { return m_toRecord[_name].subRegistrar; }
    function content(string _name) constant returns (bytes32) { return m_toRecord[_name].content; }
    function name(address _addr) constant returns (string o_name) { return m_toName[_addr]; }

    mapping (address => string) m_toName;
    mapping (string => Record) m_toRecord;
}

Using the stripCrLf script in How to load Solidity source file into geth, I've flattened the source code using the following command:

user@Kumquat:~/Registrar$ echo "var globalRegistrarSource='`stripCrLf GlobalRegistrar.sol`'"
var globalRegistrarSource='contract NameRegister { function addr(string _name) constant returns (address o_owner); function name(address _owner) constant returns (string o_name);}contract Registrar is NameRegister { event Changed(string indexed name); event ReverseChanged(address indexed addr, string indexed name); function owner(string _name) constant returns (address o_owner); function addr(string _name) constant returns (address o_address); function subRegistrar(string _name) constant returns (address o_subRegistrar); function content(string _name) constant returns (bytes32 o_content);  function name(address _owner) constant returns (string o_name);}contract AuctionSystem { event AuctionEnded(string indexed _name, address _winner); event NewBid(string indexed _name, address _bidder, uint _value);  function onAuctionEnd(string _name) internal; function bid(string _name, address _bidder, uint _value) internal { var auction = m_auctions[_name]; if (auction.endDate > 0 && now > auction.endDate) { AuctionEnded(_name, auction.highestBidder); onAuctionEnd(_name); delete m_auctions[_name]; return; } if (msg.value > auction.highestBid) {  auction.secondHighestBid = auction.highestBid; auction.sumOfBids += _value; auction.highestBid = _value; auction.highestBidder = _bidder; auction.endDate = now + c_biddingTime; NewBid(_name, _bidder, _value); } } uint constant c_biddingTime = 7 days; struct Auction { address highestBidder; uint highestBid; uint secondHighestBid; uint sumOfBids; uint endDate; } mapping(string => Auction) m_auctions;}contract GlobalRegistrar is Registrar, AuctionSystem { struct Record { address owner; address primary; address subRegistrar; bytes32 content; uint renewalDate; } uint constant c_renewalInterval = 1 years; uint constant c_freeBytes = 12; function Registrar() {  } function() {  throw; } function onAuctionEnd(string _name) internal { var auction = m_auctions[_name]; var record = m_toRecord[_name]; if (record.owner != 0) record.owner.send(auction.sumOfBids - auction.highestBid / 100); else auction.highestBidder.send(auction.highestBid - auction.secondHighestBid); record.renewalDate = now + c_renewalInterval; record.owner = auction.highestBidder; Changed(_name); } function reserve(string _name) external { if (bytes(_name).length == 0) throw; bool needAuction = requiresAuction(_name); if (needAuction) { if (now < m_toRecord[_name].renewalDate) throw; bid(_name, msg.sender, msg.value); } else { Record record = m_toRecord[_name]; if (record.owner != 0) throw; m_toRecord[_name].owner = msg.sender; Changed(_name); } } function requiresAuction(string _name) internal returns (bool) { return bytes(_name).length < c_freeBytes; } modifier onlyrecordowner(string _name) { if (m_toRecord[_name].owner == msg.sender) _ } function setOwner(string _name, address _newOwner) onlyrecordowner(_name) { m_toRecord[_name].owner = _newOwner; Changed(_name); } function disown(string _name) onlyrecordowner(_name) { if (stringsEqual(m_toName[m_toRecord[_name].primary], _name)) { ReverseChanged(m_toRecord[_name].primary, ""); m_toName[m_toRecord[_name].primary] = ""; } delete m_toRecord[_name]; Changed(_name); } function setName(string _name) { if (m_toRecord[_name].primary == msg.sender) { ReverseChanged(msg.sender, _name); m_toName[msg.sender] = _name; } } function setAddress(string _name, address _a) onlyrecordowner(_name) { m_toRecord[_name].primary = _a; Changed(_name); } function setSubRegistrar(string _name, address _registrar) onlyrecordowner(_name) { m_toRecord[_name].subRegistrar = _registrar; Changed(_name); } function setContent(string _name, bytes32 _content) onlyrecordowner(_name) { m_toRecord[_name].content = _content; Changed(_name); } function stringsEqual(string storage _a, string memory _b) internal returns (bool) { bytes storage a = bytes(_a); bytes memory b = bytes(_b); if (a.length != b.length) return false;  for (uint i = 0; i < a.length; i ++) if (a[i] != b[i]) return false; return true; } function owner(string _name) constant returns (address) { return m_toRecord[_name].owner; } function addr(string _name) constant returns (address) { return m_toRecord[_name].primary; } function subRegistrar(string _name) constant returns (address) { return m_toRecord[_name].subRegistrar; } function content(string _name) constant returns (bytes32) { return m_toRecord[_name].content; } function name(address _addr) constant returns (string o_name) { return m_toName[_addr]; } mapping (address => string) m_toName; mapping (string => Record) m_toRecord;}'

I'm running a dev network using the following command (I have my password in passwordfile):

geth --datadir ~/devdata --dev --mine --minerthreads 1 --unlock 0 --password ~/passwordfile console

I paste the flattened code in the geth command line:

> var globalRegistrarSource='contract NameRegister { function addr(string _name) constant returns (address o_owner); function name(address _owner) constant returns (string o_name);}contract Registrar is NameRegister { event Changed(string indexed name); event ReverseChanged(address indexed addr, string indexed name); function owner(string _name) constant returns (address o_owner); function addr(string _name) constant returns (address o_address); function subRegistrar(string _name) constant returns (address o_subRegistrar); function content(string _name) constant returns (bytes32 o_content);  function name(address _owner) constant returns (string o_name);}contract AuctionSystem { event AuctionEnded(string indexed _name, address _winner); event NewBid(string indexed _name, address _bidder, uint _value);  function onAuctionEnd(string _name) internal; function bid(string _name, address _bidder, uint _value) internal { var auction = m_auctions[_name]; if (auction.endDate > 0 && now > auction.endDate) { AuctionEnded(_name, auction.highestBidder); onAuctionEnd(_name); delete m_auctions[_name]; return; } if (msg.value > auction.highestBid) {  auction.secondHighestBid = auction.highestBid; auction.sumOfBids += _value; auction.highestBid = _value; auction.highestBidder = _bidder; auction.endDate = now + c_biddingTime; NewBid(_name, _bidder, _value); } } uint constant c_biddingTime = 7 days; struct Auction { address highestBidder; uint highestBid; uint secondHighestBid; uint sumOfBids; uint endDate; } mapping(string => Auction) m_auctions;}contract GlobalRegistrar is Registrar, AuctionSystem { struct Record { address owner; address primary; address subRegistrar; bytes32 content; uint renewalDate; } uint constant c_renewalInterval = 1 years; uint constant c_freeBytes = 12; function Registrar() {  } function() {  throw; } function onAuctionEnd(string _name) internal { var auction = m_auctions[_name]; var record = m_toRecord[_name]; if (record.owner != 0) record.owner.send(auction.sumOfBids - auction.highestBid / 100); else auction.highestBidder.send(auction.highestBid - auction.secondHighestBid); record.renewalDate = now + c_renewalInterval; record.owner = auction.highestBidder; Changed(_name); } function reserve(string _name) external { if (bytes(_name).length == 0) throw; bool needAuction = requiresAuction(_name); if (needAuction) { if (now < m_toRecord[_name].renewalDate) throw; bid(_name, msg.sender, msg.value); } else { Record record = m_toRecord[_name]; if (record.owner != 0) throw; m_toRecord[_name].owner = msg.sender; Changed(_name); } } function requiresAuction(string _name) internal returns (bool) { return bytes(_name).length < c_freeBytes; } modifier onlyrecordowner(string _name) { if (m_toRecord[_name].owner == msg.sender) _ } function setOwner(string _name, address _newOwner) onlyrecordowner(_name) { m_toRecord[_name].owner = _newOwner; Changed(_name); } function disown(string _name) onlyrecordowner(_name) { if (stringsEqual(m_toName[m_toRecord[_name].primary], _name)) { ReverseChanged(m_toRecord[_name].primary, ""); m_toName[m_toRecord[_name].primary] = ""; } delete m_toRecord[_name]; Changed(_name); } function setName(string _name) { if (m_toRecord[_name].primary == msg.sender) { ReverseChanged(msg.sender, _name); m_toName[msg.sender] = _name; } } function setAddress(string _name, address _a) onlyrecordowner(_name) { m_toRecord[_name].primary = _a; Changed(_name); } function setSubRegistrar(string _name, address _registrar) onlyrecordowner(_name) { m_toRecord[_name].subRegistrar = _registrar; Changed(_name); } function setContent(string _name, bytes32 _content) onlyrecordowner(_name) { m_toRecord[_name].content = _content; Changed(_name); } function stringsEqual(string storage _a, string memory _b) internal returns (bool) { bytes storage a = bytes(_a); bytes memory b = bytes(_b); if (a.length != b.length) return false;  for (uint i = 0; i < a.length; i ++) if (a[i] != b[i]) return false; return true; } function owner(string _name) constant returns (address) { return m_toRecord[_name].owner; } function addr(string _name) constant returns (address) { return m_toRecord[_name].primary; } function subRegistrar(string _name) constant returns (address) { return m_toRecord[_name].subRegistrar; } function content(string _name) constant returns (bytes32) { return m_toRecord[_name].content; } function name(address _addr) constant returns (string o_name) { return m_toName[_addr]; } mapping (address => string) m_toName; mapping (string => Record) m_toRecord;}'
undefined

And compile the code using the following command:

> var globalRegistrarCompiled = web3.eth.compile.solidity(globalRegistrarSource);
Version: 0.3.5-0/RelWithDebInfo-Linux/g++/Interpreter

path: /usr/bin/solc
undefined

You can view the Application Binary Interface using the following commands. I will only display the GlobalRegistrar output as that contract implements all the necessary functions:

> globalRegistrarCompiled.NameRegister.info.abiDefinition
...
> globalRegistrarCompiled.Registrar.info.abiDefinition
...
> globalRegistrarCompiled.AuctionSystem.info.abiDefinition
...
> globalRegistrarCompiled.GlobalRegistrar.info.abiDefinition
[{
    constant: true,
    inputs: [{
        name: "_addr",
        type: "address"
    }],
    name: "name",
    outputs: [{
        name: "o_name",
        type: "string"
    }],
    type: "function"
}, {
    constant: false,
    inputs: [{
        name: "_name",
        type: "string"
    }],
    name: "disown",
    outputs: [],
    type: "function"
}, {
    constant: false,
    inputs: [{
        name: "_name",
        type: "string"
    }, {
        name: "_newOwner",
        type: "address"
    }],
    name: "setOwner",
    outputs: [],
    type: "function"
}, {
    constant: true,
    inputs: [{
        name: "_name",
        type: "string"
    }],
    name: "addr",
    outputs: [{
        name: "",
        type: "address"
    }],
    type: "function"
}, {
    constant: true,
    inputs: [{
        name: "_name",
        type: "string"
    }],
    name: "subRegistrar",
    outputs: [{
        name: "",
        type: "address"
    }],
    type: "function"
}, {
    constant: false,
    inputs: [{
        name: "_name",
        type: "string"
    }, {
        name: "_a",
        type: "address"
    }],
    name: "setAddress",
    outputs: [],
    type: "function"
}, {
    constant: false,
    inputs: [{
        name: "_name",
        type: "string"
    }],
    name: "reserve",
    outputs: [],
    type: "function"
}, {
    constant: false,
    inputs: [],
    name: "Registrar",
    outputs: [],
    type: "function"
}, {
    constant: false,
    inputs: [{
        name: "_name",
        type: "string"
    }],
    name: "setName",
    outputs: [],
    type: "function"
}, {
    constant: false,
    inputs: [{
        name: "_name",
        type: "string"
    }, {
        name: "_registrar",
        type: "address"
    }],
    name: "setSubRegistrar",
    outputs: [],
    type: "function"
}, {
    constant: true,
    inputs: [{
        name: "_name",
        type: "string"
    }],
    name: "content",
    outputs: [{
        name: "",
        type: "bytes32"
    }],
    type: "function"
}, {
    constant: true,
    inputs: [{
        name: "_name",
        type: "string"
    }],
    name: "owner",
    outputs: [{
        name: "",
        type: "address"
    }],
    type: "function"
}, {
    constant: false,
    inputs: [{
        name: "_name",
        type: "string"
    }, {
        name: "_content",
        type: "bytes32"
    }],
    name: "setContent",
    outputs: [],
    type: "function"
}, {
    anonymous: false,
    inputs: [{
        indexed: true,
        name: "_name",
        type: "string"
    }, {
        indexed: false,
        name: "_winner",
        type: "address"
    }],
    name: "AuctionEnded",
    type: "event"
}, {
    anonymous: false,
    inputs: [{
        indexed: true,
        name: "_name",
        type: "string"
    }, {
        indexed: false,
        name: "_bidder",
        type: "address"
    }, {
        indexed: false,
        name: "_value",
        type: "uint256"
    }],
    name: "NewBid",
    type: "event"
}, {
    anonymous: false,
    inputs: [{
        indexed: true,
        name: "name",
        type: "string"
    }],
    name: "Changed",
    type: "event"
}, {
    anonymous: false,
    inputs: [{
        indexed: true,
        name: "addr",
        type: "address"
    }, {
        indexed: true,
        name: "name",
        type: "string"
    }],
    name: "ReverseChanged",
    type: "event"
}]

Deploy the contract on the blockchain:

> var globalRegistrarContract = web3.eth.contract(globalRegistrarCompiled.GlobalRegistrar.info.abiDefinition);
undefined
> var globalRegistrar = globalRegistrarContract.new({
    from:web3.eth.accounts[0], 
    data: globalRegistrarCompiled.GlobalRegistrar.code, gas: 2000000}, 
    function(e, contract) {
      if (!e) {
        if (!contract.address) {
          console.log("Contract transaction send: TransactionHash: " + 
            contract.transactionHash + " waiting to be mined...");
        } else {
          console.log("Contract mined! Address: " + contract.address);
          console.log(contract);
        }
    }
})
...
Contract mined! Address: 0x6232a8cabd6171c8be20c2e5f32766c3805bdb39
[object Object]

Let's now register an owner to our account at eth.accounts[0]:

> globalRegistrar.reserve.sendTransaction("BokkyPooBah", {from: eth.accounts[0]})
"0xf38d70f2b7b505954b07ea50ff5ef6d11af318ee9be9df0a1cf882b738f2e945"

> globalRegistrar.setAddress.sendTransaction("BokkyPooBah", eth.accounts[0], {from: eth.accounts[0]})
"0x259c7902f83ed7c05e866f8f4cc52d85487730bfc1b7433e8bf8eacaa3e81f24"

But I'm getting an error currently when querying the data:

> globalRegistrar.addr("BokkyPooBah")
"0x0000000000000000000000000000000000000000"
> globalRegistrar.owner("BokkyPooBah")
"0x0000000000000000000000000000000000000000"

And the reason I cannot register BokkyPooBah is because it is less than 12 characters long, and would require an auction. So let's increase the name to one longer than 12 characters:

> globalRegistrar.reserve.sendTransaction("BokkyPooBahWuzHere", {from: eth.accounts[0]})
"0x0d194774f6e13ac0860a945aa96336a595cce61220fca67c1b7600b9538ff6e3"
> globalRegistrar.setAddress.sendTransaction("BokkyPooBahWuzHere", eth.accounts[0], {from: eth.accounts[0]})
"0xbc88acc79591b83c941e3d14e42a051d3c2ec8868a29ed195662b3e8072589db"
> globalRegistrar.owner("BokkyPooBahWuzHere")
"0xa7857047907d53a2e494d5f311b4b586dc6a96d2"
> globalRegistrar.addr("BokkyPooBahWuzHere")
"0xa7857047907d53a2e494d5f311b4b586dc6a96d2"

See also https://ethereum.gitbooks.io/frontier-guide/content/registrar_services.html for further information.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.