Здесь (в основном завершен) пример создания и подписания сырой сделки, она является лишь частью более крупным проектом, который принимает запросы от других, но это должно быть достаточно, чтобы увидеть код обработки транзакций. Не совсем комментировал, но, надеюсь, входы названы достаточно хорошо, что вы можете сказать, что они должны быть, если не просто спросите.
И обычный отказ очень тщательно проверить все сгенерированные транзакции, прежде чем позволить им свободно на главной сети. Кроме того, очень возможно, что есть некоторые вызовы в здесь слишком долго, чтобы работать с большими объемами на 32 битной системе, я знаю, я заменил некоторые звонки в других сценариях, но не уверен, что это один никогда не был бежать за исключением 64 -разр системы поэтому убедитесь, что ваши тестовые случаи включают в себя большое количество в какой-то момент.
#! / USR / бен / Perl
использовать Digest :: SHA;
требуют ("functions.inc");
$ REQ = сдвиг (@ARGV);
@ Г = разделение (/, /, $ REQ); Еогеасп $ г (@r) {@ р-р = разделение (/: /, $ г, 2); $ REQ {$ RR [0]} = $ р-р [1 ];}
$ Общая = 0; $ onum = 1; $ Sout = ''; UNDEF% вне;
@ O = разделение (/ - /, $ REQ { 'выход'}); Еогеасп $ о (@o) {@ оо = разделение (/ = /, $ о, 2);
($ Нетто, $ ключ) = decode_b58 ($ оо [0]);
если ($ оо [1]>0 && $ Нетто == 0 && $ Ключей п '') {$ из $ {оо [0]} + = $ оо [1]; $ общих + = $ оо [1]; $ onum ++;
$ А = Sprintf ( '% х', $ оо [1]), в то время (длина ($ а)<16) {$ а ="0". $ А;}
$ А = обратный ($ а);. $ Sout = упаковка ( 'ч *', $ а);
$ Сс = упаковка ( 'H *', '76a914' $ key.'88ac.);
$ А = Sprintf ( '% х', длина ($ сс)); если (длина ($ а)<2) {$ а ="0". $ А;}
$ Sout = упаковка ( 'Н *', $ а) $ сс..;
}}
$ Есть = 0; $ inum = 0;
@ O = разделение (/ - /, $ REQ { 'вход'}); Еогеасп $ о (@o) {($ ID, $ куб.см, $ амт, $ адр) = сплит (/: /, $ о, 4 );
$ В {"$ ID: $ куб.см"} = $ Адр; $ у + = $ амт; $ inum ++;
}
$ Плата = плата ($ onum, $ inum);
если ($ общей + $ плату>$ Есть) {умереть ("Недостаточно средств");}
$ Изменить = $ have- $ total- $ плату;
если ($ изменения>0) {
$ Из {$ REQ { 'изменения'}} = $ изменения; $ общего изменения + = $;
$ А = Sprintf ( '% х', $ изменить), в то время (длина ($ а)<16) {$ а ="0". $ А;}
$ А = обратный ($ а);. $ Sout = упаковка ( 'ч *', $ а);
($ Нетто, $ ключ) = decode_b58 ($ REQ { 'изменение'});
$ Сс = упаковка ( 'H *', '76a914' $ key.'88ac.);
$ А = Sprintf ( '% х', длина ($ сс)); если (длина ($ а)<2) {$ а ="0". $ А;}
$ Sout = упаковка ( 'Н *', $ а) $ сс..;
}
$ = Sprintf отправить ( '% X', $ onum); если ($ onum<16) {$ = отправить"0". $ Отправки;}
$ = Отправить пакет ( 'H *', $ посыла). $ Sout."\ X00 \ x00 \ x00 \ x00";
$ Start = Sprintf ( '% х', 1), в то время (длина ($ старт)<8) {$ = начать"0". $ Старт;}
$ = Начать обратное ($ старт); $ = начать пакет ( 'ч *', $ старт);
$ С = Sprintf ( '% х', $ inum); если ($ inum<16) {$ с ="0". $ С;}
$ = Начать упаковка ( 'Н *', $ с).
$ Хх = 0; для моего $ х (ключи% в) {$ а = $ в {$ х}; $. Inlist = $ х.",";
($ PTX, $ OID) = сплит (/: /, $ х); $ idtx [$ хх] = $ х;
$ PTX = обратное ($ PTX); $ BTX [$ хх] = пакет ( 'ч *', $ PTX);
$ С = Sprintf ( '% х', $ OID), в то время (длина ($ с)<8) {$ с ="0". $ С;}
$ С = задний ход ($ с); $ BTX [$ хх] = упаковка ( 'ч *', $ с).
$ БТК [$ хх]. ="\ X00 \ XFF \ XFF \ XFF \ XFF";
$ Хх ++;
} Измельчить ($ inlist);
$ Хх = 0, в то время ($ хх<$ Inum) {$ TMP = $ BTX [$ хх];
($ PTX, $ OID) = сплит (/: /, $ idtx [$ хх]); $ а = $ в {$ idtx [$ хх]};
$ BTX [$ хх] = зиЬзЬг ($ BTX [$ хх], 0, -5);
($ Нетто, $ ключ) = decode_b58 ($ а); $ сс = упаковка ( 'H *', '76a914' $ key.'88ac.);
$ Л = Sprintf ( '% х', длина ($ сс)); если (длина ($ л)<2) {$ л ="0". $ Л;}
$ BTX [$ хх]. = Упаковка ( 'Н *', $ л). $ Сс."\ XFF \ XFF \ XFF \ XFF";
$ PKey = addrprivkey ($ а); если ($ PKey экв '') {ошибка ("Не закрытый ключ найден в $ а");}
$ Те = $ start.join ( '', @ BTX). $ Посыл."\ X01 \ x00 \ x00 \ x00";
$ Тх = Digest :: ША :: sha256 (Digest :: ША :: sha256 ($ ТХ));
$ Ая = распаковка ( 'Н *', $ ТЙ); $ FTX [$ ая] = зиЬзЬги ($ TMP, 0, -5);
$ Сиг = signtx ($ ТХ, $ PKey);
$ Л = Sprintf ( '% х', длина (сиг $) + 1); если (длина ($ л)<2) {$ л ="0". $ Л;}
$ Сиг = упаковка ( 'Н *', $ л). $ Сиг."\ x01";
$ Рк = addrpubkey ($ а); $ рк = упаковка ( 'Н *', $ рк);
$ Л = Sprintf ( '% х', длина ($ рк)); если (длина ($ л)<2) {$ л ="0". $ Л;}
$ Сиг = упаковка ( 'Н *', $ л) $ рк..;
$ Л = Sprintf ( '% х', длина ($ сиг)); если (длина ($ л)<2) {$ л ="0". $ Л;}
$ FTX [$ хх]. = Упаковка ( 'Н *', $ л). $ Сиг."\ XFF \ XFF \ XFF \ XFF";
$ БТК [$ хх] = $ TMP; $ хх ++;
}
. $ Декабрь = $ start.join ( '', @ FTX) $ отправить;
$ Гекс = распаковка ( 'Н *', $ декабря);
$ Ч = Digest :: ША :: sha256 (Digest :: ША :: sha256 ($ Декабрь));
$ Хеш = обратное (распаковку ( 'ч *', $ ч));
Распечатать "Сырые сделки: $ шестигранной \ nTransaction ID: $ хэша \ п";
к югу плата {мой $ о = сдвиг (@_), мои $ я = сдвиг (@_) мой $ е = 0;
мой $ s = размер ($ о, $ я) мой $ р = INT ($ s / 1024) +1;
если ($ REQ { 'Приоритет'}>= 0) {
$ F + = 10000 * $ с;
} Если ($ REQ { 'Приоритет'}>= 1) {
$ F + = 40000 * $ с;
} Если ($ REQ { 'Приоритет'}>= 2) {
$ F + = $ s;
} Возвращение $ е;
}
к югу размер {мой $ о = сдвиг (@_) мой $ я = сдвиг (@_);
возвращение 10+ (180 * $ я) + (34 * $ о);
}
к югу addrprivkey {мой $ а = сдвиг (@_);
мой $ и = $ db->подготовка (кв.кв {выберите privkey от адреса, где адрес = «$ а»});
$ u->выполнить () мой $ ер, если ($ ер = $ и->fetchrow_array ()) {
вернуться распакуйте ( 'H *', $ cipher->decrypt_hex ($ ер));
}
}
к югу addrpubkey {мой $ а = сдвиг (@_);
мой $ и = $ db->подготовки (кв. {выберите Публичные от адреса, где адрес = «$ а»});
$ u->выполнить () мой $ ер = $ и->fetchrow_array (); возвращение $ ер;
}
А вот functions.inc, что он ссылается на:
использовать Digest :: SHA КЯ (sha256 sha256_hex);
использовать Crypt :: ripemd160;
использовать Math :: BigInt LIB => 'GMP';
@ Бб = (1..9, 'А' .. 'Н', 'J' .. 'N', 'Р' .. 'Z', 'а' .. 'к', 'т' .. 'г');
к югу decode_b58 {мой $ х = сдвиг (@_);
$ Х = ~ s / [0о] / о / г; $ х = ~ s / [II] / 1 / г;
мой $ вол = $ х мой $ п = Math :: BigInt->Новый (0);
$ Я = Math :: BigInt->новый (0), в то время как ($ х) {мой $ с = измельчить ($ х);
мой $ р = 0, в то время как ($ бб [$ ф] пе $ с && $ ф<= $ # Бб) {$ ф ++;}
$ П + = $ ф * (58 ** $ я); $ я ++;
} $ Я = $ n->as_hex (); $ г = зиЬзЬг ($ я, 2);
$ Х = обратный ($ вол) мой $ с = измельчить ($ х), в то время ($ C э '1') {$ с = измельчить ($ х); $ я ="00". $ Я;}
если (длина ($ я)% 2 == 1) {$ I ="0". $ Я;}
мой $ вер = подстрока ($ я, 0,2) мой $ CHK = зиЬзЬги ($ я, -8);
$ Я = зиЬзЬги ($ я, 2, -8);
$ П = упаковка ( 'Н *', $ вер $ я.);
мой $ ч = Digest :: ША :: sha256 (Digest :: ША :: sha256 ($ п));
$ С = зиЬзЬг (распаковка ( 'Н *', $ ч), 0,8);
$ Веры = гекс ($ вер);
если ($ CHK экв $ с) {возвращение ($ вер, $ я);}
вернуть ('','');
}
к югу ecadd {мой $ а = сдвиг (@_) мой $ Ь = сдвиг (@_);
мой $ р = Math :: BigInt->новый ( '0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F');
мой $ ах = Math :: BigInt->новый ( '0x'.substr ($ а, 2,64));
мой $ ау = Math :: BigInt->новый ( '0x'.substr ($ а, 66));
мой $ BX = Math :: BigInt->новый ( '0x'.substr ($ Ь, 2,64));
мой $ от = Math :: BigInt->новый ( '0x'.substr ($ Ь, 66));
если ($ уравнения '') {возвращение $ а;}
если ($ ау экв '') {вернуть $ Ь;}
если ($ ах == $ BX) {
если (($ ау + $ от)% $ р == 0) {
вернуть '';
} Еще {
мой ($ гх, $ чень) = ecdouble ($ аи $ ау);
Возвращение ( '04'.substr ($ RX->as_hex (), 2) .substr (Рыбаковым $>as_hex (), 2));
}
}
мой $ х = $ bx- $ Ax; $ x->bmodinv ($ р);
мой $ хх = (($ $ ау каждого конкретного) * $ х)% $ р;
мой $ гх = ($ хх * $ xx- $ ax- $ BX)% $ р;
мой $ гу = ($ хх * ($ ax- $ гх) - $ ау)% $ р;
$ Ге = зиЬзЬги ($ RX->as_hex (), 2); $ Ry = зиЬзЬги ($ Рыбаков>as_hex (), 2);
в то время как (длина ($ гх)<64) {$ гх ="0". $ Гх;}, а (длина ($ Ry)<64) {$ Ry ="0". $ Чень;}
вернуть "04".. $ Гх $ чень;
}
к югу ecaddnum {мой $ ах = сдвиг (@_) мой $ ау = сдвиг (@_) мой $ BX = смещение (@_) мой $ от = сдвига (@_);
мой $ р = Math :: BigInt->новый ( '0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F');
если ($ уравнения '') {возвращение ($ ах, $ AY);}
если ($ ау э '') {возвращение ($ BX, $ пути);}
если ($ ах == $ BX) {
если (($ ау + $ от)% $ р == 0) {
вернуть('','');
} Еще {
вернуться ecdouble ($ топор, $ ау);
}
}
мой $ х = $ bx- $ Ax; $ x->bmodinv ($ р);
мой $ хх = (($ $ ау каждого конкретного) * $ х)% $ р;
мой $ гх = ($ хх * $ xx- $ ax- $ BX)% $ р;
мой $ гу = ($ хх * ($ ax- $ гх) - $ ау)% $ р;
возврат ($ гх, $ чень);
}
к югу ecmult {мой $ рь = сдвиг (@_) мой $ р = сдвиг (@_);
мой $ х = Math :: BigInt->новый ( '0x'.substr ($ рь, 2,64));
мой $ у = Math :: BigInt->новый ( '0x'.substr ($ рь, 66));
мой $ п = Math :: BigInt->новый ( '0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141');
если ($ р == 0) {возвращение '';}
если ($ у эк '') {возвращение '';}
$ Р = $ р% $ п; $ р = $ р * 3;
мой $ я = Math :: BigInt->новый ( '1');
в то время как ($ я<= $ Рр) {$ я = $ г * 2;} $ я = $ I / 4;
мой $ гх = $ х->копия (); мой $ гу = $ y->копия ();
в то время как ($ я>1) {
($ Гх, $ Ry) = ecdouble ($ гх, $ Ry);
мой $ е = $ pp->копия (); $ e->группа ($ я), мой $ й = $ p->копия (); $ ee->группа ($ я);
если ($ е! = 0 && $ Й == 0) {($ гй, $ Ry) = ecaddnum ($ гй, $ гу, $ х, $ у);}
если ($ е == 0 && ! $ Й = 0) {($ ге, $ чень) = ecaddnum ($ гй, $ чень, $ х, - $ у);}
$ Я = $ я / 2;
}
$ Ге = зиЬзЬги ($ RX->as_hex (), 2); $ Ry = зиЬзЬги ($ Рыбаков>as_hex (), 2);
в то время как (длина ($ гх)<64) {$ гх ="0". $ Гх;}, а (длина ($ Ry)<64) {$ Ry ="0". $ Чень;}
вернуть "04".. $ Гх $ чень;
}
к югу ecdouble {мой $ х = сдвиг (@_) мой $ у = сдвиг (@_);
мой $ р = Math :: BigInt->новый ( '0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F');
мой $ л = 2 * $ у; $ l->bmodinv ($ р);
$ L = ($ л * 3 * $ х * $ х)% $ р;
мой $ хх = ($ л * $ л-2 * $ х)% $ р;
мой $ уу = ($ л * ($ х $ хх) - $ у)% $ р;
возврата ($ хх, $ уу);
}
к югу signtx {мой $ т = сдвиг (@_) мой $ к = сдвиг (@_);
мой $ мм = Math :: BigInt->новый ( '0x' $ м.);
мой $ рк = Math :: BigInt->новый ( '0x' $ к.);
мой $ п = Math :: BigInt->новый ( '0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141');
мои @chars = ( 'а' .. 'F', 0..9); мой $ ЧД = присоединиться к '', карта {$ сов [ранд @chars]} 1..64;
мой $ г = Math :: BigInt->новый ( '0x' $ р-р.);
мой $ к = $ г $% п;
мой $ р = ecmult ( '0479BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8', $ к);
$ Г = Math :: BigInt->новый ( '0x'.substr ($ р, 2,64));
мой $ s = $ k->копия (); $ s->bmodinv ($ п);
$ S = $ s * ($ мм + ($ рк * $ г)% $ п)% $ п;
$ Г = зиЬзЬги ($ r->as_hex (), 2); $ S = зиЬзЬги ($ втор->as_hex (), 2);
если (длина ($ г)% 2 == 1) {$ г ="0". $ Г;} если (длина ($ s)% 2 == 1) {$ s ="0". $ S;}
$ к = зиЬзЬги ($ г, 0,1); если ($ к>7 || ($ К == 0 && $ К пе '0')) {$ г ="00". $ Г;}
$ К = SUBSTR ($ с, 0,1); если ($ K>7 || ($ К == 0 && $ К пе '0')) {$ s ="00". $ S;}
$ Г = упаковка ( 'Н *', $ г); $ S = упаковка ( 'Н *', $ s);
мой $ = Л.Р. Sprintf ( '% х', длина ($ г)); если (длина ($ Л.Р.)<2) {$ = Л.Р."0". $ Л.Р.;}
мои $ Ls = Sprintf ( '% х', длина ($ s)); если (длина ($ Ls)<2) {$ = Ls"0". $ Ls;}
$ Rs ="\ x02".pack ( 'Н *', $ Л.Р.). $ г."\ x02".pack ( 'H *', $ Ls) $ s.
мой $ л = Sprintf ( '% х', длина ($ RS)); если (длина ($ л)<2) {$ л ="0". $ Л;}
вернуть("\ x30".pack ( 'Н *', $ л) $ Rs).
}
к югу hashtoaddr {мой $ нб = сдвиг (@_) мой $ х = сдвиг (@_);
мой $ Н = Sprintf ( '% х', $ пи), в то время как (длина ($ Н)<2) {$ Н ="0". $ Н;}
$ Х = упаковка ( 'Н *', $ Н $ х.);
мой $ адр = распаковывать ( 'H *', $ х); $ х = Digest :: ША :: sha256 (Digest :: ША :: sha256 ($ х));
. $ Адр = зиЬзЬг (распаковать ( 'H *', $ х), 0,8);
мой $ из = '', в то время (подстрока ($ адр, 0,2) э '00') {$ = вне."1"; $ Адр = зиЬзЬги ($ адр, 2);}
мой $ а = Math :: BigInt->новый ( '0x' $ адр.) мой $ о = '';
в то время как ($ а>58) {$ о = $ бб [$ а% 58] $ O;. $ А = $ а / 58;}
$ А = $ бб [$ а] $ о.
вернуть $ из $ о.
}
к югу pkeytoaddr {мой $ нб = сдвиг (@_) мой $ х = сдвиг (@_);
$ Х = упаковка ( 'H *', $ х); $ х = Digest :: ША :: sha256 ($ х);
мой $ Н = Sprintf ( '% х', $ пи), в то время как (длина ($ Н)<2) {$ Н ="0". $ Н;}
$ Х = упаковка ( 'H *', $ Н) .Crypt :: RIPEMD160->хэш ($ х);
мой $ адр = распаковывать ( 'H *', $ х); $ х = Digest :: ША :: sha256 (Digest :: ША :: sha256 ($ х));
. $ Адр = зиЬзЬг (распаковать ( 'H *', $ х), 0,8);
мой $ из = '', в то время (подстрока ($ адр, 0,2) э '00') {$ = вне."1"; $ Адр = зиЬзЬги ($ адр, 2);}
мой $ а = Math :: BigInt->новый ( '0x' $ адр.) мой $ о = '';
в то время как ($ а>58) {$ о = $ бб [$ а% 58] $ O;. $ А = $ а / 58;}
$ А = $ бб [$ а] $ о.
вернуть $ из $ о.
}
1;