Pages:
Author

Topic: Помогите разобраться с SegWit (Read 1560 times)

sr. member
Activity: 770
Merit: 305
September 19, 2017, 01:15:13 PM
#25
Да, обычный SHA256. У вас хорошая память, что вы всё это в голове держите.
Ну я все-таки анализом блокчейна и транзакций в нем занимаюсь уже больше трех лет.
Можете посмотреть с чего я сам начинал https://bitcointalksearch.org/topic/--461351
 
newbie
Activity: 58
Merit: 0
Quote
Тогда берем сегвит-данные, проверяем что хэш (не помню какой - вроде просто SHA256) от последнего
элемента будет именно таким как надо

Да, обычный SHA256. У вас хорошая память, что вы всё это в голове держите.

До OP_CHECKMULTISIG всё заработо с первого раза) Вау!
https://play.golang.org/p/NIjm1yO4YO

Вернусь с коммандировки, будет мне домашнее задание посчитать мультисигну. И разобраться как формируется сам scriptSig.


sr. member
Activity: 770
Merit: 305
Про завернут внутрь P2SH, это вы про P2WSH реализацию?
Рассмотрим транзакцию.
Удобнее смотреть тут:
https://www.smartbit.com.au/tx/06c543e4f1f2ff6448e2c370078ac80b1d1ab324aa9dbef8db2202313a70c643
там в верхнем-правом углу кнопичка со стрелочками которая разворачивает всё.

Quote
Почему первый элемент txinwitness пустой?
О, это "жук в янтаре".
На заре существования биткойна когда реализовывали OP_CHECKMULTISIG
сделали багу, что эта операция брала из стека на один элемент больше чем
того требовалось. Исправлять уже было нельзя, так как это хард-форк и сплит
сети. Поэтому сперва добавляли "что-нибудь любое", потом договорились, что
всегда этот ненужный элемент будет "пусто"

Quote
Дальше идут две подписи для каждого из ключей (в данном случае мультиподпись из 2-х ключей)
И вконце и дет pubKeyScript который формируется как MultiSigMOfN
Верно?
Угу. Верно.
Логика проверки такая (я на пальцах объясняю, не особо заморачиваясь):
1) scriptPubKey у транзакции
https://www.smartbit.com.au/tx/d91ed6680ad4cef0201a5019c09eaafaa2091be56a767d7d8015d3f471b505e1
OP_HASH160 90211ae4ccee5a308b2ad45481cded4a011aab96 OP_EQUAL

2) scriptSig у https://www.smartbit.com.au/tx/06c543e4f1f2ff6448e2c370078ac80b1d1ab324aa9dbef8db2202313a70c643
0020434ba0752213a5551c8a8f034442076cae04085cda17015eec248017a2c08486

то есть в сумме получается
а) положить на стек 0020434ba0752...
б) взять со стека и проделать хэш-функцию, результат потожить в стек
в) положить в стек 90211ae4cce...
г) взять два элемента со стека, сравнить их, в случае успеха положить 1, иначе 0

Это мы оригинальный концепт рассмотрели. Там всё стыкуется и транзакция валидна
Но. Согласно BIP-16 надо теперь полученную 1 из стека убрать, и исполнить
последний элемент scriptSig

OP_0 434ba0752213a5551c8a8f034442076cae04085cda17015eec248017a2c08486
После его исполнения на стеке два элемента: ноль и вот эта херотень 434ba0752213a5...
По правилам BIP-16 транзакция тоже валидна

Но. Если на стеке два элемента, один из которых ноль, а второй (хотя он первый считая с вершины)
это 32-байтовое число - это сегвит v0.

Тогда берем сегвит-данные, проверяем что хэш (не помню какой - вроде просто SHA256) от последнего
элемента будет именно таким как надо. Все элементы сегвит кроме последнего кладем по порядку на стек
а последний исполняем
Последний элемент это скрипт
OP_2 03b4d8d05ac62e0427357286b412793da1d3e5f731a6251beaa7983de3cf56dbc8 022401777940919353fc3c586799807fc5baddd591fcf6c6629c35a4e354357466 02ec3ffe1bd397fae6c74b1c366a8f3d750a8b1e86c0822dea495820b32447333e OP_3 OP_CHECKMULTISIG

