У меня есть смарт-контракт, который содержит данные о человеке. Каждый новый человек получает новый смарт-контракт, которым он «владеет».
У меня есть регулятор/администратор, который хочет видеть количество таких смарт-контрактов, существующих в системе, и видеть человека, которому они принадлежат. Он не сможет просмотреть какие-либо личные данные, хранящиеся на них (данные будут зашифрованы). Только имя владельца (публичная переменная) будет в незашифрованном виде. Можно ли написать функцию, которая это делает? Я рассматривал возможность создания реестра, в котором хранятся 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
консольных команд.
Это шаблон ступицы и спицы, адаптированный для примерного сопоставления с вашим кодом. 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;
}
}
Стандартные клиенты Эфириума (geth и parity) поддерживают только ограниченный набор индексов для запросов к блокчейну. Например, вы можете найти транзакцию по ее хешу (используя web3 getTransaction(hash)
или RPC eth_getTransactionByHash
), но вы не можете искать транзакции по отправителю. Такие службы, как http://etherscan.io , которые предлагают более полную навигацию, используют настраиваемые клиенты, которые создают дополнительные индексы.
Так что вам придется построить индекс самостоятельно. Но у вас есть выбор: хранить индекс в блокчейне или нет. Чтобы сохранить его в цепочке, вы можете People
зарегистрировать конструктор в одноэлементном контракте, который существует для хранения индекса. Контракт реестра может иметь поле участника, например address[] people
, для хранения списка адресов людей.
Но обратите внимание, что Solidity не так удобна для реальных структур данных, таких как изменяемые списки: вы не можете удалить элемент из середины массива и нет способа перечислить ключи сопоставления.
Если вы хотите хранить индекс вне цепочки, вам все равно нужен способ получить список контрактов People из цепочки. Если каждый экземпляр People создается по одному и тому же адресу (или небольшому известному набору адресов создателя), это поможет вам найти все контракты People постфактум путем воспроизведения всей истории транзакций. Или вы можете добавить оператор журнала событий в конструктор People, и тогда ваш код вне сети сможет отслеживать события журнала этого типа. Но ни один из этих методов не дает вам индекса, который можно использовать в коде контракта в цепочке.
Варун Агарвал
Роб Хитченс
Варун Агарвал
Эрик Кигати
Роб Хитченс