Keccak

Design

Design criteria:

  • Simple API
  • Simple design
  • Lowest sloc possible
  • Pluggable choice of permutation implementation
  • Safe to incorporate in source form into client code (i.e.,
    strict conformance with the C11 standard)
  • Built-in-self-tests

Trade-offs

It trades support for big-endian platforms and arbitrary bit-length
messages for simplicity; I think this is a worthwhile tradeoff to
make. (If you have a big-endian platform to test on, however, I
am happy to accept pull requests in to implement
support.)

It trades some simplicity to get verification tools to work. This
is not a worthwhile tradeoff; it is a bug (perhaps mine, perhaps
the tools’).

Credits

Mad props to Guido Bertoni, Joan Daemen, Michaël Peeters,
and Gilles Van Assche for the very beautiful Keccak permutation,
and the incredibly useful sponge construction.

And also mad props to Ronny Van Keer, whose charming assembler
implementations of Keccak introduced me to the permutation.

The opt64 and varopt64 implementations of the permutation are
entirely their work (and some contribution from CPP and clang-format).

Notes

This code is not endorsed by the Keccak Team or, in fact,
anyone else. The official Keccak code package can be found at
https://github.com/gvanas/KeccakCodePackage

Their code has been substantially cleaned up recently; I believe that
it is now free of undefined behavior. It is much more flexible than
this code, at the cost of a more complex interface.

Тестовые векторы

Значения разных вариантов хеша от пустой строки.

SHA3-224("")
6b4e03423667dbb73b6e15454f0eb1abd4597f9a1b078e3f5b5a6bc7
SHA3-256("")
a7ffc6f8bf1ed76651c14756a061d662f580ff4de43b49fa82d80a4b80f8434a
SHA3-384("")
0c63a75b845e4f7d01107d852e4c2485c51a50aaaa94fc61995e71bbee983a2ac3713831264adb47fb6bd1e058d5f004
SHA3-512("")
a69f73cca23a9ac5c8b567dc185a756e97c982164fe25859e0d1dcc1475c80a615b2123af1f5f94c11e3e9402c3ac558f500199d95b6d3e301758586281dcd26
SHAKE128("", 256)
7f9c2ba4e88f827d616045507605853ed73b8093f6efbc88eb1a6eacfa66ef26
SHAKE256("", 512)
46b9dd2b0ba88d13233b3feb743eeb243fcd52ea62b81b82b50c27646ed5762fd75dc4ddd8c0f200cb05019d67b592f6fc821c49479ab48640292eacb3b7c4be

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

SHA3-224("The quick brown fox jumps over the lazy dog")
d15dadceaa4d5d7bb3b48f446421d542e08ad8887305e28d58335795
SHA3-224("The quick brown fox jumps over the lazy dog.")
2d0708903833afabdd232a20201176e8b58c5be8a6fe74265ac54db0
SHA3-256("The quick brown fox jumps over the lazy dog")
69070dda01975c8c120c3aada1b282394e7f032fa9cf32f4cb2259a0897dfc04
SHA3-256("The quick brown fox jumps over the lazy dog.")
a80f839cd4f83f6c3dafc87feae470045e4eb0d366397d5c6ce34ba1739f734d
SHA3-384("The quick brown fox jumps over the lazy dog")
7063465e08a93bce31cd89d2e3ca8f602498696e253592ed26f07bf7e703cf328581e1471a7ba7ab119b1a9ebdf8be41
SHA3-384("The quick brown fox jumps over the lazy dog.")
1a34d81695b622df178bc74df7124fe12fac0f64ba5250b78b99c1273d4b080168e10652894ecad5f1f4d5b965437fb9
SHA3-512("The quick brown fox jumps over the lazy dog")
01dedd5de4ef14642445ba5f5b97c15e47b9ad931326e4b0727cd94cefc44fff23f07bf543139939b49128caf436dc1bdee54fcb24023a08d9403f9b4bf0d450
SHA3-512("The quick brown fox jumps over the lazy dog.")
18f4f4bd419603f95538837003d9d254c26c23765565162247483f65c50303597bc9ce4d289f21d1c2f1f458828e33dc442100331b35e7eb031b5d38ba6460f8
SHAKE128("The quick brown fox jumps over the lazy dog", 256)
f4202e3c5852f9182a0430fd8144f0a74b95e7417ecae17db0f8cfeed0e3e66e
SHAKE128("The quick brown fox jumps over the lazy dof", 256)
853f4538be0db9621a6cea659a06c1107b1f83f02b13d18297bd39d7411cf10c

Дополнение[править | править код]

Для того, чтобы исходное сообщение M можно было разделить на блоки длины r, необходимо дополнение. В SHA-3 используется паттерн pad10*1: к сообщению добавляется 1, после него — 0 или больше нулевых битов (до r-1), в конце — 1.

r-1 нулевых битов может быть добавлено, когда последний блок сообщения имеет длину r-1 бит. Этот блок дополняется единицей, следующий блок будет состоять из r-1 нулей и единицы.

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

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

Аппаратное ускорение

Шестиядерные процессорные ядра SoC Apple A13 ARMv8 поддерживают ускорение SHA-3 (и SHA-512) с использованием специализированных инструкций (EOR3, RAX1, XAR, BCAX) из набора криптографических расширений ARMv8.2-SHA.

Некоторые программные библиотеки используют средства векторизации ЦП для ускорения использования SHA-3. Например, Crypto ++ может использовать SSE2 на x86 для ускорения SHA3, а OpenSSL может использовать MMX , AVX-512 или AVX-512VL также на многих системах x86. Также процессоры POWER8 реализуют 2×64-битное вращение вектора, определенное в PowerISA 2.07, которое может ускорять Каким-то образом реализации SHA-3. Большинство реализаций для ARM не используют векторные команды , как это происходит медленнее , чем скалярный код , однако он может быть ускорены с помощью СВА и SVE2 инструкции вектора (например , на Fujitsu A64FX CPU).

Хэш-функция

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

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

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

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

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

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

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

Примеры вариантов SHA-3

Следующие хеш-значения взяты с сайта NIST.gov:

SHA3-224("") 6b4e03423667dbb73b6e15454f0eb1abd4597f9a1b078e3f5b5a6bc7 SHA3-256("") a7ffc6f8bf1ed76651c14756a061d662f580ff4de43b49fa82d80a4b80f8434a SHA3-384("") 0c63a75b845e4f7d01107d852e4c2485c51a50aaaa94fc61995e71bbee983a2ac3713831264adb47fb6bd1e058d5f004 SHA3-512("") a69f73cca23a9ac5c8b567dc185a756e97c982164fe25859e0d1dcc1475c80a615b2123af1f5f94c11e3e9402c3ac558f500199d95b6d3e301758586281dcd26 SHAKE128("", 256) 7f9c2ba4e88f827d616045507605853ed73b8093f6efbc88eb1a6eacfa66ef26 SHAKE256("", 512) 46b9dd2b0ba88d13233b3feb743eeb243fcd52ea62b81b82b50c27646ed5762fd75dc4ddd8c0f200cb05019d67b592f6fc821c49479ab48640292eacb3b7c4be 

Изменение одного бита приводит к тому, что каждый бит на выходе изменяется с вероятностью 50%, демонстрируя лавинный эффект :

SHAKE128("The quick brown fox jumps over the lazy dog", 256) f4202e3c5852f9182a0430fd8144f0a74b95e7417ecae17db0f8cfeed0e3e66e SHAKE128("The quick brown fox jumps over the lazy dof", 256) 853f4538be0db9621a6cea659a06c1107b1f83f02b13d18297bd39d7411cf10c 

Функция перестановок

Базовая функция перестановки состоит из раундов по пять шагов:

  1. Шаг

  2. Шаг

  3. Шаг

  4. Шаг

  5. Шаг

Тета, Ро, Пи, Хи, Йота

Далее будем использовать следующие обозначения:

Так как состояние имеет форму массива , то мы можем обозначить каждый бит состояния как

Обозначим результат преобразования состояния функцией перестановки

Также обозначим функцию, которая выполняет следующее соответствие:

— обычная функция трансляции, которая сопоставляет биту бит ,

где — длина слова (64 бит в нашем случае)

Я хочу вкратце описать каждый шаг функции перестановок, не вдаваясь в математические свойства каждого.

Шаг

Эффект отображения можно описать следующим образом: оно добавляет к каждому биту побитовую сумму двух столбцов и

Схематическое представление функции:

Псевдокод шага:

Шаг

Отображение направлено на трансляции внутри слов (вдоль оси z).

Проще всего его описать псевдокодом и схематическим рисунком:

Шаг

Шаг представляется псевдокодом и схематическим рисунком:

Шаг

Шаг является единственный нелинейным преобразованием в

Псевдокод и схематическое представление:

Шаг

