Как используется OP_RETURN и почему он вообще был введен?
Примечание. Я вышел и узнал, как OP_RETURN
код операции работает на уровне байтов в биткойн-транзакциях. Я пишу это здесь, чтобы другие могли быстро изучить. Во-первых, краткая история того, почему мы вообще говорим о OP_RETURN
.
Еще в 2013 году различные игроки в биткойн-экосистеме пытались включать в транзакции биты информации, чтобы воспользоваться преимуществами необратимости блокчейна. Представьте, например, что вы хотите написать контракт и поместить его в неизменяемое место, чтобы в любой момент в будущем можно было вернуться, чтобы убедиться, что он существует. Вы можете сделать это, используя блокчейн. Вы добавляете некоторые биты к значению scriptSig транзакции, которые не изменяют конечный результат запуска этого скрипта, но позволяют вам хранить информацию, такую как «Настоящим я заявляю, что передаю актив A по адресу XYZ во время UNIX_TIMESTAMP». Были и еще более странные способы, которыми люди добавляли дополнительные биты, например, включение их в значение BTC вывода. Некоторым членам сообщества это не понравилось, так как они увидели, что эти лишние биты загрязняют блокчейн.
Чтобы достичь золотой середины в этих противоположных взглядах, основные разработчики сделали код операции OP_RETURN действительным кодом операции для использования в транзакции биткойнов, что позволяет использовать 80 произвольных байтов в транзакции, которую нельзя потратить. Хорошее объяснение этому можно найти здесь:
https://bitcoinfoundation.org/bitcoin/core-development-update-5/
Позже, в феврале 2014 года, количество байтов было уменьшено с 80 до 40 байт. Это изменение задокументировано по ссылке ниже. Обратите внимание, что в этом обсуждении извлечения мы узнали, что в одну транзакцию можно включить не более одного вывода с OP_RETURN:
https://github.com/bitcoin/bitcoin/pull/3737
Теперь, когда мы выяснили причину отказа OP_RETURN, давайте рассмотрим пример OP_RETURN. Я использовал API chain.com, чтобы найти транзакцию, которая имеет OP_RETURN в своем scriptSig. Хэш этого tx
8bae12b5f4c088d940733dcd1455efc6a3a69cf9340e17a981286d3778615684
Убедитесь, что вы подключены к полностью загруженному узлу bitcoind, и выполните следующую команду:
$> bitcoind getrawtransaction 8bae12b5f4c088d940733dcd1455efc6a3a69cf9340e17a981286d3778615684 1
который даст вам этот вывод:
{
"hex" : "0100000001c858ba5f607d762fe5be1dfe97ddc121827895c2562c4348d69d02b91dbb408e010000008b4830450220446df4e6b875af246800c8c976de7cd6d7d95016c4a8f7bcdbba81679cbda242022100c1ccfacfeb5e83087894aa8d9e37b11f5c054a75d030d5bfd94d17c5bc953d4a0141045901f6367ea950a5665335065342b952c5d5d60607b3cdc6c69a03df1a6b915aa02eb5e07095a2548a98dcdd84d875c6a3e130bafadfd45e694a3474e71405a4ffffffff020000000000000000156a13636861726c6579206c6f766573206865696469400d0300000000001976a914b8268ce4d481413c4e848ff353cd16104291c45b88ac00000000",
"txid" : "8bae12b5f4c088d940733dcd1455efc6a3a69cf9340e17a981286d3778615684",
"version" : 1,
"locktime" : 0,
"vin" : [
{
"txid" : "8e40bb1db9029dd648432c56c295788221c1dd97fe1dbee52f767d605fba58c8",
"vout" : 1,
"scriptSig" : {
"asm" : "30450220446df4e6b875af246800c8c976de7cd6d7d95016c4a8f7bcdbba81679cbda242022100c1ccfacfeb5e83087894aa8d9e37b11f5c054a75d030d5bfd94d17c5bc953d4a01 045901f6367ea950a5665335065342b952c5d5d60607b3cdc6c69a03df1a6b915aa02eb5e07095a2548a98dcdd84d875c6a3e130bafadfd45e694a3474e71405a4",
"hex" : "4830450220446df4e6b875af246800c8c976de7cd6d7d95016c4a8f7bcdbba81679cbda242022100c1ccfacfeb5e83087894aa8d9e37b11f5c054a75d030d5bfd94d17c5bc953d4a0141045901f6367ea950a5665335065342b952c5d5d60607b3cdc6c69a03df1a6b915aa02eb5e07095a2548a98dcdd84d875c6a3e130bafadfd45e694a3474e71405a4"
},
"sequence" : 4294967295
}
],
"vout" : [
{
"value" : 0.00000000,
"n" : 0,
"scriptPubKey" : {
"asm" : "OP_RETURN 636861726c6579206c6f766573206865696469",
"hex" : "6a13636861726c6579206c6f766573206865696469",
"type" : "nulldata"
}
},
{
"value" : 0.00200000,
"n" : 1,
"scriptPubKey" : {
"asm" : "OP_DUP OP_HASH160 b8268ce4d481413c4e848ff353cd16104291c45b OP_EQUALVERIFY OP_CHECKSIG",
"hex" : "76a914b8268ce4d481413c4e848ff353cd16104291c45b88ac",
"reqSigs" : 1,
"type" : "pubkeyhash",
"addresses" : [
"1HnhWpkMHMjgt167kvgcPyurMmsCQ2WPgg"
]
}
}
],
"blockhash" : "000000000000000004c31376d7619bf0f0d65af6fb028d3b4a410ea39d22554c",
"confirmations" : 2655,
"time" : 1404107109,
"blocktime" : 1404107109
}
Теперь посмотрите на список выходов этой транзакции, в частности на 1-й. Ссылаясь на страницу Биткойн Вики, посвященную Script , основанному на стеке языку программирования Биткойн, мы можем видеть здесь, что OP_RETURN
код операции представлен шестнадцатеричным значением 0x6a. За этим первым байтом следует байт, представляющий длину остальных байтов в scriptPubKey. В данном случае мы видим шестнадцатеричное значение Ox13, что означает наличие еще 19 байт. Эти байты составляют произвольные менее 40 байтов, которые вам разрешено отправлять в транзакции, отмеченной OP_RETURN
кодом операции. Если вы вставите байты сообщения в декодер UTF8, вы увидите, что
636861726c6579206c6f766573206865696469
становится «Чарли любит Хайди». Ой! Это почти как цифровая версия романтической резьбы по дереву сердца пары. Теперь вы понимаете на уровне байтов, как OP_RETURN
это должно работать. Теперь вы можете написать программное обеспечение, которое ищет OP_RETURN
код операции в выходном файле scriptPubKey и использует его для проверки контракта или другого цифрового актива.
Если вы хотите записать OP_RETURN в блокчейн, не вникая во внутренности построения транзакций, простой способ — использовать наши библиотеки для PHP и Python:
https://github.com/coinspark/php-OP_RETURN
https://github.com/coinspark/python-OP_RETURN
Они поддерживают либо отправку отдельных транзакций с одним прикрепленным OP_RETURN, либо отправку пакета связанных транзакций для встраивания больших фрагментов контента. Затем этот контент может быть извлечен из блокчейна с использованием одного идентификатора.
Предполагая, что вы используете Bitcoin Core 0.11, вы можете изменить значение OP_RETURN_MAX_BYTES
на 80
, а не 40
на то, что сейчас указано в коде.
OP_RETURN
это способ получить произвольные данные в блокчейн с меньшей нагрузкой на сеть
Как следствие, данные также будут присутствовать в меньшем количестве клиентов, поскольку OP_RETURN
данные могут быть удалены.
Цель этого ответа — объяснить, что объяснил https://bitcoin.stackexchange.com/a/29555/21282 , но с немного большим контекстом для новичков в биткойнах.
Как выглядит стандартная транзакция
Как видно из разборки JSON с https://bitcoin.stackexchange.com/a/29555/21282 , у каждой транзакции есть список выходов, и у каждого выхода есть скрипт.
На сегодняшний день наиболее распространенным скриптом является pay-to-pubkey-hash , который в основном говорит:
этот вывод может быть использован человеком, который контролирует закрытый ключ к этому открытому ключу
или, проще говоря, «заплатите X биткойнов на адрес Y».
Этот скрипт имеет формат:
OP_DUP OP_HASH160 <length-of-hash> <pubKeyHash> OP_EQUALVERIFY OP_CHECKSIG
где pubKeyHash — 20 байт, а все остальные 5 полей — 1 байт.
Невозможно узнать, является ли стандартный хеш транзакции фактическим хэшем или произвольными данными.
Поскольку pubKeyHash
это хэш, невозможно узнать, является ли это фактическим хэшем чего-либо или произвольными данными, которые кто-то хочет закодировать в блокчейне.
Загвоздка в том, что если вы добавите туда произвольные данные, у вас не будет соответствующего закрытого ключа для возврата этих средств. Итак, что люди делают, так это совершают транзакции с наименьшей возможной суммой, которую майнеры готовы взять за работу по проверке.
Теперь каждая транзакция в блокчейне принимает в качестве входных данных предыдущий неизрасходованный вывод.
Следовательно, встраивание этих данных стоит вам немного, потому что эти выходные данные нельзя потратить: они никогда не могут быть использованы в качестве входных данных для другой транзакции.
Чтобы проверить, действительна ли транзакция, реализации Биткойн должны хранить полный список всех неизрасходованных выходных данных, когда-либо созданных, известный как набор UTXO .
Израсходованные выходные данные можно обрезать для экономии места, а неизрасходованные — нет.
Таким образом, всякий раз, когда вы записываете хеш-функция поддельного ключа паблика, вы заставляете каждую реализацию хранить эту информацию всегда, поскольку эти средства никогда не могут быть потрачены.
Как OP_RETURN
решает эту проблему
Возврат OP — это еще один тип транзакции скрипта, отличный от стандартной транзакции pay-to-pubkey-hash.
Как упоминалось в: https://en.bitcoin.it/wiki/Script#Provably_Unspendable.2FPrunable_Outputs , транзакция имеет простую форму:
OP_RETURN <data>
OP_RETURN
просто останавливает выполнение сценария с ошибкой, что делает невозможным использование этого вывода в качестве ввода другой транзакции.
Поэтому, когда реализация биткойна видит эту транзакцию, она может немедленно решить, что ее нельзя потратить, в отличие от описанной выше транзакции с оплатой по хеш-ключу, где принять такое решение невозможно. Вот почему эта транзакция называется «доказуемо невозможной».
Таким образом, майнер может майнить за плату за майнинг, но тогда реализации сразу же удаляют его из набора UTXO.
Это позволяет уменьшить набор UTXO, что делает биткойн более эффективным для всех.
Но, с другой стороны, это также означает, что ваши встроенные данные будут присутствовать на компьютерах меньшего количества людей.
Если вы здесь пытаетесь преобразовать OP_RETURN в читаемые значения:
Примечание. Это javascript/машинопись.
export default class OpReturnConverter {
// Input -> <Buffer 35 33 36 39...>
// Output -> 53696d706c6520616e737765722120f09f988a
public static convertBufferToHex(buffer: Buffer) {
const str = buffer.toString('hex')
return Buffer.from(str, 'hex').toString()
}
// Input -> 53696d706c6520616e737765722120f09f988a
// Output -> Simple answer! 😊
public static convertHexToString(hex: string) {
return Buffer.from(hex, 'hex').toString()
}
// Input -> Simple answer! 😊
// Output -> <Buffer 35 33 36 39...>
public static convertStringToBuffer(message: string) {
const hexBuffer = Buffer.from(message).toString('hex')
return Buffer.from(hexBuffer)
}
}
Полученные результаты
const string = 'Simple answer! 😊'
console.log('Original ->', string)
const buf = OpReturnConverter.convertStringToBuffer(string)
console.log('Buffer ->', buf)
const hex = OpReturnConverter.convertBufferToHex(buf)
console.log('Hex ->', hex)
const unhex = OpReturnConverter.convertHexToString(hex)
console.log('Unhex ->', unhex)
онимос
OACDesigns
636861726c6579206c6f766573206865696469
в php, это шестнадцатеричное значение, поэтому используйтеhex2bin()
Натан Паркер
Наюки
Талис К.
bitcoin-cli
а неbitcoind
.пользователь207863
xxd
команду можно использовать.echo 636861726c6579206c6f766573206865696469 | xxd -p -r
возвращаетсяcharley loves heidi
Роберманн
Роберманн
дионизиз
Талис К.
Buffer.from('636861726c6579206c6f766573206865696469', 'hex').toString('utf8');
Талис К.
it is usually considered non-standard (though valid) for a transaction to have more than one OP_RETURN output or an OP_RETURN output with more than one pushdata op
.Рони Теслер
Рони Теслер
Рони Теслер
Уильям Энтрикен
addresses
записьscriptPubKey
, чтобы указать получателя сообщения?