From ef3562ddab0cc2499abdd7510a1c09dbe8fd3391 Mon Sep 17 00:00:00 2001 From: axelpoise Date: Sun, 15 May 2016 20:55:04 +0200 Subject: [PATCH] added a basis for a registrar for parties --- src/contracts.js | 1 + src/contracts/OriginalRegistrar.sol | 175 ++++++++++++++++++++++++++++ src/contracts/PartyRegistrar.sol | 34 ++++++ test/contracts/setregistrar.js | 96 +++++++++++++++ 4 files changed, 306 insertions(+) create mode 100644 src/contracts/OriginalRegistrar.sol create mode 100644 src/contracts/PartyRegistrar.sol create mode 100644 test/contracts/setregistrar.js diff --git a/src/contracts.js b/src/contracts.js index e58c2b7..03938fc 100644 --- a/src/contracts.js +++ b/src/contracts.js @@ -5,6 +5,7 @@ var contracts = { delegate: require('./contracts/Delegate.sol'), passwordDelegate: require('./contracts/PasswordDelegate.sol'), //bank: require('./contracts/Bank.sol') + registrar: require('./contracts/PartyRegistrar.sol'), }; var all = "" diff --git a/src/contracts/OriginalRegistrar.sol b/src/contracts/OriginalRegistrar.sol new file mode 100644 index 0000000..6033147 --- /dev/null +++ b/src/contracts/OriginalRegistrar.sol @@ -0,0 +1,175 @@ +//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; +} \ No newline at end of file diff --git a/src/contracts/PartyRegistrar.sol b/src/contracts/PartyRegistrar.sol new file mode 100644 index 0000000..bdcba3c --- /dev/null +++ b/src/contracts/PartyRegistrar.sol @@ -0,0 +1,34 @@ +contract PartyRegistar{ + struct Party { + + address partyAddress; + } + + mapping(string => Party) private partyMapping; + + function PartyRegistrar(){ + // can invoke standard users + } + + function(){ + // no ether to the registrar + return; + } + + function isAvailable(string _name) constant returns(bool ){ + Party a = partyMapping[_name]; + if (a.partyAddress != 0x0){ + return true; + } + else { return false;} + } + + function setPartyName(string _name, address _address){ + partyMapping[_name].partyAddress = _address; + } + + function getAddress(string _name) constant returns(address){ + partyMapping[_name].partyAddress; + } + +} \ No newline at end of file diff --git a/test/contracts/setregistrar.js b/test/contracts/setregistrar.js new file mode 100644 index 0000000..32243aa --- /dev/null +++ b/test/contracts/setregistrar.js @@ -0,0 +1,96 @@ +/* +a global registrar address and abi should be hardcoded +in the library provided for a private blockchain to +override the global registrar settings +*/ + +var assert = require('assert'); + +var Web3 = require('web3'); +//var ethereumjsUtil = require('ethereumjs-util'); + +//var Watch = require('../../src/watch'); +//var Wallet = require('../../src/wallet'); + +var contracts = require('../../src/contracts'); + +describe('SetRegistrar', function () { + + this.timeout(100000); + + var DEFAULT_GAS = 5000000; + + //var web3 = new Web3(); + //var watch = new Watch(web3); + + var defaultProvider = new web3.providers.HttpProvider("http://128.199.53.68:8545") + + web3.setProvider(defaultProvider); + web3.eth.defaultAccount = web3.eth.coinbase; + + var appWallet; + + it('should create the registrar contract and update the web3', function (done) { + + var abi = compiled.Registrar.info.abiDefinition; + var code = compiled.Registrar.code; + + + web3.eth.contract(abi).new({ + from: web3.eth.coinbase, + gas: DEFAULT_GAS, + data: code + }, callback); + + + + function callback(err, contract) { + if (err) { + console.log("Contract creation error", err); + done(err); + } else if (contract.address) { + console.log("Contract Created", contract.address); + web3.namereg.global.address = contract.address; + web3.namereg.global.abi = abi; + done(); + } + }; + }); + it('should name a party contract', function(done){ + + var abi = compiled.Party.info.abiDefinition; + var code = compiled.Party.code; + + web3.eth.contract(abi).new({ + from: web3.eth.coinbase, + gas: DEFAULT_GAS, + data: code + }, callback); + + function callback(err, contract) { + if (err) { + console.log("Contract creation error", err); + done(err); + } else if (contract.address) { + console.log("Contract Created", contract.address); + if(web3.namereg.isAvailable){ + web3.namereg.setPartyName("testparty", contract.address ); + done(); + } + else{ + console.log('not available') + done(); + } + + } + } + }) + it('should return the address given the name', function(done){ + web3.namereg.getAddress("testparty", function(regAddress){ + console.log(regAddress); + done(); + }) + }) + +}); +