И к моменту его выполнения на стеке лежит элемент-пустышка и две сигнатуры
ну дальше все как обычно
а) кладем 2
б) кладем три публичных ключа
в) кладем 3
г) CHECKMULTISIG вытаскивает из стека "3", потом вытаскивает три публичных ключа, потом
вытаскивает "2", потом вытаскивае две сигнатуры, потом из-за ошибки вытаскивает (но не использует
в дальнейшем) пустышку, потом проверяет чтобы две сигнатуры подходили бы к каким-то
из трех пубкеев и в случае успеха кладет в стек "1" (ну а в случае неуспеха 0, но раз транзакция
в блоке - значит все правильно)





newbie
Activity: 58
Merit: 0
Quote
Сегвит (версии v0) добавляет два стандартных выхода (не помню как называются)
и еще может быть завернут в P2SH

Про завернут внутрь P2SH, это вы про P2WSH реализацию?
Рассмотрим транзакцию.
http://learnmeabitcoin.com/browser/transaction/json.php?txid=06c543e4f1f2ff6448e2c370078ac80b1d1ab324aa9dbef8db2202313a70c643

Почему первый элемент txinwitness пустой?
Дальше идут две подписи для каждого из ключей (в данном случае мультиподпись из 2-х ключей)
И вконце и дет pubKeyScript который формируется как MultiSigMOfN

Верно?
sr. member
Activity: 770
Merit: 305
Quote
Мы немного перепрыгнули BIP-16. Ладно.

Да. Это я на радостях))

Как я понял до BIP16 использовались
P2PK и P2PKH

BIP 16 подарил нам
P2SH
Что в свою очередь очен изменило архитектуру и добавило плюшки вроде MUTLISIG.

А сам SegWit уже в
P2WPK, P2WSH

Нет, немного не так.
Были P2PK и P2PKH и m-of-n MSIG - стандартные выходы
Но уже этот зоопарк из трех вариантов был излишним. Хотелось иметь один вариант, для простоты.
И это был BIP-16 то есть P2SH
Теперь по сути scriptPubkey заносился внутрь scriptSig и может быть практически любым.
А в scriptPubkey оставался только хэш этого скрипта.

Использование P2SH на 99% это мультисигнатурные транзакции
Но, повторюсь, там под капотом может лежать любой скрипт и изредка
встречаются редкие экземпляры.

Для совместимости P2PK и P2PKH и m-of-n MSIG оставили стандартными и доступными
к использованию, но m-of-n MSIG - он очень неудобный, чересчур много места занимает
в базе неизрасходованных выходов, поэтому в последних версиях клиента есть даже настройка
"не считать такой выход стандартным и не майнить его" - такое подталкивание юзеров к тому,
чтобы этим не пользовались.

Сегвит (версии v0) добавляет два стандартных выхода (не помню как называются)
и еще может быть завернут в P2SH
newbie
Activity: 58
Merit: 0
Quote
Мы немного перепрыгнули BIP-16. Ладно.

Да. Это я на радостях))

Как я понял до BIP16 использовались
P2PK и P2PKH

BIP 16 подарил нам
P2SH
Что в свою очередь очен изменило архитектуру и добавило плюшки вроде MUTLISIG.

А сам SegWit уже в
P2WPK, P2WSH
sr. member
Activity: 770
Merit: 305
Да я уже понял что опкоды
01-4B отвечают за копирование данных, указанной длины в стек.
Мне пора брать бабло за репетиторство Smiley

Quote
Ура наконец добрались до txinwitness данных. Как они загружаются в стек и выполняются
предположу что по той же схеме что и скрипты. Но зачем они, какова их суть?
Мы немного перепрыгнули BIP-16. Ладно.
Сегвит решает несколько задач.
1. Он обратно совместим со старым биткойном. То есть не надо пересаживать 100500 юзеров
на новый клиент, что в децентрализованном мире нелегко или даже невозможно. Достаточно
чтобы проголосовали хэш-мощности.
2. Он уменьшает размер транзакции, если считать "по старым правилам". Вкупе с пунктом 1
это дает большую пропускную способность сети.
3. Он устраняет проблемы с пластичностью транзакций, то есть если вы посылаете транзакцию
с каким-то txid то она не сможет подтвердиться с другим txid
4. Самое главное - это позволяет узнать txid до подписывания транзакции.
newbie
Activity: 58
Merit: 0
Да я уже понял что опкоды
01-4B отвечают за копирование данных, указанной длины в стек.

