Consulta de datos públicos de múltiples contratos inteligentes

Tengo un contrato inteligente que contiene los detalles de una persona. Cada nueva persona obtiene un nuevo contrato inteligente que 'posee'.

Tengo un regulador/administrador que quiere ver la cantidad de contratos inteligentes de este tipo que existen en el sistema y ver a la persona que lo posee. No podrá ver ninguno de los datos privados almacenados en ellos (los datos estarán encriptados). Solo el nombre del propietario (variable pública) estará en formato no cifrado. ¿Es posible escribir una función que haga esto? He considerado hacer un registro que almacene el addressvs el owner nameen una base de datos, pero estoy buscando una solución que solo use contratos inteligentes.

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

La última función está incompleta, agregaré partes que verifiquen si la persona que solicita la transacción es realmente el propietario del contrato inteligente o no. Es ownerNameuna variable pública que el administrador debería poder consultar y ver.

Estoy usando web3.js, la solidez del navegador para compilar abiel código y una cadena de bloques privada que se ejecuta con los gethcomandos de la consola.

Respuestas (2)

Este es un patrón de centro y radios adaptado para mapear aproximadamente a su código. El concentrador implementa contratos de persona y realiza un seguimiento de ellos. Puede iterar sobre la lista desordenada de web3 y eliminar un elemento de la lista si es necesario. Puede agregar o eliminar privilegios de persona y concentrador a nivel de persona. Por ejemplo, si lo desea, puede tener una función de autodestrucción en el contrato de persona y convertirlo en solo propietario (solo Hub puede destruirlo) o solo persona para autoeliminación. Presentado sin garantía. Muy pocas pruebas. ;-)

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;
  }
}
Gracias por la claridad. Trabajaré en esto y publicaré un contrato actualizado pronto con más funcionalidades. Me encantaría escuchar tus pensamientos al respecto.
Me alegro de que haya aclarado algo. Feliz de ayudar.
No estoy seguro de si esto es apropiado según las reglas de la pila, pero si pudiera ayudarme con esto: ethereum.stackexchange.com/questions/10981/…
@RobHitchens: ¿hay una lista (completa o no) de los diversos patrones para contratos inteligentes?
No que yo sepa, pero puedo ver cómo tal cosa sería muy útil.

Los clientes estándar de ethereum (geth y parity) mantienen solo un conjunto limitado de índices para consultar la cadena de bloques. Por ejemplo, puede buscar una transacción por su hash (usando web3 getTransaction(hash)o RPC eth_getTransactionByHash), pero no puede buscar transacciones por remitente. Los servicios como http://etherscan.io que ofrecen una navegación más completa utilizan clientes personalizados que crean índices adicionales.

Así que tendrás que construir un índice tú mismo. Pero tiene la opción de almacenar el índice en la cadena de bloques o no. Para almacenarlo en la cadena, puede hacer que el Peopleconstructor se registre en un contrato único que existe para proporcionar almacenamiento para el índice. El contrato de registro podría tener un campo de miembro como address[] peoplepara almacenar la lista de direcciones de Personas.

Pero tenga en cuenta que Solidity no es tan conveniente para estructuras de datos reales como listas mutables: no puede eliminar un elemento del medio de una matriz y no hay forma de enumerar las claves de una asignación.

Si está dispuesto a almacenar el índice fuera de la cadena, aún necesita una forma de obtener la lista de contratos de personas de la cadena. Si cada instancia de Personas es creada por la misma dirección (o un conjunto pequeño y conocido de direcciones de creador), eso lo ayudaría a encontrar todos los contratos de Personas después del hecho al reproducir todo el historial de transacciones. O bien, podría agregar una declaración de registro de eventos al constructor People, y luego su código fuera de la cadena podría observar eventos de registro de este tipo. Pero ninguna de estas técnicas le brinda un índice que pueda ser utilizado por el código de contrato en cadena.