Как дедуплицировать массивы в Solidity
Как дедуплицировать массивы в Solidity

1. Введение

Solidity — это язык программирования смарт-контрактов для платформы Ethereum с синтаксической структурой, аналогичной JavaScript и C++. Он специально разработан для написания самоисполняющихся контрактов на блокчейне, поддержки разработки сложной бизнес-логики и децентрализованных приложений (dApps). С быстрым развитием технологии блокчейна Solidity стал предпочтительным языком для построения децентрализованных финансов (DeFi), рынков NFT и других приложений блокчейна (на самом деле, это в основном связано с большим количеством пользователей Ethereum).

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

Итак, как эффективно дедуплицировать массивы в Solidity? Эту тему стоит изучить глубже. В этой статье будут представлены несколько распространенных методов дедупликации и проанализированы их преимущества и недостатки, чтобы помочь вам выбрать наиболее подходящую стратегию в реальной разработке.

2. Основы работы с массивами в Solidity

существовать Solidity В России массивы являются одной из наиболее часто используемых структур данных, позволяющих разработчикам хранить и манипулировать рядом элементов одного типа. В зависимости от того, фиксирована ли длина массива, Solidity вмножествоможно разделить настатический массивидинамический массив

2.1 Базовое использование массивов в Solidity

существовать Solidity , метод определения и использования массивов очень интуитивно понятен. Типы массивов состоят из типа элемента и квадратных скобок, например. uint256[] Экспресс одининдивидуальныйдинамический массив,uint256[5] представляет собой содержащий 5 индивидуальный uint256 Статический массив элементов.

Вот несколько основных примеров манипуляций с массивами:

Язык кода:javascript
копировать
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract ArrayExample {
    // динамический массив
    uint256[] public dynamicArray;

    // статический массив
    uint256[5] public staticArray;

    // Добавьте элементы в мотивацию массив
    function addElement(uint256 element) public {
        dynamicArray.push(element);
    }

    // Исправлятьстатический массиввэлемент    function setElement(uint256 index, uint256 element) public {
        require(index < staticArray.length, "Index out of bounds");
        staticArray[index] = element;
    }

    // получатьдинамический массивиз длины
    function getDynamicArrayLength() public view returns (uint256) {
        return dynamicArray.length;
    }
}

2.2 Разница между динамическими и статическими массивами

статический массив:статический массивиз длинысуществовать Определяется во время компиляции,исуществовать Не может быть изменено в течение жизненного цикла контракта.。использоватьстатический Использование массивов в качестве преимуществ заключается в том, что затраты на их эксплуатацию из хранилищ относительно невелики, поскольку они не требуют динамического изменение размера。статический Массив часто используется в контрактах, которым необходимо обрабатывать фиксированное количество транзакций, например фиксированное количество участников или предопределенное постоянное значение.

Язык кода:javascript
копировать
// Определение 1 «Индивидуальное лицо» содержит 3 индивидуальныйэлементизстатический массив
uint256[3] public staticArray = [1, 2, 3];

динамический массив:динамический массивиз длинасуществовать контракта является переменной в течение его жизненного цикла,Разработчики могутиспользовать push Метод добавляет элементы в массив. Хотя динамические массивы обеспечивают гибкость, они также обладают более высокими gas расходы, особенно когда существование добавляет и удаляет элементы. динамичный Массив подходит для сценариев, в которых необходимо обрабатывать переменное количество данных, таких как списки адресов пользователей или записи транзакций.

Язык кода:javascript
копировать
// Определение 1индивидуальныйдинамический массив
uint256[] public dynamicArray;

// Кдинамический Добавляем элементы в массив
dynamicArray.push(4);

2.3 Стоимость газа при операциях с массивами и ее важность в смарт-контрактах

существовать смарт-контракт,Каждая множество операций будет потреблять определенное количество газа., поскольку операция включает в себя чтение и запись в виртуальную машину Ethereum (EVM). Газ, особенно в сети Ethereum Стоимость напрямую влияет на комиссию за транзакцию, поэтому эффективность операций с массивом особенно важна.

  • Операция чтения:существоватьмножество Читать вданныеиз gas Расходы относительно невелики и обычно требуют только доступа к устройству хранения.
  • операция записи:операция записииз gas расходы выше, поскольку они включают в себя запись данных в Ethereum из хранилища персистентности.
  • Динамическое изменение размера:длядинамический массив, каждый раз push Эта операция не только требует написания новых элементов, но также может включать в себя множество операций изменения размера, которые добавят дополнительные элементы. gas расходы。