Ура наконец добрались до txinwitness данных. Как они загружаются в стек и выполняются предположу что по той же схеме что и скрипты. Но зачем они, какова их суть?
sr. member
Activity: 770
Merit: 305
Минусы в избыточности данных? Или что-то с безопасностью?

С безопасностью. Если scriptPubkey состоит из N байтов (что внутри неважно, 0 < N < 72), то я scriptSig
сделаю из одного байта со значением N и после конкатенации результирующий скрипт будет
в стек класть сам scriptPubKey - то есть я таким образом могу потратить любой чужой выход

Вот тут есть наша с theymos (это владелец этого форума) дискуссия
https://bitcoin.stackexchange.com/questions/29754/history-behind-the-scripting-language-in-bitcoin
sr. member
Activity: 770
Merit: 305
Транзакция будет считаться валидной, но майнеры её не включат из-за полиси по размеру стека
Ну да.
Именно этот финт я пытался использовать вот тут: https://bitcointalksearch.org/topic/--1759350
Ответ на мой вопрос я хотел получить одним словом: scriptSig может быть любой
в том числе и пустой. После выполнения scriptSig и scriptPubkey на вершине стека остается ненулевой
элемент и транзакция с точки зрения старых клиентов валидна, то есть имеет право жить в блоке.

А новые клиенты имеют костыль - они видят что scriptSig пустой а scriptPubkey имеет определенный формат
и вытаскивают из witness-данных транзакции код и начинают исполнять его тоже.
newbie
Activity: 58
Merit: 0
Спасибо. Так более ясная картинка становится с каждым сообщением.

Quote
Потом Сатоши допёр почему так нельзя делать.

Минусы в избыточности данных? Или что-то с безопасностью?

Quote
Мы к сегвиту уже перешли. Рассматриваем как видит сегвит-транзакции обычная старая нода.

Ура. Но все равно у меня вопрос.

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

scriptHash -> [] -> scriptSigResult(если он есть)

Транзакция будет считаться валидной, но майнеры её не включат из-за полиси по размеру стека
sr. member
Activity: 770
Merit: 305
Разберу оптимистический сценарий
1. Заносим scriptSig в стэк
pubKey->signature
Всё правильно. Только что значит "заносим в стек"? Кто его заносит?
Поймите: scriptSig - это тоже скрипт и его просто выполняют
Когда-то раньше не было ограничений на этот скрипт - можно было любые
конанды использовать. Потом решили что достаточно только пуш-операций.
Остальное тоже можно (вроде софт-форк ограничивающий множество
доступных в scriptSig операций не вводили), но нестандартно.

Quote
Повторяю вопрос. Каким должен быть scriptSig чтобы после выполнения сперва scriptSig а потом этого scriptPubKey
на вершине стека было бы ненулевое число? Ответ - одним словом.

Quote
Что-то тут неясно. Во первых scriptSig - это ж набор параметров, почему он должен выполнятся?
Во вторых чтоб на выходе scriptPubKey было ненулевое число, сценарий должен дойти до конца и вернуть
true. А это значит:

Каждый отдельный скрипт не обязан, чтобы на стеке после его выполнения было ненулевой значение на вершине.
Транзакция считается валидной если после последовательного выполнения scriptSig и scriptPubKey
на вершине стека ненулевое значение. Вам надо понять, что проверка транзакции - это именно что выполнение
scriptSig и scriptPubKey над одним объектом стека. scriptSig туда кладет, scriptPubKey - забирает и проверяет.

В первых версиях биткойна вообще проверка транзакции проходила так, что scriptSig и scriptPubKey склеивались
в один байтовый массив и выполнялись как один скрипт. Потом Сатоши допёр почему так нельзя делать.

