Solidity – Query Multiple Smart Contracts’ Public Data

contract-designcontract-developmentcontract-invocationsolidityweb3js

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.

Best Answer

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;
  }
}
Related Topic