Оптимизированные операции с массивами Solidity Разработайте индивидуальные ключевые моменты. Чтобы уменьшить ненужное gas Потребление: разработчики обычно тщательно учитывают множество методов использования и работы в логике контракта. Например, старайтесь избегать многократного выполнения цикла существования операции. записи или существование. Используйте медленную, когда в этом нет необходимости. массив。

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

3. Проблемы дедупликации в Solidity

существуют смарт-контракты в разработке, Solidity Ограничения часто влияют на то, как разработчики реализуют определенные функции. Одним из существенных ограничений является то, что Solidity Не поддерживается напрямую, как JavaScript в Set Такая из динамической структуры данных. Это делает существование Solidity Обработка операций сбора данных (например, дедупликации) становится более сложной и дорогостоящей.

потому что Solidity Из-за ограничений среды блокчейна разработчики должны обеспечить дедупликацию, в то же время максимально сокращая вычислительные операции хранилища, чтобы сэкономить gas иуменьшатьхранилищерасходы。Это требует тщательного проектированиядоговорлогика,Выберите наиболее подходящие изданные структуру и алгоритм для оптимизации производительности ирасходов. существующие смарт-контракты находятся в разработке,Этот компромисс и оптимизация неизбежны,Это также ключевой момент, который разработчикам необходимо постоянно учиться и совершенствоваться.

3.1 Ограничения твердости

  1. Не хватает структур данных высокого уровня.:Solidity В настоящее время поддерживаются только базовые изданные структуры, такие как множество картографий. Хотя этих структур данных достаточно для удовлетворения многих простых потребностей, их недостаточно при выполнении более сложных изданных операций, таких как автоматическая дедупликация или сортировка. и JavaScript Разные, Солидность Нет родного из Set type, что означает, что нет прямого способа хранения уникальных значений.
  2. Затраты на эксплуатацию хранилища высоки:Solidity Любая операция записи, особенно если речь идет о постоянной памяти (хранилище), потребляет много ресурсов. газ. Чем больше хранилищеизданных, тем сложнее эксплуатация и потребление gas тем выше. Таким образом, построение сложной структуры или выполнение нескольких операций записи значительно ускорят развертывание и выполнение контракта.
  3. Нет родного из Установить операции:Solidity Отсутствие встроенной поддержки операций сбора данных. как существовать JavaScript используется в Set из add метод автоматического удаления дубликатов или используйте has Способы быстрого поиска элементов с такими существующими Solidity Все нужно реализовывать вручную. в целом,Это требует написания дополнительной логики и циклов.,Дальнейшее увеличение сложности контракта и затрат на его исполнение.

3.2 Сложность реализации дедупликации в Solidity

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

  1. Высокий и высокий gas расходы:Чтобы добиться дедупликации,Разработчикам необходимо пройти через все элементы множества,И обычно необходимо проверить, сохранился ли каждый отдельный элемент в процессе обхода. Использование сопоставлений или наборов для отслеживания просмотренных элементов является распространенным решением.,Но каждый визити Исправлять Картирование будет потреблять Газ, особенно когда его количество велико, может быть очень высоким.
  2. хранилище Пространство из отходов:Для достижения дедупликации,Нам нужны дополнительные изданные структуры, чтобы отслеживать, какие из элементов были обработаны. Например,Используйте сопоставление, чтобы записать, произошел ли индивидуальный элемент,Хотя таким образом можно сделать операцию поиска из Временной классификации равной O(1), но само отображение требует дополнительного места, что увеличивает общий контракт хранилищарасходов. Что еще хуже, хранилищесуществовать постоянно хранится в блокчейне, а это означает, что такое дополнительное потребление будет долгосрочным.
  3. Ограничение по пределу газа:Сопряжение с сетью Ethereumиндивидуальныйисполнение сделкииз gas Существует верхний предел количества (т. gas лимит). Если контрактная функция существует, потребляет при выполнении gas Если этот лимит превышен, транзакция будет отменена, и контракт не будет успешно выполнен. Сложность операций дедупликации может привести к gas Потребление быстро увеличивается, особенно когда приходится иметь дело с многочисленными операциями дедупликации, вложенными в большое количество или существующую сложную логику.

