Kompilieren und Bereitstellen von Registrar.sol in einem privaten Netzwerk

Ich habe einen Vertrag mit der Go-Ethereum-Konsole erstellt und möchte den Registrar in einem privaten Netzwerk bereitstellen. Ich habe einen Weg zum Kompilieren und Bereitstellen in https://github.com/ethereum/dapp-bin/tree/master/registrar gefunden

Aber ich weiß nicht, wie ich den Vertrag kompilieren soll: Registrar.sol .

Antworten (1)

Sie müssen den Code von github.com/ethereum/dapp-bin/.../registrar kompilieren und bereitstellen .

Registrar.sol enthält nur eine Klasse mit den Schnittstellenfunktionen.

GlobalRegistrar.sol implementiert die Registrar.sol-Schnittstelle.

Daher finden Sie hier eine Schritt-für-Schritt-Anleitung zum Bereitstellen und Verwenden des GlobalRegistrarVertrags.

Es folgt der Quellcode für GlobalRegistrar.sol . Speichern Sie es in GlobalRegistrar.sol in Ihrem Arbeitsunterverzeichnis:

//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;
}

Unter Verwendung des stripCrLfSkripts in How to load Solidity source file into geth habe ich den Quellcode mit dem folgenden Befehl vereinfacht:

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;}'

Ich betreibe ein Entwicklungsnetzwerk mit dem folgenden Befehl (ich habe mein Passwort in passwordfile):

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

Ich füge den abgeflachten Code in die gethBefehlszeile ein:

> 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

Und kompilieren Sie den Code mit dem folgenden Befehl:

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

path: /usr/bin/solc
undefined

Sie können die Binärschnittstelle der Anwendung mit den folgenden Befehlen anzeigen. Ich werde nur die GlobalRegistrar-Ausgabe anzeigen, da dieser Vertrag alle erforderlichen Funktionen implementiert:

> 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"
}]

Stellen Sie den Vertrag auf der Blockchain bereit:

> 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]

Lassen Sie uns nun einen Eigentümer in unserem Konto bei eth.accounts[0] registrieren:

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

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

Aber ich bekomme derzeit einen Fehler beim Abfragen der Daten:

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

Und der Grund, warum ich BokkyPooBah nicht registrieren kann, ist, dass es weniger als 12 Zeichen lang ist und eine Auktion erfordern würde. Erhöhen wir also den Namen auf einen mit mehr als 12 Zeichen:

> 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"

Siehe auch https://ethereum.gitbooks.io/frontier-guide/content/registrar_services.html für weitere Informationen.