2

I have a smart contract that holds the details of a person. Each new person gets a new smart contract that they 'own'.

I have a regulator/ admin who wants to see the number of such smart contracts existing on the system and see the person who owns it. He will not be able to view any of the private data stored on them (data will be encrypted). Only the owner name (public variable) will be in unencrypted form. Is it possible to write a function that does this? I have considered making a registry that stores the address vs the owner name on a database but am looking for a solution just using smart contracts.

contract People{
    bool public isActive = false;
    uint public objectId;
    string public ownerName;
    string somePrivateData;
    mapping (address => bool) owned;

    function initPeopleContract(string name){
        if (!isActive) {
            isActive = true;
            ownerName = name;
        }
    }

    function getOwnerName() returns (string val) {
        if (!isActive) {
          val = ownerName;
        }else {
          val = "Account Deactivated";
        }
    }

    function getPrivateData() returns (string data) {
        if (msg.sender == address){
          // Send the data back
        } else {
          // Reject due to un-authorized request
        }
    }
}

The last function is incomplete, I will add parts that check whether the person who request the transaction is really the owner of the smart contract or not. The ownerName is a public variable that the admin should be able to query and view.

I am using web3.js , browser solidity to compile abi code and a private block chain run using geth console commands.

2 Answers 2

4

This is a hub & spoke pattern adapted to roughly map to your code. The Hub deploys Person contracts and keeps track of them. You can iterate over the unordered list from web3 and delete an item from the list if needed. You can add or remove person and hub privileges at the person level. For example, if you want, you can have a selfDestruct function in the Person contract and make it onlyOwner (only Hub can destroy it) or onlyPerson for self-delete. Presented without warranty. Very little testing. ;-)

pragma solidity ^0.4.6;

contract Hub {

  // two-way interable index with delete
  mapping(address => uint) personMap;
  address[] public personIndex;

  address public owner;

  function Hub() {
    owner = msg.sender;
  }

  modifier onlyOwner() {
    if(msg.sender != owner) throw;
    _;
  }

  function createPerson() 
    public
    returns(address newPerson)
  {
    Person p = new Person(msg.sender);              // whoever called this will "own" the Person contract created
    personMap[p] = personIndex.length;              // remember where it lives in the unordered list
    personIndex.push(p);                            // append to the end of the list
    return p;
  }

  function deletePerson(address person) 
    onlyOwner
    returns(bool success)
  {
    // step by step for clarity
    uint location = personMap[person];              // location on the list
    address personAddress = personIndex[location];  // should match the person
    // as one line
    if(personIndex[personMap[person]] != person) throw; // non-existent person
    // move the last item in the index to the location where the unperson was
    personIndex[personMap[person]] = personIndex[personIndex.length-1];
    // also have to update the personMap because the last item changed position in the list
    // whoever was in the last row is now in the row where we are removing a record
    personMap[personIndex[personIndex.length-1]] = personMap[person]; 
    // now the list is shorter
    personIndex.length--;
    // person is removed from the list
    return true;
  }

  // the next two functions make the unordered list of contracts iterable

  function getPersonCount() 
    public
    constant
    returns(uint count)
  {
    return personIndex.length;
  }

  function getPersonAtIndex(uint index)
    public
    constant
    returns(address person)
  {
    return personIndex[index];
  }
}

contract Person {

  // address public owner;
  address public personOwner;

  struct PersonStruct {
    bytes32 encrypted1;
    bytes32 encrypted2;
  }

  PersonStruct p;

  modifier onlyPerson {                       // add this to functions only the "person" passed in should be able to do
    if(msg.sender != personOwner) throw;
    _;
  }

  function Person(address person) {
    personOwner = person;                   // passed in by the creating Hub
    // owner = msg.sender                   // this would enable the Hub to have certain privileges if needed
  }

  function getPerson()
    onlyPerson
    constant
    returns(bytes32, bytes32)
  {
    return(p.encrypted1, p.encrypted2);
  }

  function setPerson(bytes32 part1, bytes32 part2)
    onlyPerson
    returns(bool success)
  {
    p.encrypted1 = part1;
    p.encrypted2 = part2;
    return true;
  }
}
5
  • Thanks for the clarity. I will work on this and post an updated contract soon with more functionalities. Would love to hear your thoughts on it. Commented Dec 23, 2016 at 5:58
  • 1
    Glad it clarified something. Happy to help. Commented Dec 23, 2016 at 12:13
  • Not sure if this is appropriate by stack rules but if you could please help me out with this : ethereum.stackexchange.com/questions/10981/… Commented Dec 28, 2016 at 11:30
  • @RobHitchens - Is there a list (comprehensive or not) of the various patterns for smart contracts? Commented Jan 24, 2018 at 11:38
  • Not that I know of but I can see how such a thing would be very handy. Commented Jan 24, 2018 at 15:29
2

The standard ethereum clients (geth and parity) maintain only a limited set of indexes for querying the blockchain. For example, you can look up a transaction by its hash (using web3 getTransaction(hash) or RPC eth_getTransactionByHash) but you cannot look up transactions by sender. Services like http://etherscan.io that offer more complete navigation use custom clients that build additional indexes.

So you will have to build an index yourself. But you have a choice of whether to store the index on the blockchain or off. To store it on the chain, you could have the People constructor register itself in a singleton contract that exists to provide storage for the index. The registry contract could have a member field like address[] people to store the list of People addresses.

But note that Solidity isn't all that convenient for real data structures like mutable lists: you can't remove an item from the middle of an array and there is no way to enumerate the keys of a mapping.

If you are willing to store the index off-chain, you still need a way to get the list of People contracts from the chain. If every People instance is created by the same address (or a small, known set of creator addresses), that would help you find all the People contracts after the fact by replaying the entire history of transactions. Or, you could add an event log statement to the People constructor, and then your off-chain code could watch for log events of this type. But neither of these techniques gives you an index that can be used by on-chain contract code.

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.