4. Способ 1. Используйте коллекции (или сопоставления) для удаления дубликатов.

Ниже приведен индивидуальный вариант использования openzepplin из EnumerableSet KuLai быстро дедуплицирует адрес раздачи из примера смарт-контракта:

Язык кода:javascript
копировать
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

// version >= v3.3.0
import {EnumerableSet} from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";

contract AirdropUniqueAddresses {
    // Using the EnumerableSet library for AddressSet
    using EnumerableSet for EnumerableSet.AddressSet;

    // Declare a state variable of type EnumerableSet.AddressSet to store unique addresses
    EnumerableSet.AddressSet private seen;

    // Function to add an address to the set if it is not already present
    function addAirdropAddress(address _address) public returns (bool) {
        // Add the address to the set
        // Returns true if the address was not already in the set, false otherwise
        return seen.add(_address);
    }

    // Function to check if an address is already in the set
    function isAirdropAddressSeen(address _address) public view returns (bool) {
        // Check if the address is in the set
        return seen.contains(_address);
    }

    // Function to get the total number of unique addresses in the set
    function getTotalUniqueAddresses() public view returns (uint256) {
        // Return the number of unique addresses in the set
        return seen.length();
    }

    // Function to retrieve an address by index in the set
    function getAirdropAddressAtIndex(uint256 index) public view returns (address) {
        // Ensure the index is within the bounds of the set
        require(index < seen.length(), "Index out of bounds");
        // Retrieve the address at the specified index
        return seen.at(index);
    }

    // Function to remove an address from the set
    function removeAirdropAddress(address _address) public returns (bool) {
        // Remove the address from the set
        // Returns true if the address was in the set and removed, false otherwise
        return seen.remove(_address);
    }
}
  • преимущество
    • Эффективность: картирование существующих Solidity предоставлено в O(1) из Найти время.
    • Легко реализовать: логика проста и понятна.
  • недостаток
    • Требуются дополнительные помещения, может увеличиться gas расходы。
    • Невозможно создать сопоставление динамически,Необходимо определиться заранееданныеструктура:Код такойсуществовать Во время компиляции будет сообщено об ошибкеUninitialized mapping. Mappings cannot be created dynamically, you have to assign them from a state variable.
Язык кода:javascript
копировать
mapping(uint256 => bool) memory seen;
uint256[] memory input = [1, 2, 2, 3, 4, 4];
for (uint256 i = 0; i < input.length; i++) {
    if (!seen[input[i]]) {
        seen[input[i]] = true;
    }
}

5. Способ 2: Дедупликация двойного цикла

Ниже приведен пример смарт-контракта, который использует двойной цикл для дедупликации адресов раздачи:

Язык кода:javascript
копировать
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract AirdropUniqueAddresses {
    // Function to get the unique addresses after removing duplicates
    function getUniqueAirdropAddresses(address[] airdropAddresses;) public view returns (address[] memory) {
        // Calculate the length of the airdropAddresses array
        uint256 length = airdropAddresses.length;

        // Create a dynamic array to store unique addresses
        address[] memory uniqueAddresses = new address[](length);
        uint256 uniqueCount = 0;

        // Outer loop to iterate through each address in the airdropAddresses array
        for (uint256 i = 0; i < length; i++) {
            bool isDuplicate = false;

            // Inner loop to check if the address is already in the uniqueAddresses array
            for (uint256 j = 0; j < uniqueCount; j++) {
                if (airdropAddresses[i] == uniqueAddresses[j]) {
                    isDuplicate = true;
                    break;
                }
            }

            // If the address is not a duplicate, add it to the uniqueAddresses array
            if (!isDuplicate) {
                uniqueAddresses[uniqueCount] = airdropAddresses[i];
                uniqueCount++;
            }
        }

        // Create a new array with the size of uniqueCount to store the final unique addresses
        address[] memory finalUniqueAddresses = new address[](uniqueCount);

        // Copy the unique addresses to the final array
        for (uint256 k = 0; k < uniqueCount; k++) {
            finalUniqueAddresses[k] = uniqueAddresses[k];
        }

        return finalUniqueAddresses;
    }
}
  • преимущество
    • Никаких дополнительных изхранилищ не требуется.,Очень экономит место.
    • Подходит для небольших объемов данных,Просто и легко понять.
  • недостаток
    • Временная сложность равна O(n^2),длябольшойданные Набор не применим。
    • может вызвать высокий gas Потребление, не рекомендуется для производственных сред используется в。