Quote
1. scriptSig должен состоять из публичного ключа и сигнатуры
2. сигнатура должна соответсвовать дайджесту
Это только для расходования p2pkh-выходов.
Есть же еще другие типы выходов например pay-to-public-key
в этом случае scriptPubkey OP_CHECKSIG
(когда я пишу в угловых скобках - это значит операция:положить в стек)
и scriptSig соответствующий этому scriptPubkey - это просто

Quote
3. еще и полиси правило про один ненулевой элемент не мешало бы соблюсти.
Как на это ответить одним словом?
Причем тут OP_0 и scripthash?
Мы к сегвиту уже перешли. Рассматриваем как видит сегвит-транзакции обычная старая нода.
newbie
Activity: 58
Merit: 0
Quote
Не-не-не
Вы неправильно поняли мою запись.
OP_DUP OP_HASH160
OP_EQUALVERIFY OP_CHECKSIG - в этом скрипте
значит
"положить 20 байтов в стек" то есть здесь пять операций делается

Разберу оптимистический сценарий

1. Заносим scriptSig в стэк
pubKey->signature

2. Дублируем верхний элемент стека
pubKey->pubKey->signature

3. Находим хеш публичного ключа
pubKeyHash->pubKey->signature

4. Помещаем хеш адреса в стек
addressHash->pubKeyHash->pubKey->signature

5. Сравниваем addressHash и pubKeyHash (функция OP_EQUAL)
true->pubKey->signature

6. Если валидация не прошла помечаем транзакцию как невалидную (процедура OP_VERIFY)
pubKey->signature

7. Проверяем подпись OP_CHECKSIG
true

Quote
Повторяю вопрос. Каким должен быть scriptSig чтобы после выполнения сперва scriptSig а потом этого scriptPubKey
на вершине стека было бы ненулевое число? Ответ - одним словом.

Что-то тут неясно. Во первых scriptSig - это ж набор параметров, почему он должен выполнятся? Во вторых чтоб на выходе scriptPubKey было ненулевое число, сценарий должен дойти до конца и вернуть true. А это значит:

1. scriptSig должен состоять из публичного ключа и сигнатуры
2. сигнатура должна соответсвовать дайджесту
3. еще и полиси правило про один ненулевой элемент не мешало бы соблюсти.

Как на это ответить одним словом?

Причем тут OP_0 и scripthash?


sr. member
Activity: 770
Merit: 305
Так как значения забираются из стека в обратной последовательности, и функция почистит два элемента сигнатуру и публичный ключ,
то в стеке останутся остальные элементы. А первый операнд будет заменён на результат функции.
Предположу что да, транзакция будет валидной при условии соответсвия адреса и сигнатуры
Да. Лучше конечно называть "элемент на вершине стека", а то непонятно откуда мы считаем.
Транзакция валидна, но майнеры её не включат, так как по полиси-правилам (это нестрогое правило)
на стеке должен остаться только один ненулевой элемент.

Quote
По идее на первом обращении к функции, так как количество аргументов отличается от задекларированного.
Ну или как вариант если аргументы динамические то OP_EQUALVERIFY так как до OP_CHECKSIG  не дойдёт очередь.
Почему не дойдет? Проверка необходимого числа элементов в стеке происходит при выполнении каждой команды
Если в scriptSig только публичный ключ - то OP_EQUALVERIFY сработает, а OP_CHECKSIG сломается - ему
надо два аргумента, а в стеке только один
Если в scriptSig вообще пусто - то сломается на OP_DUP

Quote
OP_0 - добавляет пустой массив в стек.
Значит scripthash любой отличный от нуля. Ненулевое значение в стеке будет если scriptPubkey вернёт не ноль.
Не-не-не
Вы неправильно поняли мою запись.
OP_DUP OP_HASH160
OP_EQUALVERIFY OP_CHECKSIG - в этом скрипте
значит
"положить 20 байтов в стек" то есть здесь пять операций делается

