Запрос общедоступных данных нескольких смарт-контрактов

У меня есть смарт-контракт, который содержит данные о человеке. Каждый новый человек получает новый смарт-контракт, которым он «владеет».

У меня есть регулятор/администратор, который хочет видеть количество таких смарт-контрактов, существующих в системе, и видеть человека, которому они принадлежат. Он не сможет просмотреть какие-либо личные данные, хранящиеся на них (данные будут зашифрованы). Только имя владельца (публичная переменная) будет в незашифрованном виде. Можно ли написать функцию, которая это делает? Я рассматривал возможность создания реестра, в котором хранятся addressсравнения с данными в owner nameбазе данных, но я ищу решение, просто используя смарт-контракты.

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

Последняя функция неполная, я добавлю части, которые проверяют, действительно ли человек, запрашивающий транзакцию, является владельцем смарт-контракта или нет. Это ownerNameобщедоступная переменная, которую администратор должен иметь возможность запрашивать и просматривать.

Я использую web3.js, надежность браузера для компиляции abiкода и частную цепочку блоков, запускаемую с помощью gethконсольных команд.

Ответы (2)

Это шаблон ступицы и спицы, адаптированный для примерного сопоставления с вашим кодом. Hub развертывает контракты Person и отслеживает их. Вы можете перебирать неупорядоченный список из web3 и при необходимости удалять элемент из списка. Вы можете добавлять или удалять привилегии пользователя и хаба на уровне пользователя. Например, если вы хотите, вы можете иметь функцию selfDestruct в контракте Person и сделать его onlyOwner (его может уничтожить только Hub) или onlyPerson для самоудаления. Представлен без гарантии. Очень мало испытаний. ;-)

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;
  }
}
Спасибо за ясность. Я буду работать над этим и скоро опубликую обновленный контракт с большим количеством функций. Хотелось бы услышать ваши мысли по этому поводу.
Рад, что что-то прояснил. Рад помочь.
Не уверен, что это соответствует правилам стека, но не могли бы вы помочь мне с этим: ethereum.stackexchange.com/questions/10981/…
@RobHitchens - Есть ли список (полный или нет) различных шаблонов для смарт-контрактов?
Не то, чтобы я знал об этом, но я вижу, как такая вещь была бы очень удобной.

Стандартные клиенты Эфириума (geth и parity) поддерживают только ограниченный набор индексов для запросов к блокчейну. Например, вы можете найти транзакцию по ее хешу (используя web3 getTransaction(hash)или RPC eth_getTransactionByHash), но вы не можете искать транзакции по отправителю. Такие службы, как http://etherscan.io , которые предлагают более полную навигацию, используют настраиваемые клиенты, которые создают дополнительные индексы.

Так что вам придется построить индекс самостоятельно. Но у вас есть выбор: хранить индекс в блокчейне или нет. Чтобы сохранить его в цепочке, вы можете Peopleзарегистрировать конструктор в одноэлементном контракте, который существует для хранения индекса. Контракт реестра может иметь поле участника, например address[] people, для хранения списка адресов людей.

Но обратите внимание, что Solidity не так удобна для реальных структур данных, таких как изменяемые списки: вы не можете удалить элемент из середины массива и нет способа перечислить ключи сопоставления.

Если вы хотите хранить индекс вне цепочки, вам все равно нужен способ получить список контрактов People из цепочки. Если каждый экземпляр People создается по одному и тому же адресу (или небольшому известному набору адресов создателя), это поможет вам найти все контракты People постфактум путем воспроизведения всей истории транзакций. Или вы можете добавить оператор журнала событий в конструктор People, и тогда ваш код вне сети сможет отслеживать события журнала этого типа. Но ни один из этих методов не дает вам индекса, который можно использовать в коде контракта в цепочке.