Я пытался создать свой собственный генератор необработанных транзакций на Java, который затем я могу транслировать в сети testnet. Проблема в том, что когда я пытаюсь транслировать транзакцию, он говорит, что в сценарии выкупа есть ошибка, которую я не понимаю.
Вот пример транзакции в тестовой сети:
0100000001e468833270cf713f3bbccc62b7b5b0fc0b0a4570608718530816795a6589f322000000008a473044022051646b77924f6bb7c411c5aa890110ab55db8812b8998fe24c8bdce39795ebd602200bc4de18fd5524ad8b946ee57604424e2b943ef2a14fc7199a7853dda0743cbe014104b97c679207532e0f4ee2515aedaba5f87700bbe0138f7457baa58e89a53153823ab29632e6c3c804ecaab5913656512339792479a1b898b7e5dc31f075ff8660ffffffff0176df1710000000001976a91448ddfd3891f3f422d5c3c9c25e35b382667fc6e688ac00000000
Сценарий, который я пытаюсь разблокировать:
76a91448ddfd3891f3f422d5c3c9c25e35b382667fc6e688ac
Со сценарием выкупа:
473044022051646b77924f6bb7c411c5aa890110ab55db8812b8998fe24c8bdce39795ebd602200bc4de18fd5524ad8b946ee57604424e2b943ef2a14fc7199a7853dda0743cbe014104b97c679207532e0f4ee2515aedaba5f87700bbe0138f7457baa58e89a53153823ab29632e6c3c804ecaab5913656512339792479a1b898b7e5dc31f075ff8660
Это код Java для подписи обратного двойного хэша sha256:
public static byte[] sign(byte[] hash, BigInteger priv){
ECDSASigner signer = new ECDSASigner(new HMacDSAKCalculator(new SHA256Digest()));
signer.init(true, new ECPrivateKeyParameters(priv, domain));
BigInteger[] signature = signer.generateSignature(hash);
ByteArrayOutputStream s = new ByteArrayOutputStream();
try {
DERSequenceGenerator seq = new DERSequenceGenerator(s);
seq.addObject(new ASN1Integer(signature[0]));
seq.addObject(new ASN1Integer(signature[1]));
seq.close();
return s.toByteArray();
}
catch(IOException e){
return null;
}
}
Что случилось?
Быстро расшифровать tx:
VERSION 01000000
TX_IN COUNT hex=01, decimal=1
TX_IN[0]
TX_IN[0] OutPoint hash 22F389655A7916085318876070450A0BFCB0B5B762CCBC3B3F71CF70328368E4
TX_IN[0] OutPoint index hex=00000000, reversed=00000000, decimal=0
TX_IN[0] Script Length hex=8A, decimal=138
TX_IN[0] Script Sig 473044022051646B77924F6BB7C411C5AA890110AB55DB8812B8998FE24C8BDCE39795EBD602200BC4DE18FD5524AD8B946EE57604424E2B943EF2A14FC7199A7853DDA0743CBE014104B97C679207532E0F4EE2515AEDABA5F87700BBE0138F7457BAA58E89A53153823AB29632E6C3C804ECAAB5913656512339792479A1B898B7E5DC31F075FF8660
47: OP_DATA_0x47: push hex 47 (decimal 71) bytes as data
30: OP_SEQUENCE_0x30: type tag indicating SEQUENCE, begin sigscript
44: OP_LENGTH_0x44: length of R + S
02: OP_INT_0x02: type tag indicating INTEGER
20: OP_LENGTH_0x20: this is SIG R
51646B77924F6BB7:C411C5AA890110AB:55DB8812B8998FE2:4C8BDCE39795EBD6
02: OP_S_INT_0x02
20: OP_LENGTH_0x20: this is SIG S
0BC4DE18FD5524AD:8B946EE57604424E:2B943EF2A14FC719:9A7853DDA0743CBE
01: OP_SIGHASHALL: this terminates the ECDSA signature (ASN1-DER structure)
Minimum and maximum size constraints - ok
scriptsig always starts with 0x30 - ok
length 136 chars is less than actual sig length (140 chars) - ok
(hex 0x44, decimal 68, 136 chars)
length of R coordinate (64) >= 0 - ok
length of S coordinate (64) >= 0 - ok
S-Value is within scriptsig boundaries - ok
Make sure the R & S length covers the entire signature - ok
S-value must be smaller than N/2 - ok
strictly check DER-encoded signature - ok
41: OP_DATA_0x41: push hex 41 (decimal 65) bytes as data
04: OP_LENGTH_0X04
B97C679207532E0F:4EE2515AEDABA5F8:7700BBE0138F7457:BAA58E89A5315382
3AB29632E6C3C804:ECAAB59136565123:39792479A1B898B7:E5DC31F075FF8660
* This terminates the Public Key, corresponding bitcoin address is: mnAEswb3Aiz5YTsfCJc8vQETnSe19mc5Am
TX_IN[0] Sequence FFFFFFFF
TX_OUT COUNT, hex=01, decimal=1
TX_OUT[0] Value hex=76DF171000000000, rev_hex=000000001017DF76, dec=269999990
TX_OUT[0] PK_Script Length hex=19, dec=25
TX_OUT[0] pk_script 76A91448DDFD3891F3F422D5C3C9C25E35B382667FC6E688AC
76: OP_DUP
A9: OP_HASH160
14: OP_Data14 (= decimal 20)
48DDFD3891F3F422:D5C3C9C25E35B382
667FC6E6
88: OP_EQUALVERIFY
AC: OP_CHECKSIG This is a P2PKH script and translates base58 encoded into this bitcoin address: mnAEswb3Aiz5YTsfCJc8vQETnSe19mc5Am
LOCK_TIME 00000000
Значит транзакция правильная, и подпись собрана правильно. Он также следует правилам «строгой проверки подписи». Тх пытается провести от mnAEswb3Aiz5YTsfCJc8vQETnSe19mc5Am до mnAEswb3Aiz5YTsfCJc8vQETnSe19mc5Am. Итак, я проверил подпись по двойному хешу tx (см. знаменитое прохождение транзакции пиццы: Как работает алгоритм проверки ECDSA во время транзакции? ):
Raw_tx.txt:
0100000001e468833270cf713f3bbccc62b7b5b0fc0b0a4570608718530816795a6589f322000000008a473044022051646b77924f6bb7c411c5aa890110ab55db8812b8998fe24c8bdce39795ebd602200bc4de18fd5524ad8b946ee57604424e2b943ef2a14fc7199a7853dda0743cbe014104b97c679207532e0f4ee2515aedaba5f87700bbe0138f7457baa58e89a53153823ab29632e6c3c804ecaab5913656512339792479a1b898b7e5dc31f075ff8660ffffffff0176df1710000000001976a91448ddfd3891f3f422d5c3c9c25e35b382667fc6e688ac00000000
Удалил sig и вписал свой скрипт pubkey в raw_tx_SIGHASH_ALL.txt:
0100000001e468833270cf713f3bbccc62b7b5b0fc0b0a4570608718530816795a6589f322000000001976a91448ddfd3891f3f422d5c3c9c25e35b382667fc6e688acffffffff0176df1710000000001976a91448ddfd3891f3f422d5c3c9c25e35b382667fc6e688ac0000000001000000
и двойной хэш (двоичные значения, следовательно, сначала некоторое преобразование!)
result=$( cat raw_tx_SIGHASH_ALL.txt | sed 's/[[:xdigit:]]\{2\}/\\x&/g' )
printf $result > raw_tx.hex
hexdump -C raw_tx.hex
openssl dgst -binary -sha256 <raw_tx.hex >ssha256.hex
openssl dgst -binary -sha256 <ssha256.hex >dsha256.hex
hexdump -C dsha256.hex
Таким образом, dsha256 находится в удобочитаемой форме: 6b37475a5388fb52f227817a0ddec00e7b69495b492cd7cdc6aff2afc44810e4.
Я использую openssl для проверки шестнадцатеричного файла с двойным хешем (dsha256.hex) с подписью и ключом «pem» (необходимо преобразовать pubkey из шестнадцатеричного в pem), я всегда получаю сообщение об ошибке:
openssl pkeyutl -verify -pubin -inkey pubkey.pem -sigfile tmp_sig.hex -in dsha256.hex
при выполнении примера с пиццей он возвращает «Подпись успешно проверена».
ср-ги
пользователь 2965346
ср-ги
пользователь 2965346
ср-ги