Отображение состоит из сложения с раундовыми константами и направлено на нарушение симметрии. Без него все раунды были бы эквивалентными, что делало бы его подверженным атакам, использующим симметрию. По мере увеличения раундовые константы добавляют все больше и больше асимметрии.

Ниже приведена таблица раундовых констант для бит

Все шаги можно объединить вместе и тогда мы получим следующее:

Где константы являются циклическими сдвигами и задаются таблицей:

Как работает хеширование?

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

Валидное число в строке шифрованной подписи криптоблока биткоина должно содержать энное количество нулей. На момент составления обзора количество нулей в хеш-коде цифрового золота уже перевалило число 17. Поэтому расшифровка sha256 сложнее, чем поиск некой определенной песчинки, которая находится в произвольной точке земного шара.

Важно! В принципе зашифровать можно все что угодно хоть поэму Лермонтова «Кавказский пленник» и в результате получится шестнадцатеричный код типа: c8ba7865a9x924590dcc54a6f227859z. Шифрование не имеет обратной силы, сделать с цифробуквенного набора текст не получится, но если в самой поэме изменить хотя бы одну точку или пробел, то хеш-код произведения будет совершено иным

Вы можете убедиться в этом сами, посетив сайт для автоматической шифровки https://crypt-online.ru/crypts/sha256/

Шифрование не имеет обратной силы, сделать с цифробуквенного набора текст не получится, но если в самой поэме изменить хотя бы одну точку или пробел, то хеш-код произведения будет совершено иным. Вы можете убедиться в этом сами, посетив сайт для автоматической шифровки https://crypt-online.ru/crypts/sha256/.

Зависимость блоков в сети биткион

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

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

Usage

You can use this library from Node.js, from web browsers, and/or using ES6 imports.

Node.js (CommonJS style)

// Standard FIPS 202 SHA-3 implementation
const { SHA3 } = require('sha3');

// The Keccak hash function is also available
const { Keccak } = require('sha3');

ES6

// Standard FIPS 202 SHA-3 implementation
import { SHA3 } from 'sha3';

// The Keccak hash function is also available
import { Keccak } from 'sha3';

What’s in the box

FIPS-compatible interfaces for the following algorithms:

  • : The SHA3 algorithm.
  • : The Keccak algorithm.
  • : The SHAKE XOF algorithm.

Examples

Generating a SHAKE128 hash with 2048 bytes

import { SHAKE } from 'sha3';

const hash = new SHAKE(128);

hash.update('foo');
hash.digest({ buffer: Buffer.alloc(2048), format: 'hex' });

API Reference

All hash implementations provided by this library conform to the following API specification.

The constructor for each hash (e.g: , ), expects the following parameters:

size (Number): Optional. The size of the hash to create, in bits. If provided, this must be one of 224, 256, 384, or 512. Defaults to 512.

Example
// Construct a new Keccak hash of size 256
const hash = new Keccak(256);

Updates the hash content with the given data. Returns the hash object itself.

  • (Buffer|string): Required. The data to read into the hash.
  • (string): Optional. The encoding of the given , if of type . Defaults to .
Example
const hash = new Keccak(256);

hash.update('hello');

hash.update('we can also chain these').update('together');

Digests the hash and returns the result. After calling this function, the hash may continue to receive input.

encoding (string): Optional. The encoding to use for the returned digest. Defaults to ‘binary’.

If an is provided and is a value other than , then this function returns a .
Otherwise, it returns a .

Example
const hash = new Keccak(256);

hash.update('hello');

hash.digest('hex');
// => hash of 'hello' as a hex-encoded string

Digests the hash and returns the result. After calling this function, the hash may continue to receive input.

Options include:

  • (Buffer): Optional. A pre-allocated buffer to fill with output bytes. This is how XOF algorithms like SHAKE can be used to obtain an arbitrary number of hash bytes.
  • (string): Optional. The encoding to use for the returned digest. Defaults to . If is also provided, this value will passed directly into on the given buffer.
  • (byte): Optional. Override the padding used to pad the input bytes to the algorithm’s block size. Typically this should be omitted, but may be required if building additional cryptographic algorithms on top of this library.

If a is provided and is a value other than , then this function returns a .
Otherwise, it returns a .

Example
const hash = new Keccak(256);

hash.update('hello');

hash.digest({ buffer: Buffer.alloc(32), format: 'hex' });
// => hash of 'hello' as a hex-encoded string

Resets a hash to its initial state.

  • All input buffers are cleared from memory.
  • The hash object can safely be reused to compute another hash.
Example
const hash = new Keccak(256);

hash.update('hello');
hash.digest();
// => hash of 'hello'

hash.reset();

hash.update('world');
hash.digest();
// => hash of 'world'

Скорость

Скорость хеширования длинных сообщений SHA-3 определяется вычислением f = Keccak-f и XORing S с расширенным P i , операцией над b = 1600 битами. Однако, поскольку последние c бит расширенного P i в любом случае равны 0, а XOR с 0 является NOP, достаточно выполнить операции XOR только для r бит ( r = 1600 — 2 × 224 = 1152 бит для SHA3-224 , 1088 бит для SHA3-256, 832 бит для SHA3-384 и 576 бит для SHA3-512). Чем меньше r (и, наоборот, чем выше c = br = 1600 — r ), тем менее эффективным, но более безопасным становится хеширование, поскольку меньшее количество битов сообщения может быть преобразовано в состояние XOR (быстрая операция) перед каждым применение затратных в вычислительном отношении f . Авторы сообщают о следующих скоростях программных реализаций Keccak-f плюс XORing 1024 бит, что примерно соответствует SHA3-256:

  • 57,4 cpb на IA-32, Intel Pentium 3
  • 41 cpb на IA-32 + MMX, Intel Pentium 3
  • 20 cpb на IA-32 + SSE, Intel Core 2 Duo или AMD Athlon 64
  • 12,6 cpb на типичной машине на базе x86-64
  • 6–7 cpb на IA-64

Для точного SHA3-256 на x86-64 Бернштейн измеряет 11,7–12,25 cpb в зависимости от процессора. SHA-3 подвергался критике за то, что он медленный на архитектурах набора команд (CPU), которые не имеют инструкций, специально предназначенных для более быстрого вычисления функций Keccak — SHA2-512 более чем в два раза быстрее, чем SHA3-512, а SHA-1 более в три раза быстрее на процессоре Intel Skylake с тактовой частотой 3,2 ГГц. Авторы отреагировали на эту критику, предложив использовать SHAKE128 и SHAKE256 вместо SHA3-256 и SHA3-512 за счет сокращения вдвое сопротивления прообраза (но при сохранении сопротивления столкновению). При этом производительность находится на уровне SHA2-256 и SHA2-512.

Однако в аппаратной реализации SHA-3 заметно быстрее, чем все остальные финалисты, а также быстрее, чем SHA-2 и SHA-1.

Архитектуры ARMv8 ARMv8 и IBM s390x уже (по состоянию на 2018 год) включают специальные инструкции, которые позволяют алгоритмам Keccak выполняться быстрее.

Sample Programs

There are five sample programs. The first prints information about the hash. The second creates a hash using SHA3-256 class. The third creates a hash using a pipeline. The fourth and fifth examples show how to verify an existing digest.

The examples below use SHA3-256, but you can swap-in any hash function, like PanamaHash or SM3.

The first example dumps the name, digest size and internal block size of the hash.

#include "cryptlib.h"
#include "sha3.h"
#include <iostream>

int main (int argc, char* argv[])
{
    using namespace CryptoPP;

    SHA3_256 hash;	
    std::cout << "Name: " << hash.AlgorithmName() << std::endl;
    std::cout << "Digest size: " << hash.DigestSize() << std::endl;
    std::cout << "Block size: " << hash.BlockSize() << std::endl;

    return 0; 
}

Running the program results in the following. In general you should use and avoid . is usually not required by a program. In the case of SHA3 the block size is the rate .

$ ./test.exe
Name: SHA3-256
Digest size: 32
Block size: 136

The second example creates a hash using the hash object and member functions. You add data using and you calculate the hash using . Calling resets the hash so you don’t need to do it manually.

using namespace CryptoPP;
HexEncoder encoder(new FileSink(std::cout));

std::string msg = "Yoda said, Do or do not. There is no try.";
std::string digest;

SHA3_256 hash;
hash.Update((const byte*)msg.data(), msg.size());
digest.resize(hash.DigestSize());
hash.Final((byte*)&digest);

std::cout << "Message: " << msg << std::endl;

std::cout << "Digest: ";
StringSource(digest, true, new Redirector(encoder));
std::cout << std::endl;

Running the program results in the following.

$ ./test.exe
Message: Yoda said, Do or do not. There is no try.
Digest: 18CEA61486D217DCDC19246FA28BBD32660CEC3771442B5C2AB93271D32B2797

