ОРИГИНАЛЬНАЯ СТАТЬЯ
ПЕРЕВЕДЕНО СПЕЦИАЛЬНО ДЛЯ XSS.IS
Транзакции Bitcoin и Litecoin считаются "анонимными", поскольку не требуют идентификации. Однако, как только адрес биткоина раскрывается, все связанные с ним транзакции становятся прозрачными. В этой статье рассказывается о том, как модель Unspent Transaction Output (UTXO) используется обеими криптовалютами для отслеживания исторических объемов данных, и как анализ блокчейна может быть использован для идентификации сторон, участвующих в транзакции. Кроме того, в статье рассматриваются методы обфускации, которые могут усложнить отслеживание транзакций в блокчейне для посторонних.
Биткойн - неуправляемое казино.
" Не уверен, что "накачка и сброс" биткоина Элоном Маском является технически незаконной или мошенничеством с ценными бумагами. Но очень подозрительно что тот, кто якобы совершает революцию в области энергопотребления и внедряет инновации в космические путешествия, по идее, должен быть выше этого. "
- Арпит Гупта (@arpitrage) 17 мая 2021 г.
Протокол Биткойн был настолько популярен, что им заинтересовались широкие слои населения. К сожалению, большинство из этих людей пришли не для того, чтобы воспользоваться преимуществами одноранговой псевдо-анонимной денежной системы, а для того, чтобы извлечь выгоду из ее неустойчивой стоимости и нерегулируемой торговли, которая часто связана с "накачкой и сбросом" или другими теневыми схемами в попытке быстро заработать. Такая популярность привела к высокому росту транзакций, но блокчейн Биткойна способен обрабатывать только 1 МБ данных транзакций в каждом блоке, который добывается примерно каждые 10 минут в зависимости от сети. Транзакции могут транслироваться за плату, так как майнеры предпочитают наиболее выгодные транзакции, что приводит к высоким комиссиям из-за постоянной потребности пользователей в транзакциях. Средний размер транзакции составляет около 224 байт, то есть блок размером 1 МБ (1.048.576 байт) может содержать примерно 4681 транзакцию, которые будут обработаны в среднем за 10 минут, или около 7,8 транзакций каждую секунду. Ограниченность размера блока является причиной того, что плата за транзакции стала такой высокой за последние несколько лет. На момент написания статьи комиссия за транзакцию составляет около 102 сатоши за байт, тогда как в старые добрые времена я мог получить всего 3-4 сатоши за байт. В среднем комиссия изменилась с всего лишь 0,02$ до 0,65$. В неудачный день вы можете обнаружить, что платите несколько (десятков) долларов за то, чтобы вас взяли майнеры.
Поприветствуйте Litecoin
Биткойн-сообщество придумало несколько интересных технологий, чтобы справиться с этой проблемой масштабируемости. Некоторые из этих решений - SegWit, Taproot и Lightning Network. Однако мое "решение" этой проблемы заключается в том, чтобы просто использовать другой блокчейн. Я выбрал проект Litecoin, это один из первых форков Bitcoin, и, похоже, он получил хорошую поддержку в сообществах. Пока что я буду придерживаться биткоинов как средства стоимости и использовать Litecoin в качестве промежуточного звена для денежных операций.
Актуальная проблема
На протяжении всего исследования я буду смешивать Bitcoin и Litecoin, поскольку они основаны на одной и той же кодовой базе и имеют одну и ту же проблему. Основное различие заключается в том, что Litecoin - это не биткоин, так как Litecoin осуществляют транзакции на блокчейне Litecoin. Проблемы, с которыми я сталкиваюсь в связи с псевдоанонимностью, остаются теми же, поскольку технология блокчейн в основе своей одинакова для обеих цепочек. На самом деле проблема, с которой я сталкиваюсь, связана с тем, как биткойн работает в качестве одноранговой "наличности". Все прозрачно, поскольку публично зарегистрировано в блокчейне. Причина, по которой это все еще "анонимно", заключается в том, что для начала использования протокола Bitcoin не требуется KYC или других видов идентификации. Все, что требуется, - это немного криптографии для генерации открытого ключа (адреса) и закрытого ключа, и вы готовы получать и создавать транзакции Bitcoin без каких-либо вопросов. Все происходит анонимно до тех пор, пока вы не раскроете свой Bitcoin-адрес. Другими словами, если вы отправляете или получаете средства, сторона, с которой вы проводите транзакцию, узнает ваш адрес и может посмотреть все в блокчейне, чтобы увидеть ваши исторические данные, и даже может продолжить отслеживать ваши адреса для получения новых данных. (например, чтобы узнать, как или когда вы отправляли средства).
О транзакции в двух словах
Биткойн и Litecoin используют модель Unspent Transaction Output (UTXO), которая использует "входы" и "выходы" для отслеживания исторических объемов данных. Идея заключается в том, что один адрес может получить несколько выходов с определенной суммой внутри них. Эти данные могут быть использованы только один раз, именно поэтому существует " возвратный адрес". Допустим, у вас есть 10 биткойнов, и вы хотите отправить Бобу 1 биткойн. Для этого вы отправите 1 Биткойн Бобу, а остальные 9 отправите обратно себе, так как вы должны израсходовать всю стоимость данного выхода. Теперь вы и Боб владеете новым уникальным значением, содержащим 9 биткойнов и 1 биткойн соответственно. Вывод 10 биткойнов, использованный в транзакции, теперь помечен как "потраченный" и больше не может быть использован в дальнейших транзакциях. (если только вы не проведете атаку "двойной траты").
Анализ блокчейна
Изображение иллюстрирует поток монет в средних транзакциях, подобных вышеупомянутой, где две стороны совершают сделки с Litecoins. Хорошей практикой является создание нового адреса и использование его в качестве обратного адреса, чтобы сбить с толку любого, кто рассматривает транзакцию без контекста. Например, посторонний человек не сможет отличить " возвратный адрес" и получателя, однако можно догадаться, что была проведена транзакция на сумму либо 1 Litecoin, либо 9 Litecoin, а остаток находится у предыдущего владельца под новым адресом.
Рассматривая только одну транзакцию, можно сделать лишь предположение, что отправитель может владеть ни единым, ни одним, ни двумя адресами. Чтобы получить более точный результат, мы должны проанализировать больше данных о транзакциях и выполнить прием, известный как "анализ консолидации UTXO".
Идея анализа консолидации заключается в том, что если у вас нет необходимого количества в одном выводе, вам придется использовать какой-то иной вывод. Например, допустим, у Боба есть 1 Litecoin, и он хочет отправить 2 Litecoin в книжный интернет-магазин. Для этого Боб может использовать 1 Litecoin, которым он уже владеет, но ему понадобится еще один источник, чтобы восполнить недостающий 1 Litecoin.
Предположим, что Боб сообщил нам о новой книге, которую он хочет приобрести в Интернете за 2 Litecoin. Посмотрев на поток монет новой транзакции, мы видим, что Боб использовал наш 1 Litecoin и еще 1 Litecoin с неизвестного адреса (названного Unknown 1). Теперь мы можем предположить, что Боб уже владел 1 Litecoin до получения 1 Litcoin, который мы отправили, и теперь мы можем провести анализ, чтобы узнать, откуда взялся первый Litecoin Боба. (Дальнейший анализ Litecoin Боба невозможен, поскольку все Litecoin были потрачены на покупку книги, и мы остаемся в тупике).
Обфускация
Боб может не беспокоиться о своей недавней покупке в книжном магазине, однако он не хочет, чтобы кто-то знал, сколько у него Litecoins. У Боба есть свои причины, не задавайте вопросов о причинах Боба. Боб говорит, что нормальные люди не кричат о том, сколько денег у них в их (традиционных) банках, Боб также любит быть скромным, но, к сожалению, блокчейн создан не для этого.
Чтобы скрыть данные о своих транзакциях в Blockchain, Боб будет использовать так называемые микшеры. Идея микшеров заключается в том, что ваши монеты смешиваются с другими участниками, и через некоторое время вы (надеюсь) получаете монеты обратно, но с рандомизированными транзакциями, чтобы запутать анализ блокчейна.
К сожалению, у Боба, как и у многих других, есть серьезные проблемы с доверием. Боб не собирается отправлять деньги на неизвестную онлайн-платформу в надежде получить свои деньги обратно. Вся система блокчейн была создана для того, чтобы не вызывать доверия, поскольку транзакции с несколькими подписями - это вещь. Именно поэтому Боб наткнулся на технологию под названием "CoinJoin" - технологию "смешивания монет" с нулевым доверием, которая запутывает поток монет и может даже уменьшить размер транзакций.
Что такое CoinJoin
Оригинальная концепция CoinJoin была предложена пользователем 'gmaxwell' на форумах Bitcointalk. Идея заключается в том, что традиционная транзакция "один к одному" заменяется на "несколько к нескольким". Возьмем предыдущий пример, где только вы совершали денежные операции, и добавим к ним второго человека, Алису. Алиса сказала, что ей нужно отправить 1 Litecoin со своего адреса "X" на другой адрес "Y".
Мы перенесемся в прошлое и вместо того, чтобы отправить Бобу 1 Litecoin в транзакции "один на один", мы проведем транзакцию с несколькими подписями. Вы отправите Бобу 1 из 10 Litecoin, но в то же время Алиса отправит свой 1 из 2,5 Litecoin на адрес, который она указала как 'X'. Алисе не нужно доверять вам, поскольку вы владеете только 1 (из 2) ключами для завершения транзакции, поэтому Алиса получит частично подписанную транзакцию и (по желанию) расшифрует ее, чтобы проверить, куда отправляются ее деньги. Когда она убедится, что подписала транзакцию и подписала ее последней, она передаст ее в сеть Litecoin.
Изображение иллюстрирует транзакцию с несколькими подписями, в которой участвовали и вы, и Алиса, чтобы отправить 1 Litecoin Бобу, 1 Litecoin X, 1,5 Litecoin в ответ Алисе и 9 Litecoin в ответ вам. Даже без меток можно увидеть оба обратных адреса, однако транзакции на 1 Litecoin Бобу или X неразличимы, если не наклеивать никаких меток. Делая выходы с одинаковой суммой (1 Litecoin в данном случае), уже невозможно увидеть, кто чем владеет.
Отправила ли Алиса 1 Litecoin другому человеку? Или Алиса владеет 1 X? А для третьей стороны, которая ничего не знает о Бобе, кто кому отправил этот 1 Litecoin?
Разбор реального примера
На приведенном ниже изображении показан реальный пример, опубликованный в блокчейне Биткойна. Два адреса, владеющие 0,00012 BTC и 0,00015 BTC, совершили транзакции на 4 перевода. Два из этих переводов одинаковы (0,0001 BTC), а два других уникальны, поскольку, скорее всего, являются обратными адресами обоих участников.
Интересно отметить, что сумма не складывается.
Total input (0.0001200 + 0.0001500): 0.0001700
Total output (0.0001134 + 0.0001501): 0.0001635
Первое, что мы замечаем, - это несоответствие общего выхода общему входу. В отличие от нашего теоретического примера, разница между общим входом и общим выходом есть, так как она уходит на комиссию за транзакцию.
0.0001000 + 0.0000134 = 0.0001134
0.0001000 + 0.0000501 = 0.0001501
Кроме того, мы видим, что результаты тоже не сходятся. Мы можем предположить, что 2 адреса, участвовавшие в транзакции, получают по 2 выхода, что соответствует 4 выходам. Если мы возьмем адрес 0.0001 и сложим его с обратным адресом, то увидим заметную разницу.
Предполагается, что владелец, отправляющий 0.0001500, теперь владеет 0.0001501, мы просто не знаем, какой из выходов 0.0001000 принадлежит ему. Предполагается, что владелец, посылающий 0.0001200, теперь владеет 0.0001134, что намного меньше. Скорее всего, потому что 0,0001200 используется для оплаты сетевых сборов, а во-вторых, платит (очень низкую) комиссию от 0,0000001 до 0,0001500 за смешивание активов.
Создание CoinJoin
Теперь, когда у нас есть полное понимание того, что нужно делать, мы можем сразу же перейти к нашей IDE и начать строить решение, основанное на этой идее. Как вы, возможно, уже знаете, я большой поклонник C# и поэтому буду использовать C# в сочетании с популярной библиотекой NBitcoin.
Забегая вперед, я создал на GitHub репозиторий MultiSigTransaction, который содержит несколько вспомогательных классов для добавления, удаления и обновления так называемых "участников", которые могут быть назначены на "группу", созданную "GroupManager".
Используя эти вспомогательные классы, мы можем легко создать транзакцию с несколькими подписями, используя приведенный ниже код.
C#:
// Create a group that agrees on 600 satoshi output
GroupManager GroupManager = new GroupManager();
decimal amount = 600;
Group testGroup = GroupManager.CreateNewGroup("test", amount);
// Add 2 participants
Participant Alice = new Participant("Alice");
testGroup.AddParticipant(Alice);
Participant Bob = new Participant("Bob");
testGroup.AddParticipant(Bob);
// Alice configuration
Alice.UpdateMainAddress("bc1qrk259cv8m7hgcejqyw2g8772ngfmc6n32hu4gx"); // Alice send addr
Alice.UpdateReturnAddress("bc1qrk259cv8m7hgcejqyw2g8772ngfmc6n32hu4gx"); // Alice recv addr (same as main for now)
Alice.AddOutputAddress("3LFaWZ1zoxzAXkG94E5Hw5PfjnhQz2aeMR", amount); // Alice sends 600 sats to target
bool readyA = Alice.Ready(true);
if (!readyA)
{
Console.WriteLine("Alice failed getting ready");
return;
}
// Bob configuration
Bob.UpdateReturnAddress("bc1qq2g23nufzygkgc78rzpsghmx0egvfr4wkf6n3u");
Bob.UpdateMainAddress("bc1qq2g23nufzygkgc78rzpsghmx0egvfr4wkf6n3u");
Bob.AddOutputAddress("3H9LV7w89mqWP4HTjGtRamvbdhRr72KXXh", amount);
bool readyB = Bob.Ready(true);
if (!readyB)
{
Console.WriteLine("Bob failed getting ready");
return;
}
bool canStart = testGroup.CanMultiSig();
if (!canStart)
{
Console.WriteLine("Something wrong on group signing!");
return;
}
// start mult-ish
testGroup.StartMiltiSig();
bool isFinished = testGroup.IsFinishedSigning();
if(!isFinished)
{
Console.WriteLine("Failed finalising the group");
}
// The current raw (unsigned) transaction
string rawTranscationHex = testGroup.CurrentTransaction.ToHex();
Console.WriteLine(testGroup.DebugLog);
Console.WriteLine("Done!");
Я не буду вдаваться в подробности, поскольку здесь много специфического для C#, но после выполнения этого фрагмента переменная rawTranscationHex должна дать нам следующее:
Код:
0100000002a7ab1a4cd06fed32f231936cb205caa8a323ffdb3dfe8682ab3a5e33e218a88e0100000000ffffffffa7ab1a4cd06fed32f231936cb205caa8a323ffdb3dfe8682ab3a5e33e218a88e0300000000ffffffff03580200000000000017a914cb9ac6d00534e4595960b77259678296c9094b1887580200000000000017a914a984323e2d9b262fda7694cdeddcef3ac3ce204c87b00e0000000000001600140290a8cf8911116463c71883045f667e50c48eae00000000
Сначала это кажется довольно скучным, но мы можем расшифровать это с помощью команды decoderawtransaction в кошельке Bitcoin Core, чтобы получить следующий вывод JSON
JSON:
{
"txid": "b5e757cb0a310cce731f184388cac1cf6f82f032067bcda7e108391810e05a71",
"hash": "b5e757cb0a310cce731f184388cac1cf6f82f032067bcda7e108391810e05a71",
"version": 1,
"size": 187,
"vsize": 187,
"weight": 748,
"locktime": 0,
"vin": [
{
"txid": "8ea818e2335e3aab8286fe3ddbff23a3a8ca05b26c9331f232ed6fd04c1aaba7",
"vout": 1,
"scriptSig": {
"asm": "",
"hex": ""
},
"sequence": 4294967295
},
{
"txid": "8ea818e2335e3aab8286fe3ddbff23a3a8ca05b26c9331f232ed6fd04c1aaba7",
"vout": 3,
"scriptSig": {
"asm": "",
"hex": ""
},
"sequence": 4294967295
}
],
"vout": [
{
"value": 0.00000600,
"n": 0,
"scriptPubKey": {
"asm": "OP_HASH160 cb9ac6d00534e4595960b77259678296c9094b18 OP_EQUAL",
"hex": "a914cb9ac6d00534e4595960b77259678296c9094b1887",
"address": "3LFaWZ1zoxzAXkG94E5Hw5PfjnhQz2aeMR",
"type": "scripthash"
}
},
{
"value": 0.00000600,
"n": 1,
"scriptPubKey": {
"asm": "OP_HASH160 a984323e2d9b262fda7694cdeddcef3ac3ce204c OP_EQUAL",
"hex": "a914a984323e2d9b262fda7694cdeddcef3ac3ce204c87",
"address": "3H9LV7w89mqWP4HTjGtRamvbdhRr72KXXh",
"type": "scripthash"
}
},
{
"value": 0.00003760,
"n": 2,
"scriptPubKey": {
"asm": "0 0290a8cf8911116463c71883045f667e50c48eae",
"hex": "00140290a8cf8911116463c71883045f667e50c48eae",
"address": "bc1qq2g23nufzygkgc78rzpsghmx0egvfr4wkf6n3u",
"type": "witness_v0_keyhash"
}
}
]
}
Мы видим, что выделенные участки показывают количество Биткойнов, отправляемых на соответствующие выходные адреса. Для завершения транзакции каждый участник должен подписать транзакцию. Я делаю это с помощью команды Bitcoin Core walletpassphrase "mypassword" 60, чтобы разблокировать кошелек, а затем signrawtransactionwithwallet, чтобы подписать транзакцию.
В данном случае я владею обоими входами и могу подписать транзакцию самостоятельно, результат приведен ниже.
Код:
01000000000102a7ab1a4cd06fed32f231936cb205caa8a323ffdb3dfe8682ab3a5e33e218a88e0100000000ffffffffa7ab1a4cd06fed32f231936cb205caa8a323ffdb3dfe8682ab3a5e33e218a88e0300000000ffffffff03580200000000000017a914cb9ac6d00534e4595960b77259678296c9094b1887580200000000000017a914a984323e2d9b262fda7694cdeddcef3ac3ce204c87b00e0000000000001600140290a8cf8911116463c71883045f667e50c48eae02473044022074c999c6a4f758d4c841507feaa91014066e2dc6177e1c11362573d5019d272402203646e1e781b12912a017c81fc349bf4287789a739f14f2aa4bf5ce3064442153012102fbded889a1f26d5b362977ddeb508c7a586cdaca8893b82ca4b9be67cf7da9e002473044022023ce79f494e6e78a67e3c47269da0db414381e8b8b81bf403ad74046c24c285e022023b02c0405015e6f8b2d07dfde0125b3e8eea40f15b4621f193cb38bbc52727a012103c48926b53c84327780f935c574525906e6de0c87981177d5fa7a953e0e0c248e00000000
Эти байты могут выглядеть бессмысленными, но эта транзакция была подписана, и любой, включая вас, может взять подписанную транзакцию и распространить ее по сети. (например, этот сетевой tx pusher может передать любую подписанную транзакцию для вас). Не стесняйтесь делать это, поскольку я совершил эту транзакцию в образовательных целях. Другими словами, плата за транзакцию устанавливается очень низкой, поэтому она не будет подхвачена сетью и либо "застрянет" в мемпуле, либо будет ждать повторной трансляции.
В реалистичном варианте транзакция сначала была бы создана с разумными комиссионными за транзакции, а затем транслировалась бы последним пользователем, подписавшим ее. После этого сеть подхватит ее в любом из новых добытых блоков, и транзакции будут завершены.
Заключение
Мы рассмотрели, как псевдоанонимность не соответствует потребностям повседневных пользователей, и рассмотрели транзакции с несколькими подписями, чтобы иметь объединенную группу участников для совершения денежных операций. Каждый участник должен согласиться отправить точно такую же сумму, чтобы сохранить транзакцию в тайне. Этот тип транзакции часто называют "CoinJoin", и он доказал свою эффективность при условии, что участники следуют надлежащей практике (например, не объединяют монеты), чтобы сохранить свои монеты в тайне. В реалистичном сценарии транзакция сначала создается с разумными транзакционными сборами, а затем транслируется последним пользователем, который ее подписывает. После этого сеть подхватит ее в любом из новых добытых блоков, и транзакции будут завершены.
С учетом сказанного, похоже, что единственной проблемой остается поиск других людей, желающих принять участие в такой совместной транзакции, и соблюдение определенного набора правил, чтобы не ослабить замаскированную транзакцию.