6. Справочные материалы

  1. https://docs.soliditylang.org/zh/v0.8.21/types.html
  2. https://docs.openzeppelin.com/contracts/3.x/api/utils#EnumerableSet
  3. https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/structs/EnumerableSet.sol
boy illustration
Углубленный анализ переполнения памяти CUDA: OutOfMemoryError: CUDA не хватает памяти. Попыталась выделить 3,21 Ги Б (GPU 0; всего 8,00 Ги Б).
boy illustration
[Решено] ошибка установки conda. Среда решения: не удалось выполнить первоначальное зависание. Повторная попытка с помощью файла (графическое руководство).
boy illustration
Прочитайте нейросетевую модель Трансформера в одной статье
boy illustration
.ART Теплые зимние предложения уже открыты
boy illustration
Сравнительная таблица описания кодов ошибок Amap
boy illustration
Уведомление о последних правилах Points Mall в декабре 2022 года.
boy illustration
Даже новички могут быстро приступить к работе с легким сервером приложений.
boy illustration
Взгляд на RSAC 2024|Защита конфиденциальности в эпоху больших моделей
boy illustration
Вы используете ИИ каждый день и до сих пор не знаете, как ИИ дает обратную связь? Одна статья для понимания реализации в коде Python общих функций потерь генеративных моделей + анализ принципов расчета.
boy illustration
Используйте (внутренний) почтовый ящик для образовательных учреждений, чтобы использовать Microsoft Family Bucket (1T дискового пространства на одном диске и версию Office 365 для образовательных учреждений)
boy illustration
Руководство по началу работы с оперативным проектом (7) Практическое сочетание оперативного письма — оперативного письма на основе интеллектуальной системы вопросов и ответов службы поддержки клиентов
boy illustration
[docker] Версия сервера «Чтение 3» — создайте свою собственную программу чтения веб-текста
boy illustration
Обзор Cloud-init и этапы создания в рамках PVE
boy illustration
Корпоративные пользователи используют пакет регистрационных ресурсов для регистрации ICP для веб-сайта и активации оплаты WeChat H5 (с кодом платежного узла версии API V3)
boy illustration
Подробное объяснение таких показателей производительности с высоким уровнем параллелизма, как QPS, TPS, RT и пропускная способность.
boy illustration
Удачи в конкурсе Python Essay Challenge, станьте первым, кто испытает новую функцию сообщества [Запускать блоки кода онлайн] и выиграйте множество изысканных подарков!
boy illustration
[Техническая посадка травы] Кровавая рвота и отделка позволяют вам необычным образом ощипывать гусиные перья! Не распространяйте информацию! ! !
boy illustration
[Официальное ограниченное по времени мероприятие] Сейчас ноябрь, напишите и получите приз
boy illustration
Прочтите это в одной статье: Учебник для няни по созданию сервера Huanshou Parlu на базе CVM-сервера.
boy illustration
Cloud Native | Что такое CRD (настраиваемые определения ресурсов) в K8s?
boy illustration
Как использовать Cloudflare CDN для настройки узла (CF самостоятельно выбирает IP) Гонконг, Китай/Азия узел/сводка и рекомендации внутреннего высокоскоростного IP-сегмента
boy illustration
Дополнительные правила вознаграждения амбассадоров акции в марте 2023 г.
boy illustration
Можно ли открыть частный сервер Phantom Beast Palu одним щелчком мыши? Супер простой урок для начинающих! (Прилагается метод обновления сервера)
boy illustration
[Играйте с Phantom Beast Palu] Обновите игровой сервер Phantom Beast Pallu одним щелчком мыши
boy illustration
Maotouhu делится: последний доступный внутри страны адрес склада исходного образа Docker 2024 года (обновлено 1 декабря)
boy illustration
Кодирование Base64 в MultipartFile
boy illustration
5 точек расширения SpringBoot, супер практично!
boy illustration
Глубокое понимание сопоставления индексов Elasticsearch.
boy illustration
15 рекомендуемых платформ разработки с нулевым кодом корпоративного уровня. Всегда найдется та, которая вам понравится.
boy illustration
Аннотация EasyExcel позволяет экспортировать с сохранением двух десятичных знаков.