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.

Sebi
  • 5,294
  • 6
  • 27
  • 52
Ajk Thu
  • 173
  • 10

1 Answers1

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.

BokkyPooBah
  • 40,274
  • 14
  • 123
  • 193