You can also obtain a truncated hash rather than the full hash using .

std::cout << "Message: " << msg << std::endl;

hash.Update((const byte*)msg.data(), msg.size());
digest.resize(hash.DigestSize()/2);
hash.TruncatedFinal((byte*)&digest, digest.size());

std::cout << "Digest: ";
StringSource(digest, true, new Redirector(encoder));
std::cout << std::endl;

The program produces the following result.

$ ./test.exe
Message: Yoda said, Do or do not. There is no try.
Digest: 18CEA61486D217DCDC19246FA28BBD32

Using a pipeline produces the same result. It relieves you of calling and Final manually. The code also uses a , which has its own wiki page at HashFilter.

std::string msg = "Yoda said, Do or do not. There is no try.";
std::string digest;

StringSource(msg, true, new HashFilter(hash, new StringSink(digest)));

std::cout << "Message: " << msg << std::endl;

std::cout << "Digest: ";
StringSource(digest, true, new Redirector(encoder));
std::cout << std::endl;

Running the program results in the following.

$ ./test.exe
Message: Yoda said, Do or do not. There is no try.
Digest: 18CEA61486D217DCDC19246FA28BBD32660CEC3771442B5C2AB93271D32B2797

The fourth program verifies an existing hash using the hash object. Notice the program proceeds as if the hash is going to be calculated. But rather than calling to retrieve the hash, is called to verify the existing hash.

SHA3_256 hash;
hash.Update((const byte*)msg.data(), msg.size());
bool verified = hash.Verify((const byte*)digest.data());

if (verified == true)
    std::cout << "Verified hash over message" << std::endl;
else
    std::cout << "Failed to verify hash over message" << std::endl;

The final program verifies an existing hash using a pipeline. The code uses a , which has its own wiki page at HashVerificationFilter.

bool result;
StringSource(digest+msg, true, new HashVerificationFilter(hash,
                 new ArraySink((byte*)&result, sizeof(result))));

if (result == true)
    std::cout << "Verified hash over message" << std::endl;
else
    std::cout << "Failed to verify hash over message" << std::endl;

Running the program results in the following output.

$ ./test.exe
Message: Yoda said, Do or do not. There is no try.
Digest: 18CEA61486D217DCDC19246FA28BBD32660CEC3771442B5C2AB93271D32B2797
Verified hash over message

Вывод — рентабельность оборудования

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

Даже последние модели АСИКов ля добычи биткоин имеют срок окупаемости свыше 6 месяцев. АСИК нельзя перестроить на другой алгоритм или продать геймерам. Правда на каждый из популярных алгоритмов добычи припадает в среднем 20-30 альтов, но профит на каждом из них разный. Добывайте самый выгодный в текущий момент токен и если не считаете его подходящим для длительного хранения, то обменивайте на бирже на более твердую криптовалюту, например, биткоин или эфир. Лучше не держать все активы в малоизвестных альткоинах.

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

Главное не впадайте в панику при нисходящем тренде, год назад BTC стоил 3000$, а потом снова поднялся и по-прежнему остается самой перспективной монетой. Не спешите продавать добытые монеты и средства, вложенные в майнинг криптовалюты принесут существенный доход в будущем.

The following two tabs change content below.

Mining-Cryptocurrency.ru

Материал подготовлен редакцией сайта «Майнинг Криптовалюты», в составе: Главный редактор — Антон Сизов, Журналисты — Игорь Лосев, Виталий Воронов, Дмитрий Марков, Елена Карпина. Мы предоставляем самую актуальную информацию о рынке криптовалют, майнинге и технологии блокчейн.
Отказ от ответственности: все материалы на сайте Mining-Cryptocurrency.ru имеют исключительно информативные цели и не являются торговой рекомендацией или публичной офертой к покупке каких-либо криптовалют или осуществлению любых иных инвестиций и финансовых операций.

Новости Mining-Cryptocurrency.ru

  • Исследование Fidelity: 52% крупнейших инвесторов уже владеют криптовалютой — 18.09.2021
  • «Народная партия» Канады выступила с критикой Центробанка и поддержала биткоин — 18.09.2021
  • Эмитенты стейблкоинов обязаны обеспечить свободную конвертацию токенов в фиат — 18.09.2021
  • Создатель биткоина Сатоши Накамото увековечен в виде бронзовой статуи в Венгрии — 18.09.2021
  • Как изменилась комиссия за транзакции в сети Ethereum после обновления London? — 18.09.2021