Глубокое погружение: модель безопасности Биткойна

Глубокое погружение: модель безопасности Биткойна Майнинг

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

У каждой модели сохранности есть две главные части: догадки и гарантии. Если предполагаемые входные данные являются верными, то должны обеспечиваться и гарантии на выходе из модели.

Давайте углубимся в модель сохранности, предлагаемую юзерам Биткойна, поддерживающим полные узлы.

В поисках правды

«одна из мощных сторон Биткойна — даже одна из самых основных, по моему воззрению — это ваша возможность низкой степени доверия к остальным». — Питер Уилл

Цель распределённых реестров — обеспечивать упорядоченную историю событий, поэтому что в распределённых системах вы не сможете просто доверять временным меткам.

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

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

Беря во внимание такое предположение, операторы полных узлов могут быть полностью убеждены в неких фактах:

  • никто не увеличивал валютную массу не считая майнеров и в согласовании со строго установленным графиком;
  • никто не издержал средства без владения соответствущим приватным ключом;
  • никто не издержал те же самые средства два раза.

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

  • Хоть какой блок в цепи был сотворен в течение двухчасового промежутка относительно временной метки самого блока;
  • Они синхронизируют подлинную версию истории блокчейна.

Технически это востребует огромного количества проверок.

Все блоки следуют правилам консенсуса:

  • Любой блок связан с родительским блоком;
  • Любой блок соответствует собственной степени трудности и на его решение затрачена значимая работа;
  • Временные метки блока находятся в границах окна времени для не так давно отысканных блоков;
  • Корень Блекла (хэш суммы хэша каждой транзакции в блоке) соответствует всем транзакциям в блоке;
  • Ни один из блоков не превосходит очень допустимый размер;
  • 1-ая (и лишь 1-ая) транзакция всякого блока является coinbase транзакцией (особенный тип транзакции, который не просит существовавших ранее выходов, т.е. это заслуга, которую майнеры получают за добычу новейших блоков);
  • Coinbase выходы выплачивают не больше чем установленное сейчас вознаграждение за отысканный блок;
  • Блоки содержат лишь допустимые операции подписывания.

Все транзакции следуют правилам консенсуса:

  • Входные и выходные значения являются допустимыми;
  • Транзакции растрачивают лишь неистраченные выходы;
  • Все потраченные входы имеют действительные подписи;
  • Ни один из выходов Coinbase транзакций не был истрачен ранее 100 блоков, отысканных с момента их сотворения (созревание приобретенных майнерами монет);
  • Ни одна из транзакций не истратила входы в неподтверждённом состоянии, т.е до включения её в блок.

Есть также огромное количество остальных правил, обсуждение которых тут займёт очень много времени.

Термодинамика сохранности

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

Глубокое погружение: модель безопасности Биткойна: “Bitcoin’s Security Model Revisited” by Yonatan Sompolinsky1 and Aviv Zohar

Пока никто из атакующих не владеет вычислительной мощностью, превосходящей мощность сети на 50% и добросовестные узлы могут стремительно связываться меж собой, возможность отмены транзакции миниатюризируется по экспоненте совместно с ростом количества подтверждений данной для нас транзакции. Есть остальные типы атак, к примеру эгоистичный майнинг, которые могут понизить нужное количество мощности, но, они достаточно сложны в реализации.

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

Глубокое погружение: модель безопасности Биткойна: HTTP://bitcoin.sipa.be

Разберём некие ценовые характеристики таковой атаки:

Antminer S9 просит 0.1 джоулей на Гх/с(109 хэшей)
1026 хэшей * 0.1 Дж / 109 хэшей = 1015 джоулей
1015 джоулей = 2,777,777,778 кв/ч * $0.10 кв/ч = $277,777,778 будет стоимость электроэнергии для перезаписи всего блокчейна.

На момент написания статьи, сложность раздельно взятого блока стремится к 253,618,246,641, что востребует приблизительно:
253,618,246,641 * 248 / 65535 = 1.09 * 1021 хэшей.
1.09 * 1021 хэшей * 0.1 J / 109 хэшей = 1.09 * 1011 джоулей
1.09 * 1011 джоулей = 30,278 кВт/час * $0.10 кВт/час = $3,028 стоимость электроэнергии для перезаписи 1-го блока.

Вот почему мы можем доказательно утверждать, что Биткойн термодинамически неопасен.

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

Также направьте внимание, что в этом расчёте отсутствует учёт цены владения и использования нужного количества майнингового оборудования для проведения такового типа атаки.

Сопротивление Sybil атакам

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

Это также понятно как «Sybil сопротивление», значащее, что нереально штурмовать узел, создавая много нечестных пиров, выдающих неверную информацию.