OP_0 - тут две операции - положить в стек пустой массив
и положить в стек 20 байт (или 32 байта - я ведь не указал сколько разрядов у scripthash)
(Вероятность того, что результат хэш-функции нулевой настолько мала, что это можно не упоминать специально)
Но это scriptPubkey
Повторяю вопрос. Каким должен быть scriptSig чтобы после выполнения сперва scriptSig а потом этого scriptPubKey
на вершине стека было бы ненулевое число? Ответ - одним словом.

newbie
Activity: 58
Merit: 0
Прекрасно. Половина дела сделана. Базу вы как парсите? Дергаете клиент за API
или самостоятельно открываете  читаете blk-файлы?
За API, до blk формата файлов я еще не дошел. Но предположу что там тоже levelDb и на выходе будет просто сырые данные, которые после преобразования приймут структуру подобную json дереву из примеров.
http://learnmeabitcoin.com/browser/transaction/06c543e4f1f2ff6448e2c370078ac80b1d1ab324aa9dbef8db2202313a70c643

Задание на проверку навыков. Что если scriptSig состоит не из двух, а из трех и более элементов?
последний - это публичный ключ, предпоследний - валидная сигнатура, а остальные - какие-либо
другие? Что будет в стеке после выполнения? Будет ли транзакция валидной? Подтвердят ли её майнеры?

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

И второе задание на проверку навыков: а если в scriptSig  будет одна или ноль пуш-операций?
На какой команде произойдет сбой выполнения?

По идее на первом обращении к функции, так как количество аргументов отличается от задекларированного. Ну или как вариант если аргументы динамические то OP_EQUALVERIFY так как до OP_CHECKSIG  не дойдёт очередь.

Каким должен быть scriptSig
чтобы после последовательного выполнения scriptSig и scriptPubkey наверху стека
оказалось бы ненулевое значение.

OP_0 - добавляет пустой массив в стек.
Значит scripthash любой отличный от нуля. Ненулевое значение в стеке будет если scriptPubkey вернёт не ноль.
sr. member
Activity: 770
Merit: 305
Все адреса из блокчейна вытащил) Вначале пробовал в MySQL на PHP, но получилось сильно долго и
много места. Более компактно и быстро получилось с levelDb и хранением адресов в бинарном виде.
Прекрасно. Половина дела сделана. Базу вы как парсите? Дергаете клиент за API
или самостоятельно открываете  читаете blk-файлы?

Quote
Я ведь правильно понимаю? Что раньше скрипт разблокировки включался в выход транзакции.
Сейчас там содержится только хеш Меркля (P2SH), само дерево представляет из себя возможные
Ой-вей. Всё смешалось в доме Облонских.
Меркля забудьте. И не вспоминайте. Этот хэш вообще из другой оперы.

Есть несколько "разновидностей" использования сегвита.
Два (по-моему) нативных и два завернутых в P2SH

Начнем с нативных.
А, не, давайте вспомним сперва как работает самый популярный p2pkh

scriptPubKey = OP_DUP OP_HASH160
OP_EQUALVERIFY OP_CHECKSIG
такой скрипт в обычных условиях вернет в стеке "1" если в scriptSig будет два пуш-элемента:
сигнатура и публичный ключ. Причем хэш публичного ключа (не Меркль, а посчитанный
по-биткойновски) должен быть равным адресу (иначе OP_EQUALVERIFY бросит исключение),
а сигнатура должна правильно подписывать подписывать дайджест (иначе OP_CHECKSIG вернет
"0" или вообще бросит исключение)

Задание на проверку навыков. Что если scriptSig состоит не из двух, а из трех и более элементов?
последний - это публичный ключ, предпоследний - валидная сигнатура, а остальные - какие-либо
другие? Что будет в стеке после выполнения? Будет ли транзакция валидной? Подтвердят ли её майнеры?

И второе задание на проверку навыков: а если в scriptSig  будет одна или ноль пуш-операций?
На какой команде произойдет сбой выполнения?

Теперь переходим к нативным.
Я по памяти буду писать. Идею изложу, но могу где-то напутать.
Нативный pubkeyScript имеет вид OP_0
Про сегвит пока забыли. Давайте проверим навыки. Каким должен быть scriptSig
чтобы после последовательного выполнения scriptSig и scriptPubkey наверху стека
оказалось бы ненулевое значение. (ответ на этот вопрос можно высказать одним словом)
newbie
Activity: 58
Merit: 0
Пока будете разбираться - как раз и поймете как выглядят транзакции и
что такое bip16 и segwit

