Сравнение значений полученных данных с входными данными разных контрактов

Имея два контракта следующим образом, контракт TestDataвызывает контракт Regдля извлечения данных, которые уже были сохранены в его карте, с помощью get_attributesфункции.

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

}

Вот как я это тестирую:

  1. Заполните карту["0x0","0x1","0x2","0x3","0x4"]

  2. Для пользовательского ввода я также ввожу["0x0","0x1","0x2","0x3","0x4"]

Выход правильный return [true,true,true,true,true].

Однако, если я изменю ввод, скажем, ["0xA","0x1","0x2","0x3","0x4"], вывод останется, [true,true,true,true,true]хотя он должен быть [false,true,true,true,true].

Что-то происходит с данными, когда они извлекаются из контракта Reg? Когда я пытаюсь протестировать тот же код, но с двумя входными массивами, а не с выборкой данных, он работает нормально.

Кроме того, я искал другие способы сделать сравнения. Есть ли другой эффективный способ, кроме цикла?

Не хочешь i<5и j<5? Вы останавливаетесь после сравнения 3 элементов.
Да это верно. Я исправил это в вопросе. Однако он все еще не работает, когда я меняю входные значения.
Тогда вы можете обновить вопрос с текущими результатами? Для каких значений он работает, а для каких не работает? Каков результат в обоих случаях?
Возможно, вы звоните compareкак транзакция? Если это так, он будет постоянно изменять a, и последующие вызовы будут наследовать значения там. (Как только для элемента установлено значение true, он никогда не вернется назад.) Вероятно, вам все равно следует просто переместить объявление aвнутрь compare().
А, ответ @Jaime указывает на другую проблему. Ваш вложенный цикл означает, что вы проверяете, inputсоответствует ли каждый элемент любому элементу fetched. Если вы хотите сопоставить только соответствующие элементы, вам нужно отказаться от внутреннего цикла, как это предлагается в этом ответе.
Я попытался вставить внутреннее сравнение (), но это тоже не сработало. Он продолжает оставаться [правда, правда, правда, правда, правда]

Ответы (2)

Функция compareпочти правильная, ошибки в другом месте

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

надо удалить viewотсюда

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

тоже отсюда.

Затем переместите свой массив в функцию и определите его как память.

//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);
}

если нет, вы должны удалить viewтакже из метода compare, чтобы он работал

после этого изменения результат будет false,true,true,true,trueтаким, как ожидалось.

Как удаление представления решило проблему?
если вы определяете функцию как представление, вы не можете изменить состояние контракта (например, его переменные), поэтому значение членов контракта не соответствует ожидаемому.

Есть несколько проблем:

Сначала ваш forцикл останавливается рано, в 3, когда предел должен быть i<5.

И твой второй forне нужен. Ваша функция может быть:

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

Вы также можете сделать следующее, чтобы убедиться, aчто оно обновляется, когда значения истинны или ложны:

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

наконец, ваши функции изменяют переменные состояния, поэтому их нельзя просмотреть.

Надеюсь это поможет




ОБНОВЛЕНИЕ: Полный код.

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

}
Вы правы насчет ранней остановки. Я исправил это. Однако ваш оператор if сравнивает каждый элемент в первом массиве с соответствующим элементом в другом массиве. Я пытаюсь найти, находится ли каждый элемент в первом массиве во втором массиве или нет. Поэтому я считаю, что мне нужен второй цикл.
Тогда да, второй цикл необходим. Я отредактировал ответ. Дайте мне знать, если это решит вашу проблему
Это не. Массив a продолжает возвращать [true,true,true,true,true]
Я только что изменил код, у меня это работает в ремиксе. Проблема в том, что при первой попытке aвсе верно. Затем вы попробовали что-то, что дает false, но ваш код обновляется только aтогда, когда истинно, поэтому истинное значение не изменяется. Поместив его внутрь, инициализируйте значение false при выполнении функции. Дайте мне знать
Попробуйте сначала с ложным тестовым случаем. Например, ["0x0","0x1","0x2","0x3","0x4"] и ["0xA","0x1","0x2","0x3","0x4"] должны дать [false ,true,true,true,true], однако он по-прежнему дает [true,true,true,true,true].
нет, у меня работает нормально.
Я обновил ответ и на всякий случай добавил полный код. Я пробовал это несколько раз, и это работает