Глубокое погружение: модель безопасности Биткойна

На рисунке представлен наихудший сценарий, в каком ваш узел подвергается массированной Sybil атаке, но всё ещё имеет одно соединение с добросовестным узлом, который подключен к настоящей Биткойн-сети. До того времени, пока один добросовестный пир передает настоящие блокчейн-данные на ваш полный узел, будет совсем ясно, что какие-то Sybil злоумышленники пробуют одурачить вас, и ваш узел будет игнорировать их.

Консенсус в настоящем времени

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

Создатели “Research Perspectives and Challenges for Bitcoin and Cryptocurrencies” отмечают последующие характеристики, которые важны для стабильности криптовалюты:

Окончательный консенсус. В хоть какое время все совместимые узлы согласовывают префикс того, что станет вероятным “настоящим” блокчейном.

Экспоненциальное сближение. Возможность ответвления для глубины n равна O(2−n). Это дает юзерам высшую уверенность, что обычное правило “k подтверждений” обеспечит неизменяемость состоявшихся транзакций.

Живучесть. Новейшие блоки и достоверные транзакции с адекватными комиссиями продолжат добавляться в блокчейн в течение применимого периода времени.

Корректность. Все блоки в цепи с большим подтверждением объёма работы будут включать лишь действительные транзакции.

Справедливость. Майнер, обладающий X% от общей вычислительной мощности сети будет добывать примерно X% блоков.

Создатели статьи отмечают, что Биткойн, по-видимому, владеет этими качествами, по последней мере, в предположении, что большая часть майнеров остаются добросовестными, а провоцировать их будет вознаграждение за отысканный блок, приобретенный при предоставлении подтверждения выполненного размера работы (Proof of Work).

Существует много остальных алгоритмов, которые могут быть применены для поддержания консенсуса в распределенных системах, к примеру:

  • Подтверждение владения;
  • Подтверждение возраста монеты;
  • подтверждение депозита;
  • Подтверждение поражения;
  • Подтверждение деятельности;
  • подтверждение издержек прошедшего времени;
  • Федеративный Консенсус;
  • Практическая Византийская Отказоустойчивость.

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

Непонимание модели сохранности

Есть распространенное неверное предположение, что у Биткойна существует чётко определённая модель сохранности.

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

Некие блокчейны довольно очень пострадали от атак, когда создатели добавляли централизованно транслируемые подписанные контрольные точки в программное обеспечение узла, на самом деле утверждая, что “блок X был проверен разрабами как находящийся в правильной исторической цепочке.” Это является моделью абсолютной централизации.

Необходимо отметить, что биткойн имеет 13 агрессивно закодированных контрольных точек, но они не меняют модель сохранности так, как это делают централизованно транслируемые контрольные точки. Крайняя контрольная точка была добавлена в Bitcoin Core 0.9.3 и находится на блоке 295000, который был сотворен 9 апреля 2014 года. Этот блок имел сложность 6,119,726,089, которая востребует примерно:

6,119,726,089 * 248 / 65535 = 2.62 * 1019 хэшей
2.62 * 1019 хэшей * 0.1 J / 109 хэшей = 2.62 * 109 джоулей
2.62 * 109 джоулей = 728 кВт/час * $0.10 кВт/час = $73 сумму для генерации блока.

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

Если атакующий отсечёт узел от сети, пока тот синхронизируется до блока 295000, то атакующий будет способен выдавать ему липовые блоки, затрачивая $73 на один блок, пока в конце концов не достигнет момента пересчёта трудности. Но в процессе предстоящей синхронизации атакуемого узла, для атакующего будут повсевременно расти Издержки на поддержку цепи с увеличенным совокупным объёмом выполненной работы.

Грег Максвелл и Питер Уилл вдвоём заявили, что они уповают когда-нибудь на сто процентов удалить контрольные точки. Ведущий спец по сопровождению Bitcoin Core Владимир ван дер Лаан отметил, что контрольные точки являются неизменным источником неурядицы для людей, которые стремятся осознать модель сохранности Биткойна.

Можно привести аргумент, значащий, что полный узел “доверяет” разрабам Bitcoin Core относительно реальности истории блокчейна до 9 апреля 2014 года, но узел как и раньше инспектирует Merkle-хэши в заголовке всякого блока, а это значит, что надежность истории транзакций как и раньше обеспечивается подтверждением произведённой работы. Эти старенькые контрольные точки разрешают прирастить производительность (пропуская проверку подписи) при начальной синхронизации блокчейна, хотя введение libsecp256k1 сделало разницу в производительности наименее значимой.

Контрольные точки остаются задействованными для 3-х целей:

  • Предотвращение наполнения памяти узлов допустимыми, но не надлежащими трудности (низкими) заголовками отысканных блоков.
  • Пропуск подписей в прошлых блоках (увеличение производительности).
  • Оценка хода выполнения синхронизации.
  • Пока писалась эта статья, Грег Максвелл предложил поменять контрольные точки кумулятивной проверкой работы. Как узел настраивается на цепь, которая содержит больше чем 5.4 * 1024 хэша,  цепи с наименьшим количеством кумулятивной работы будут считаться недействительными. Это приблизительно совпадает с объемом выполненных работ до блока 320,000 в сентябре 2014 года, и на тот момент сложность отдельных блоков была приблизительно 27,000,000,000.

    Глубокое погружение: модель безопасности Биткойна: Blockchain.info

    Добыча блоков на трудности 27,000,000,000 востребует приблизительно
    27,000,000,000 * 248 / 65535 = 1.16 * 1020 хэшей
    1.16 * 1020 хэшей * 0.1 дж / 109 хэшей = 1.16 * 1010 джоулей
    1.16 * 1010 джоулей = 3,222 кВт/час * $0.10 кВт/час = $322 за блок

    Таковым образом, беря во внимание предложенное изменение, если Sybil-атакующий на сто процентов окружил новейший узел, который синхронизировался с нуля, он сумел бы выдавать ему неверные блоки, начиная с хоть какого блока опосля genesis блока, практически не затрачивая средств. Если Sybil злодей на сто процентов окружил узел, который синхронизировался приблизительно с блока 320 000, он может начать выдавать ему неверную цепь с данной для нас точки по стоимости 322 бакса за блок.

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

    Добавим к вышесказанному, что любая Блокчейн система имеет собственный genesis блок, агрессивно закодированный в программное обеспечение узла. Вы сможете утверждать, что существует соц договор с “общей историей”, которая является распределённым реестром, т.е. как блок становится довольно стар, посреди всех участников сети возникает осознание того, что его никогда недозволено будет поменять. Таковым образом, когда создатели берут весьма старенькый блок и делают из него контрольную точку, это делается на базе соглашения о проверке реальности, а не под диктатом истории.

    В дополнение к контрольным точкам существует также вопросец о том, как узел загружает сам себя. Текущий процесс для Биткойн-узлов состоит в том, чтоб проверить, есть ли у него локальная база данных пиров, о которых он знал ранее. Если нет, то он запросит набор “семян DNS”, которые агрессивно закодированы в программное обеспечение. Эти семечки содержат перечень адресов отлично связанных Биткойн-узлов, загружаемых на ваш узел.

    Как мы лицезреем из кода Bitcoin Core 0.13, активные на сей день DNS семечки поддерживают Питер Уилл, Мэтт Коралло, Лючок Дашр, Кристиан Декер, Джефф Гарзик и Джонас Шнелли. Хоть какой может поддерживать в сети DNS семечки, используя ПО Питера Уила bitcoin-seeder либо ПО Мэтта Коралло, хотя для принятия новенькими узлами, для вас необходимо уверить разрабов одной из полных реализаций узла добавить собственный DNS-хост в их программное обеспечение.

    Это может ещё раз показаться точкой абсолютной централизации, когда процесс исходной загрузки для новейшего узла зависит от всего только 6 семян DNS. Напомним, что модель сохранности Биткойна просит подключения лишь к одному добросовестному пиру, для противодействия Sybil атакам.

    Таковым образом, новейший узел должен быть в состоянии лишь объединиться с одним семенем DNS, которое не скомпрометировано и возвращает IP-адреса добросовестных узлов. Но существует запасный вариант, если по некий причине все семечки DNS недосягаемы – это агрессивно закодированный перечень надежных IP-адресов узлов, который обновляется для всякого релиза.

    Модель сохранности для разных характеристик инициализации заключается не в том, что оператор полного узла доверяет ДНС семенам от Х либо разрабам ядра от Y чтоб выдавать им добросовестные данные, а в том, что по последней мере 1/х ДНС семян не скомпрометировано либо 1/y Core разрабов честны относительно рассмотрения утверждённых конфигураций перечня жёстко запрограммированных пиров.

    Ничто не является полностью неопасным

    На ещё наиболее глубочайшем уровне, когда вы запускаете полный узел, вы в определенной степени доверяете аппаратному и программному обеспечению с которым работаете.

    Есть способы проверки программного обеспечения методом сравнения цифровых подписей вашего двоичного файла с подписями van der Laan, но маловероятно, что почти все люди озаботятся прохождением таковой проверки. Что касается надежного оборудования, это непростая неувязка. Быстрее всего вы будете применять неопасное аппаратное решение наподобие ORWL, которое гарантированно “самоуничтожится”, при попытке вмешательства снаружи.Глубокое погружение: модель безопасности Биткойна

    Но, беря во внимание, что аппаратные архитектуры для микропроцессоров, оперативки и другого принципиального оборудования, как правило, являются проприетарными, вы никогда не сможете быть на 100% убеждены, что они не скомпрометированы.

    Баланс сил в Биткойне

    Вода становится ещё наиболее мутной, когда вы начинаете изучить дела меж разными участниками системы.

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

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

    Облегченное описание динамики сил воздействия в Биткойне:

    3 branches of BTC "governance:"
    * Full Nodes (can veto miners & devs)
    * Miners (can veto devs)
    * Devs (can help others bypass some vetoes)

    — Jameson Lopp (@lopp) October 12, 2016

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

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

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

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

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

    Сохранность SPV

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

    клиент, использующий облегченную проверку платежей (SPV), загружает полную копию заголовков для всех блоков во всей цепи. Это значит, что требования к загрузке и хранению масштабируются линейно с количеством времени с момента изобретения Биткойна. Это описано в разделе 8 whitepaper Биткойна.

    Глубокое погружение: модель безопасности Биткойна

    Сатоши писал, что SPV клиент “не может проверить транзакцию без помощи других, но связав её с определённым местом в цепи, он может узреть, что сетевой узел принял её, и блоки, добавленные опосля неё, в предстоящем только подтверждают принятие транзакции сетью”. SPV подразумевает, что предстоящее блокирование транзакции X будет стоить недешево.

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

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

    SPV клиенты в состоянии сделать запрос, чтоб выяснить информацию о транзакциях, затрагивающих определенные адреса. Невзирая на то, что для пиров было бы достаточно недешево врать о существовании поддельных подтвержденных транзакций (будет нужно майнинг блока с достаточным количеством PoW), они могут врать, утверждая, что результаты для bloom фильтра, использованного для запроса инфы о транзакциях, отсутствуют. Также необходимо отметить, что SPV серьёзно уязвима исходя из убеждений кофиденциальности из-за изъянов в bloom фильтрах.

    BitcoinJ имеет хорошее описание модели сохранности SPV. Касаемо неподтвержденных транзакций отмечено:

    “В режиме SPV, единственная причина, по которой вы сможете доверять подлинности транзакции, это факт трансляции транзакции узлами к которым вы подключены. Если злодей сумел бы уверить вас, что вы подключены к его узлам, это означало, что он сумел бы вынудить вас принять на сто процентов недействительную транзакцию (потраченные несуществующие средства), и она все равно была бы принята, как если б она была истинной”.

    Сохранность SPV, возможно, “довольно хороша” для среднего юзера, хотя она быть может усовершенствована при помощи доказательств мошенничества SPV. Была проведена дискуссия по данной для нас концепции, но предложения по их включению в протокол не были реализованы.

    Там нет такового места, как Локалхост

    Если вы не оперируете полным узлом (и практически не используете его для проверки транзакций), вы передаете на аутсорсинг по последней мере некий уровень доверия третьим лицам, что приводит к другой модели сохранности для вашего использования Биткойна. Обратите внимание, что это не непременно просит, чтоб все юзеры и компании делали свое ПО конкретно поверх RPC API Bitcoin Core.

    Некие другие конфигурации инфраструктуры могут применять последующие варианты, но не ограничиваться лишь ими:

    1) Внедрение мобильного кошелька, такового как Bitcoin Wallet для Android, GreenAddress либо Stash, которые разрешают настроить кошелек для выполнения запросов лишь с вашего собственного полного узла. Глубокое погружение: модель безопасности Биткойна

    2) Создание приложений на базе библиотек узлов SPV, таковых как BitcoinJ, и настройка их для подключения лишь к вашим своим полным узлам. В BitcoinJ это можно сделать, определив собственные SeedPeers, которые вы передаете вашей группе пиров во время инициализации. При помощи libbitcoin вы сможете настроить сетевое подключение к определенному узлу, используя этот пример.

    3) Создание прокси-сервера, совместимого с API JSON-RPC Bitcoin Core, который посылает некие вызовы посторонним сервисам, но также автоматом инспектирует возвращаемые ими данные, делая запросы к локальному полному узлу. Для примера см. BitGo’s BitGoD software. Эта гибридная модель способна предоставить наилучшее из обоих миров: вы сможете применять расширенные функции, предоставляемые третьими сторонами, сохраняя собственный денежный суверенитет.

    Полные узлы для свободы

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

    Источник

    Оцените статью
    Добавить комментарий