Comparación de valores de datos obtenidos con datos de entrada de diferentes contratos

Dados dos contratos de la siguiente manera, contract TestDatallama a contract Regpara obtener datos que ya se habían almacenado en su mapa usando get_attributesla función.

pragma solidity ^0.4.21;
contract Reg {
    mapping (address=>bytes32[5]) Map;

    //Filling the map
    function fill_map(bytes32[5] _attributes) public  {
            Map[msg.sender] = _attributes;
    }

    //Returns data in the map corresponding to an address
    function get_attributes(address _id) view public returns (bytes32[5]){
        return Map[_id];
    }
}


contract TestData {

    address Address;
    function get_address (address _Address) public{   
        Address = _Address;
    } 

    //Retreive data from Reg contract
    bytes32[5] fetched;
    function fetch(address _reg_Adress) public view returns (bytes32[5]) {
        Reg r = Reg(_reg_Adress);
        fetched = r.get_attributes(Address);
        return (fetched);
    }

    //Retreive input data from user
    bytes32[5] inputs;
    function getInputs(bytes32[5] _inputs) public view returns (bytes32[5]){
            inputs = _inputs;
            return (inputs);
    }    

    //Compare input data with fetched data
    bool[5] a = [false,false,false,false,false];
    function compare() public view returns(bool[5]){
        for(uint i=0;i<5;i++){
            for(uint j=0;j<5;j++){
                if(inputs[i] == fetched[j]){
                    a[i] = true;                 
                }
            }
        }

        return (a);
    }  

}

Así es como lo pruebo:

  1. Llena el mapa con["0x0","0x1","0x2","0x3","0x4"]

  2. Para la entrada del usuario también ingreso["0x0","0x1","0x2","0x3","0x4"]

La salida es correcta devolviendo [true,true,true,true,true].

Sin embargo, si cambio la entrada, digamos ["0xA","0x1","0x2","0x3","0x4"], la salida permanece [true,true,true,true,true]aunque debería ser [false,true,true,true,true].

¿Sucede algo con los datos cuando se obtienen del contrato Reg? Cuando intento probar el mismo código pero con dos matrices de entrada en lugar de obtener los datos, funciona bien.

Además, he estado buscando otras formas de hacer las comparaciones. ¿Hay alguna otra forma eficiente que no sea el bucle?

¿No quieres i<5y j<5? Te detienes después de comparar 3 elementos.
Si, eso es correcto. Lo arreglé en la pregunta. Sin embargo, todavía no funciona cuando cambio los valores de entrada.
Entonces, ¿puedes actualizar la pregunta con los resultados actuales? ¿Cuáles son los valores para los que funciona y cuáles son los valores para los que no funciona? ¿Cuál es la salida en ambos casos?
¿ Quizás estás llamando comparecomo una transacción? Si es así, se modificará permanentemente ay las llamadas posteriores heredarán los valores allí. (Una vez que un elemento se establece en true, nunca volverá). Probablemente debería mover la declaración de aadentro compare()de todos modos.
Ah, la respuesta de @Jaime señala otro problema. Su bucle anidado significa que está probando si cada elemento de inputcoincide con algún elemento de fetched. Si solo desea hacer coincidir los elementos correspondientes, debe soltar el bucle interno como se sugiere en esa respuesta.
Intenté insertar una comparación interna () pero tampoco funcionó. Sigue siendo [verdadero, verdadero, verdadero, verdadero, verdadero]

Respuestas (2)

La función comparees casi correcta, los errores están en otra parte.

function fetch(address _reg_Adress) public view returns (bytes32[5])

tienes que sacar viewde aqui

function getInputs(bytes32[5] _inputs) public view returns (bytes32[5])

también de aquí.

Luego mueva su matriz a la función y defínala como memoria.

//Compare input data with fetched data
function compare() public view returns(bool[5]){
    bool[5] memory a = [false,false,false,false,false];

    for(uint i=0;i<5;i++){
        for(uint j=0;j<5;j++){
            if(inputs[i] == fetched[j]){
                a[i] = true;                 
            }
        }
    }

    return (a);
}

si no, debe eliminar viewtambién del método comparepara que funcione

después de que esto cambie, el resultado sería false,true,true,true,trueel esperado.

¿Cómo resolvió el problema la eliminación de la vista?
si define la función como vista, no puede cambiar el estado del contrato (por ejemplo, sus variables), por lo que el valor de los miembros del contrato no es el esperado.

Hay varios problemas:

Primero, su forciclo se detiene temprano, en 3, cuando el límite debería ser i<5.

Además, su segundo forno es necesario. Su función puede ser:

function compare() public view returns(bool[5]){
    bool[5] memory a;
    for(uint i=0;i<5;i++){
        for(uint j=0;j<5;j++){
            if(inputs[i] == fetched[j]){
                a[i] = true;                 
            }
        }
    }

    return (a);
}  

También puede hacer lo siguiente para asegurarse de aque se actualice cuando los valores sean verdaderos o falsos:

function compare() public view returns(bool[5]){
    bool[5] memory a;
    for(uint i=0;i<5;i++){
        for(uint j=0;j<5;j++){
            a[i] = (inputs[i] == fetched[j]);                 
        }
    }

    return (a);
}  

finalmente, sus funciones modifican las variables de estado para que no se puedan ver.

Espero que esto ayude




ACTUALIZACIÓN: código completo.

pragma solidity ^0.4.21;
contract Reg {
    mapping (address=>bytes32[5]) public Map;

    //Filling the map
    function fill_map(bytes32[5] _attributes) public  {
            Map[msg.sender] = _attributes;
    }

    //Returns data in the map corresponding to an address
    function get_attributes(address _id) view public returns (bytes32[5]){
        return Map[_id];
    }
}


contract TestData {

    address Address;
    function get_address (address _Address) public{   
        Address = _Address;
    } 

    //Retreive data from Reg contract
    bytes32[5] public fetched;
    function fetch(address _reg_Adress) public returns (bytes32[5]) {
        Reg r = Reg(_reg_Adress);
        fetched = r.get_attributes(Address);
        return (fetched);
    }

    //Retreive input data from user
    bytes32[5] public inputs;
    function getInputs(bytes32[5] _inputs) public returns (bytes32[5]){
            inputs = _inputs;
            return (inputs);
    }    

    //Compare input data with fetched data

    function compare() public view returns(bool[5]){
        bool[5] memory a;
        for(uint i=0;i<5;i++){
            for(uint j=0;j<5;j++){
                if(inputs[i] == fetched[j]){
                    a[i] = true;                 
                }
            }
        }

        return (a);
    }  

}
Tienes razón en detenerte temprano. Yo arreglé eso. Sin embargo, su declaración if compara cada elemento en la primera matriz con el elemento correspondiente en la otra matriz. Estoy tratando de encontrar si cada elemento en la primera matriz está en la segunda matriz o no. Por lo tanto, creo que necesito el segundo bucle.
Entonces sí, el segundo bucle es necesario. Edité la respuesta. Déjame saber si esto resuelve tu problema
No es asi. La matriz a continúa devolviendo [verdadero, verdadero, verdadero, verdadero, verdadero]
Acabo de modificar el código, esto me funciona en remix. El tema es que cuando lo intentas la primera vez aes todo cierto. Luego probó con algo que da false, pero su código solo se actualiza acuando es verdadero, por lo que el valor verdadero no cambia. Poniéndolo dentro, inicializa a a falso cuando se ejecuta la función. Hágamelo saber
Pruébelo con un caso de prueba falso al principio. Por ejemplo, ["0x0","0x1","0x2","0x3","0x4"] y ["0xA","0x1","0x2","0x3","0x4"] deberían dar [falso ,verdadero,verdadero,verdadero,verdadero], sin embargo todavía da [verdadero,verdadero,verdadero,verdadero,verdadero].
no, me funciona bien.
Actualicé la respuesta y agregué el código completo, por si acaso. Lo probé varias veces y funciona.