Хорошо знаю PHP и PureBasic
Немного хуже Go

Все адреса из блокчейна вытащил) Вначале пробовал в MySQL на PHP, но получилось сильно долго и много места. Более компактно и быстро получилось с levelDb и хранением адресов в бинарном виде.

Да именно такую задачу я перед собой и ставлю. Разобраться и попробовать реализовать segWit самому. Но для того чтоб сделать, нужно вначале понять как это сделать)

Я ведь правильно понимаю? Что раньше скрипт разблокировки включался в выход транзакции. Сейчас там содержится только хеш Меркля (P2SH), само дерево представляет из себя возможные вариации скрипта (для мультиподписи или блокировки по времени к примеру). Дальше в следующей транзакции на вход добавляется cамо тело скрипта который сработал, и используя рутовый хеш из предыдущего выхода, можно проверить находился ли этот скрипт где-то в хешируемом дереве. Но это всё в теории из того что я смог понять. И тут у меня ступор, ведь на практике если взять segWit транзакцию

http://learnmeabitcoin.com/browser/transaction/json.php?txid=06c543e4f1f2ff6448e2c370078ac80b1d1ab324aa9dbef8db2202313a70c643

То scriptSig - это тело скрипта, или очередной хеш? И что такое txinwitness

P.S.
Как оно работает брал отсюда
https://bits.media/news/sleduyushchiy-etap-po-uluchsheniyu-bitkoina-nazyvaetsya-mast/



sr. member
Activity: 770
Merit: 305
К сожалению мой уровень английского крайне плох также как и знание С++.  Поэтому
я больше путаюсь в переводах. А все что вы мне говорите мне понятно. Спасибо вам
за это. Пробовал разобраться самостоятельно в исходниках, но там черт ногу сломит.
Вся логика размазана по абстрактным слоям
А не надо читать чужие исходники.
Сделайте свои. Конечно, надо хоть один язык программирования знать.
Бейсик и Паскаль тоже подойдут кстати.
Возьмите простую задачу, допустим в файл распечатать все адреса из блокчейна.
(будем считать что блокчейн уже скачан)
Пока будете разбираться - как раз и поймете как выглядят транзакции и
что такое bip16 и segwit
newbie
Activity: 58
Merit: 0
Ладно, смысл в том, что пока вы не поймете в чем суть BIP-16 вы о сегвите не поймёте
Я вас только запутаю

К сожалению мой уровень английского крайне плох также как и знание С++.  Поэтому я больше путаюсь в переводах. А все что вы мне говорите мне понятно. Спасибо вам за это. Пробовал разобраться самостоятельно в исходниках, но там черт ногу сломит. Вся логика размазана по абстрактным слоям
sr. member
Activity: 770
Merit: 305
у входа scriptSig это результат подписи публичного ключа с опкодом подписи, приватным ключом подтверждающим владение кошельком
Я это увидел где-то так
Code:
scriptSig = sign(pubkey + OP_CHECKSIG, privKey), 

Не в этом суть.
есть scriptPubKey - это некоторая функция
есть scriptSig - по сути дела это параметры передающиеся в функцию
валидация проходит если scriptPubKey ( scriptSig ) = 1
Это оригинальный концепт.

Потом подумали - а нахер нам иметь разные функции? давайте сделаем одну
но будем выполнять её хитро. То есть выполнение такое
return scriptPubKey ( scriptSig ) == 1  && executeLast ( scriptSig ) == 1
условно говоря, сперва выполняется по-старому алгоритму завещанному сатоши,
а потом еще выполняется сам последний операнд
при этом выполняются всякие проверки подписей.
Это BIP-16

А потом еще подумали и решили, а давайте если последний операнд имеет определенный формат,
то будем еще одну проверку делать, а сам код этой проверки вынесем в другое место?

Ладно, смысл в том, что пока вы не поймете в чем суть BIP-16 вы о сегвите не поймёте
Я вас только запутаю

Pages:
Jump to: