Вот пример сеанса:
Код:
$ mktx.pl
IDX адрес сумма btcdays GRP Vout
0) +18,43147597 1A7y8jy7xxxxxxxxxxxxxxxxxxxxxxxxxx 29.44 8 9c26c17f780e9e9415a6b8a58fxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: 0
1) +13,30826540 19GgbRa5xxxxxxxxxxxxxxxxxxxxxxxxxx 144,73 0 9d7ffe1562756e216c92935a71xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: 0
2) 9,00000000 18NAfDsdxxxxxxxxxxxxxxxxxxxxxxxxxx 1192,31 10 0ba6400f87c554b7e41d0fe8b8xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: 1
3) 3,58293316 15HK4cyhxxxxxxxxxxxxxxxxxxxxxxxxxx 14.18 12 a2dad2d0289449b80850d77b2dxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: 2
4) 2,57453211 1KXoabe8xxxxxxxxxxxxxxxxxxxxxxxxxx 349,31 0 5f94d690d75bca1becdc91cacdxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: 0
5) 2,29610578 1ydDG6nxxxxxxxxxxxxxxxxxxxxxxxxxx 9,09 2 a2dad2d0289449b80850d77b2dxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: 0
6) 1,83458911 1EmHjWp7xxxxxxxxxxxxxxxxxxxxxxxxxx 7,29 11 df64fb188d1965a6607032b502xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: 1
7) 0,80863146 1LMUtqtJxxxxxxxxxxxxxxxxxxxxxxxxxx 3,21 6 df64fb188d1965a6607032b502xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: 0
8) 0,59664818 1HyZb7Psxxxxxxxxxxxxxxxxxxxxxxxxxx 2,36 1 16703bc4ce9f35bd75a64e07e5xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: 1
Выбор входов (разделенные пробелами): 0 1 4
Введите выходы: адрес назначения и количество разделенных пробелом (ввод, чтобы закончить)
Введите выход (+34,31427348 доступный): 12XCzX7ogxxxxxxxxxxxxxxxxxxxxxxxxx 26.34859225
Введите выход (7,96568123 доступен):
Debug: входы общая сумма '34 0,31427348' , назначен '26 0,34859225'
Введите адрес, куда отправить 7.96568123 как изменение: новый
Изменение будет идти на «1BZoDTY3NGr65axxxxxxxxxxxxxxxxxxxx»
Отладки: приблизительный размер транзакции: 614 байт (плата требуется при 10000 байт или более)
Приоритет транзакции: Отладка 122770.67M (платная в 57.6M или меньше)
Введите желаемую сумму (по умолчанию 0):
Введите бумажник ключевую фразу (необходимый для подписания сделки):
IDX адрес сумма btcdays GRP Vout
0) +18,43147597 1A7y8jy7xxxxxxxxxxxxxxxxxxxxxxxxxx 29.44 8 9c26c17f780e9e9415a6b8a58fxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: 0
1) +13,30826540 19GgbRa5xxxxxxxxxxxxxxxxxxxxxxxxxx 144,73 0 9d7ffe1562756e216c92935a71xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: 0
2) 9,00000000 18NAfDsdxxxxxxxxxxxxxxxxxxxxxxxxxx 1192,31 10 0ba6400f87c554b7e41d0fe8b8xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: 1
3) 3,58293316 15HK4cyhxxxxxxxxxxxxxxxxxxxxxxxxxx 14.18 12 a2dad2d0289449b80850d77b2dxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: 2
4) 2,57453211 1KXoabe8xxxxxxxxxxxxxxxxxxxxxxxxxx 349,31 0 5f94d690d75bca1becdc91cacdxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: 0
5) 2,29610578 1ydDG6nxxxxxxxxxxxxxxxxxxxxxxxxxx 9,09 2 a2dad2d0289449b80850d77b2dxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: 0
6) 1,83458911 1EmHjWp7xxxxxxxxxxxxxxxxxxxxxxxxxx 7,29 11 df64fb188d1965a6607032b502xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: 1
7) 0,80863146 1LMUtqtJxxxxxxxxxxxxxxxxxxxxxxxxxx 3,21 6 df64fb188d1965a6607032b502xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: 0
8) 0,59664818 1HyZb7Psxxxxxxxxxxxxxxxxxxxxxxxxxx 2,36 1 16703bc4ce9f35bd75a64e07e5xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx: 1
Выбор входов (разделенные пробелами): 0 1 4
Введите выходы: адрес назначения и количество разделенных пробелом (ввод, чтобы закончить)
Введите выход (+34,31427348 доступный): 12XCzX7ogxxxxxxxxxxxxxxxxxxxxxxxxx 26.34859225
Введите выход (7,96568123 доступен):
Debug: входы общая сумма '34 0,31427348' , назначен '26 0,34859225'
Введите адрес, куда отправить 7.96568123 как изменение: новый
Изменение будет идти на «1BZoDTY3NGr65axxxxxxxxxxxxxxxxxxxx»
Отладки: приблизительный размер транзакции: 614 байт (плата требуется при 10000 байт или более)
Приоритет транзакции: Отладка 122770.67M (платная в 57.6M или меньше)
Введите желаемую сумму (по умолчанию 0):
Введите бумажник ключевую фразу (необходимый для подписания сделки):
Перечень неизрасходованных выходов показано, сортируются по количеству. Колонка "GRP" показывает один и тот же номер для монет, которые, как известно, связаны между собой, поэтому их использование в качестве входных данных не попадала любой частной жизни. Там также колонка показывает bitcoindays, чтобы помочь в выборе монеты. "Vout" колонка есть только потому, что.
Введите результаты, которые вы хотите использовать в качестве входов новой транзакции, а затем введите адреса назначения и их сумму. Вы можете создать столько выходов, сколько вы хотите. Введите пустую строку, чтобы закончить этот шаг, то вам будет предложено для адреса для изменения. Обратите внимание, что я вступил «новый», вы можете ввести «новый» в предыдущем шаге тоже. После этого требуется плата рассчитывается, и вы получаете возможность использовать предложенный один или переопределить его самостоятельно (то есть вы можете заплатить взнос, даже если он не нужен, или не платить плату, когда вы действительно SHOULD- Используйте на свой риск!). Плата вычитается из сигнала изменения.
В качестве последнего шага, программа запрашивает ключ шифрования бумажника для того, чтобы подписать сделку, а затем выплевывает полученную структуру данных и, в нижней части, сырье сериализованной сделка печатаются, так что вы можете вручную кормить его к sendrawtransaction RPC команды или вставить его в blochain.info/pushtx. Входы и выходы перемешиваются для повышения приватности (я не думаю, что это необходимо на входах, но решило перестраховаться) (выходы неявно перемешивается из-за характер Perl хэш). Тот факт, что эта программа не отправляет саму сделку особенность, а не ошибка.
Интересно, что пример сеанс от реальной сделки, которая прошла 3 блоков, чтобы подтвердить, даже если его приоритет представляется весьма высокими.
Критика приветствуется (желательно конструктивной).
Обновление 2013-05-03: Новая версия, что принять --list параметра (или -l) перечислить unpent выходов и выход.
Обновление 2013-05-06: Прикладывали плату за 10 Кб вместо каждого Kb. Уч.
Код:
#! / USR / бен / Perl
## TODO: можно добавить: если ($ плата) {печать "вы платите% d satoshis за т.п.н.", $ Плата * 1E8 / ($ tx_size / 1000); }
использовать предупреждение;
использовать строгий;
использовать File :: Spec;
использовать Скалярные :: Util дш / looks_like_number /;
Использовать список :: Util КЯ / мин сумма перетасовать /;
использовать Getopt :: Long;
использовать JSON RPC :: :: Client;
Использование Data :: Dumper;
мой $ MIN_FEE = 0,0005;
мой $ cfgfile = File :: спектрометр>catfile ($ ENV { 'НАЧАЛО'},».bitcoin', 'bitcoin.conf');
мой ($ rpcuser, $ rpcpass);
к югу get_rpc {
-е $ cfgfile или умереть "Bitcoin конфигурации не найден \ п";
открыть свой $ FD, '<», $ Cfgfile или умереть "Открывание: '$ cfgfile': $!";
в то время как (<$ FD>) {
если (/^rpcuser=(.*)/) {$ rpcuser = $ 1; }
если (/^rpcpassword=(.*)/) {$ rpcpass = $ 1; }
}
закрыть $ FD;
если (! $ rpcuser или! $ rpcpass) {умереть "не может найти RPC учетных данных в Bitcoin конфигурации \ п"; }
мой $ URL = "Http: // $ rpcuser: $ rpcpass \ @localhost: 8332 /";
мой $ = JSON RPC :: RPC :: Client->новый;
$ rPC->подготовить ($ URL, [дш /
createrawtransaction decoderawtransaction getnewaddress getrawtransaction listaddressgroupings
listunspent signrawtransaction validateaddress walletpassphrase
/]);
вернуть $ RPC;
}
к югу addr2grp {
мой ($ RPC) = @_;
мои $ группировки = $ rPC->listaddressgroupings;
мой% addr2grp;
Foreach моего $ group_idx (0 .. $ # $ группировок) {
Foreach моего $ записи (@ {$ groupings->[$ Group_idx]}) {
$ Addr2grp {$ entry->[0]} = $ group_idx;
}
}
вернуться% addr2grp;
}
суб vouts {
мой ($ RPC) = @_;
мой $ неизрасходованные = $ rPC->listunspent;
мои $ vouts;
Foreach мой $ U (@ $ неизрасходованные) {
мой $ rawtx = $ rPC->getrawtransaction ($ u->{ 'TXID'});
$ Rawtx = $ rPC->decoderawtransaction ($ rawtx);
мой $ Vout = $ rawtx->{ 'Vout'} [$ u->{ 'Vout'}];
Следующий, если «pubkeyhash» пе $ vout->{ 'ScriptPubKey'} { 'типа'} и 'scripthash' п $ vout->{ 'ScriptPubKey'} { 'типа'};
$ u->{ 'Адрес'} = $ vout->{ 'ScriptPubKey'} { 'адрес'} [0];
$ u->{ 'btcdays'} = $ и->{ 'Сумма'} * $ u->{ ''} Подтверждения / 144;
нажмите @ $ vouts, $ и;
}
вернуть $ vouts;
}
суб get_selected_outs {
мой ($ largest_out) = @_;
Распечатать "\ п";
OUTER: {
печать «Выбор входа (разделенных пробелами):»;
мой $ selected_ins = <>; чавкать $ selected_ins; мои @selected_ins = расщепленные / \ S + /, $ selected_ins;
Foreach мой $ в (@selected_ins) {
если ($ в! ~ / ^ \ d + $ /) {предупредить "Ошибка: неверный ввод «$ в» \ п"; повтор OUTER; }
если ($ в > $ Largest_out) {предупредить "Ошибка: ввод «$ в» слишком большой \ п"; повтор OUTER; }
}
вернуться @selected_ins;
}
}
суб get_dests {
мой ($ RPC, $ помогло) = @_;
мои% dests;
Распечатать "\ NВведите выходы: адрес получателя и количество разделенных пробелом (ввод, чтобы закончить) \ П";
в то время как (1) {
Распечатать "Введите выход (доступный $) безрезультатно: ";
мой $ = Dest <>; чавкать $ Dest;
если (! длина $ Dest) {
последний, если% dests;
предупреждать "введите по крайней мере один пункт назначения \ п";
повтор;
}
мой ($ dest_addr, $ dest_amnt) = разделить / \ s + /, $ Dest;
если (! $ определено dest_amnt) {
Распечатать "Ошибка: введите адрес получателя и количество разделенного пространства \ п";
следующий;
}
если (! looks_like_number $ dest_amnt) {предупредить "сумма «$ dest_amnt» не является числом \ п"; повтор; }
если ($ dest_amnt <= 0) {предупредить "сумма «$ dest_amnt» не является положительным \ п"; повтор; }
если ( 'новый' эк $ dest_addr) {
$ Dest_addr = $ rPC->getnewaddress;
Распечатать "Использование адреса «$ dest_addr» \ п";
}
если (! $ rPC->validateaddress ($ dest_addr) ->{ 'IsValid'}) {предупредить "адрес «$ dest_addr» недействительно \ п"; повтор; }
если (существует $ dests {$ dest_addr}) {предупредить "есть уже выход на этот адрес \ п"; повтор; }
если ($ dest_amnt > $ Помогло) {предупредить "Ошибка: не хватает средств на выбранных входов \ п"; повтор; }
$ dests {$ dest_addr} = 0 + $ dest_amnt;
$ = 0 помогло + Sprintf '% .8f', $ помогло - $ dest_amnt;
не последний, если $ безрезультатно;
}
Распечатать "\ п";
вернуться% dests;
}
к югу плата {
мой (выбран $, $ dests, $ change_addr) = @_;
мой $ tx_size = 10 + 180 * @ $ выбранных + 32 * ключи% $ dests;
Распечатать " Debug: оценивается размер сделки: $ tx_size байт (платная на 10000 байт или больше) \ п";
мой $ tx_size_ok = $ tx_size < 10000;
мои $ smallest_out = мин значения% $ dests;
мой $ out_amounts_ok = $ smallest_out >= 0,01;
мой $ tx_prio = карта сумма {$ _->{ 'Сумма'} * 10e8 * $ _->{ 'Подтверждения'}} @ $ выбрана;
$ Tx_prio / = $ tx_size;
мой $ tx_prio_ok = $ tx_prio > 57_600_000;
Printf " Debug: приоритет транзакции:% .2fM (платная в 57.6M или меньше) \ п", $ Tx_prio / 1E6;
мой $ sugg_fee = 0;
если (! $ tx_size_ok ||! $ out_amounts_ok) {
если (! $ tx_size_ok) {печать " Сделка слишком большой ($ tx_size байт), плата рекомендуется \ п"; }
если (! $ out_amounts_ok) {печать " Некоторые из выходов меньше 0,01 BTC ($ smallest_out), вознаграждение рекомендуется \ п"; }
мой $ rounded_tx_size = INT ($ tx_size / 1000); $ Rounded_tx_size ++;
$ Sugg_fee = $ MIN_FEE * $ rounded_tx_size;
}
если (! $ tx_prio_ok) {
Распечатать " Приоритет сделки слишком низкая ($ tx_prio), плата рекомендуется \ п";
$ Sugg_fee + = $ MIN_FEE;
}
Распечатать " Внимание: плата рекомендуются, но эта сделка не имеет выхода изменения, из которого вычтет плату \ п" если $ sugg_fee && ! $ Change_addr;
Распечатать " Предупреждение: предложили гонорар больше, чем выходное изменение \ п" если $ change_addr и $ sugg_fee > $ dests->{$ Change_addr};
Распечатать "\ NВведите желаемую плата (по умолчанию $ sugg_fee): "; мой $ плата = <>; $ Плата за чавкать; $ Плата || = $ sugg_fee;
если (! $ плату) {
Распечатать " Внимание: рекомендуется плата \ п" если $ sugg_fee;
вернуть;
}
умереть "Ошибка: нет выходного изменения, из которого вычтет плату \ п" если $ плата && ! $ Change_addr;
умереть "Ошибка: плата больше, чем выходное изменение \ п" если $ change_addr и $ плата > $ dests->{$ Change_addr};
если ($ стоимость == $ dests->{$ Change_addr}) {
удалить $ dests->{$ Change_addr}; ## упс, это изменяет размер ТХ, поэтому она потенциально влияет на саму плату
} Еще {
$ dests->{$ Change_addr} - = $ плата;
}
}
################################################## #
GetOptions \ Мои% Opts, '--list' или умереть "Getopt не удалось \ п";
мой $ = get_rpc RPC;
мой% addr_to_group = addr2grp $ RPC;
мой $ vouts = vouts $ или сделать RPC {печати "Никакие средства не \ п"; Выход; };
Printf кв.кв /% 3s% 12s% 35s% 8s% 3s% 66s \ п /, QW / IDX количество адресов btcdays GRP Vout /;
мой $ Индекс = 0;
@ $ Vouts = реверс рода {$ a->{'количество'} <знак равно> $ b->{ 'Сумма'}} @ $ vouts;
Foreach мой $ Vout (@ $ vouts) {
# Мой $ AMNT = $ vout->{'количество'}; если ($ AMNT ~ /\./!) {$ AMNT =. ''; } $ AMNT = '00000000'. $ AMNT = ~ s / (\ .. {8}) * / $ 1 /.
мой $ AMNT = Sprintf '% .8f', $ vout->{'количество'};
Printf кв.кв /% 2s)% 12s% 35s% 8.2f% 3s% s:% s \ п /, $ индекс, $ AMNT, @ $ Vout {дш / адрес btcdays /} $ addr_to_group {$ vout->{ 'Адрес'}} @ $ {Vout дш / TXID Vout /};
$ Индекс ++;
}
выход, если $ выбирает { «список»};
мой @selected_ins = get_selected_outs $ # $ vouts;
мой @selected = @ $ vouts [@selected_ins];
мой $ available_amnt = карта сумма {$ _->{ 'Сумма'}} @selected;
мой% dests = get_dests $ RPC, $ available_amnt;
мой $ txamnt = сумма значений% dests;
мой $ нераспределенные = Sprintf '% .8f', $ available_amnt - $ txamnt;
мой $ change_addr;
если ($ Unassigned >= 1e-8) {
## $ Unassigned может иметь дополнительные десятичные места из-за проблемы с плавающей точкой, увидеть, если эти десятичные дроби
## уже присутствуют в этих переменных, или они появляются в вычитании выше
Распечатать " Debug: входы общая сумма '$ available_amnt', присваивается '$ txamnt' \ п \ п";
{
Распечатать "Введите адрес, куда отправить $ присвоенных в качестве изменения: "; $ Change_addr = <>; чавкать $ change_addr;
если ( 'новый' эк $ change_addr) {
$ Change_addr = $ rPC->getnewaddress;
Распечатать "\ П Изменение будет идти в «$ change_addr» \ п";
}
если (! $ rPC->validateaddress ($ change_addr) ->{ 'IsValid'}) {предупредить "адрес «$ change_addr» недействительно \ п"; повтор; }
если (существует $ dests {$ change_addr}) {предупредить "есть уже выход на этот адрес \ п"; повтор; }
$ Dests {$ change_addr} = 0 + $ неприсвоенный;
последний;
}
Распечатать "\ п";
}
плата \ @selected, \% dests, $ change_addr;
мои $ INS = [перетасовать карты {{TXID => $ _->{ 'TXID'}, Vout => 0 + $ _->{ 'Vout'}}} @selected];
мои $ ауты = \% dests;
мой $ Тх = $ rPC->createrawtransaction ([$ ины, $ аутов]);
печать «Введите бумажник ключевую фразу (необходимый для подписания сделки):»;
Система «Запущенная -echo» и умереть "вилка / Exec: $!"; ## это может быть улучшено
мой $ WPP = <>; чавкать $ WPP; Распечатать "\ п";
Система «Запущенная эхо» и умереть "вилка / Exec: $!";
$ rPC->walletpassphrase ($ WPP, 1);
мой $ signed_tx = $ rPC->signrawtransaction ($ ТХ) ->{ 'Шестигранной'};
мой $ декодируется = $ rPC->decoderawtransaction ($ signed_tx);
Печать данных :: Dumper->Свалка (суб {\ @_} ->(\ $ Декодируется), [ 'Транзакция']);
Распечатать "Сырье: $ signed_tx \ п";
END {система «Запущенная эхо»; }
## TODO: можно добавить: если ($ плата) {печать "вы платите% d satoshis за т.п.н.", $ Плата * 1E8 / ($ tx_size / 1000); }
использовать предупреждение;
использовать строгий;
использовать File :: Spec;
использовать Скалярные :: Util дш / looks_like_number /;
Использовать список :: Util КЯ / мин сумма перетасовать /;
использовать Getopt :: Long;
использовать JSON RPC :: :: Client;
Использование Data :: Dumper;
мой $ MIN_FEE = 0,0005;
мой $ cfgfile = File :: спектрометр>catfile ($ ENV { 'НАЧАЛО'},».bitcoin', 'bitcoin.conf');
мой ($ rpcuser, $ rpcpass);
к югу get_rpc {
-е $ cfgfile или умереть "Bitcoin конфигурации не найден \ п";
открыть свой $ FD, '<», $ Cfgfile или умереть "Открывание: '$ cfgfile': $!";
в то время как (<$ FD>) {
если (/^rpcuser=(.*)/) {$ rpcuser = $ 1; }
если (/^rpcpassword=(.*)/) {$ rpcpass = $ 1; }
}
закрыть $ FD;
если (! $ rpcuser или! $ rpcpass) {умереть "не может найти RPC учетных данных в Bitcoin конфигурации \ п"; }
мой $ URL = "Http: // $ rpcuser: $ rpcpass \ @localhost: 8332 /";
мой $ = JSON RPC :: RPC :: Client->новый;
$ rPC->подготовить ($ URL, [дш /
createrawtransaction decoderawtransaction getnewaddress getrawtransaction listaddressgroupings
listunspent signrawtransaction validateaddress walletpassphrase
/]);
вернуть $ RPC;
}
к югу addr2grp {
мой ($ RPC) = @_;
мои $ группировки = $ rPC->listaddressgroupings;
мой% addr2grp;
Foreach моего $ group_idx (0 .. $ # $ группировок) {
Foreach моего $ записи (@ {$ groupings->[$ Group_idx]}) {
$ Addr2grp {$ entry->[0]} = $ group_idx;
}
}
вернуться% addr2grp;
}
суб vouts {
мой ($ RPC) = @_;
мой $ неизрасходованные = $ rPC->listunspent;
мои $ vouts;
Foreach мой $ U (@ $ неизрасходованные) {
мой $ rawtx = $ rPC->getrawtransaction ($ u->{ 'TXID'});
$ Rawtx = $ rPC->decoderawtransaction ($ rawtx);
мой $ Vout = $ rawtx->{ 'Vout'} [$ u->{ 'Vout'}];
Следующий, если «pubkeyhash» пе $ vout->{ 'ScriptPubKey'} { 'типа'} и 'scripthash' п $ vout->{ 'ScriptPubKey'} { 'типа'};
$ u->{ 'Адрес'} = $ vout->{ 'ScriptPubKey'} { 'адрес'} [0];
$ u->{ 'btcdays'} = $ и->{ 'Сумма'} * $ u->{ ''} Подтверждения / 144;
нажмите @ $ vouts, $ и;
}
вернуть $ vouts;
}
суб get_selected_outs {
мой ($ largest_out) = @_;
Распечатать "\ п";
OUTER: {
печать «Выбор входа (разделенных пробелами):»;
мой $ selected_ins = <>; чавкать $ selected_ins; мои @selected_ins = расщепленные / \ S + /, $ selected_ins;
Foreach мой $ в (@selected_ins) {
если ($ в! ~ / ^ \ d + $ /) {предупредить "Ошибка: неверный ввод «$ в» \ п"; повтор OUTER; }
если ($ в > $ Largest_out) {предупредить "Ошибка: ввод «$ в» слишком большой \ п"; повтор OUTER; }
}
вернуться @selected_ins;
}
}
суб get_dests {
мой ($ RPC, $ помогло) = @_;
мои% dests;
Распечатать "\ NВведите выходы: адрес получателя и количество разделенных пробелом (ввод, чтобы закончить) \ П";
в то время как (1) {
Распечатать "Введите выход (доступный $) безрезультатно: ";
мой $ = Dest <>; чавкать $ Dest;
если (! длина $ Dest) {
последний, если% dests;
предупреждать "введите по крайней мере один пункт назначения \ п";
повтор;
}
мой ($ dest_addr, $ dest_amnt) = разделить / \ s + /, $ Dest;
если (! $ определено dest_amnt) {
Распечатать "Ошибка: введите адрес получателя и количество разделенного пространства \ п";
следующий;
}
если (! looks_like_number $ dest_amnt) {предупредить "сумма «$ dest_amnt» не является числом \ п"; повтор; }
если ($ dest_amnt <= 0) {предупредить "сумма «$ dest_amnt» не является положительным \ п"; повтор; }
если ( 'новый' эк $ dest_addr) {
$ Dest_addr = $ rPC->getnewaddress;
Распечатать "Использование адреса «$ dest_addr» \ п";
}
если (! $ rPC->validateaddress ($ dest_addr) ->{ 'IsValid'}) {предупредить "адрес «$ dest_addr» недействительно \ п"; повтор; }
если (существует $ dests {$ dest_addr}) {предупредить "есть уже выход на этот адрес \ п"; повтор; }
если ($ dest_amnt > $ Помогло) {предупредить "Ошибка: не хватает средств на выбранных входов \ п"; повтор; }
$ dests {$ dest_addr} = 0 + $ dest_amnt;
$ = 0 помогло + Sprintf '% .8f', $ помогло - $ dest_amnt;
не последний, если $ безрезультатно;
}
Распечатать "\ п";
вернуться% dests;
}
к югу плата {
мой (выбран $, $ dests, $ change_addr) = @_;
мой $ tx_size = 10 + 180 * @ $ выбранных + 32 * ключи% $ dests;
Распечатать " Debug: оценивается размер сделки: $ tx_size байт (платная на 10000 байт или больше) \ п";
мой $ tx_size_ok = $ tx_size < 10000;
мои $ smallest_out = мин значения% $ dests;
мой $ out_amounts_ok = $ smallest_out >= 0,01;
мой $ tx_prio = карта сумма {$ _->{ 'Сумма'} * 10e8 * $ _->{ 'Подтверждения'}} @ $ выбрана;
$ Tx_prio / = $ tx_size;
мой $ tx_prio_ok = $ tx_prio > 57_600_000;
Printf " Debug: приоритет транзакции:% .2fM (платная в 57.6M или меньше) \ п", $ Tx_prio / 1E6;
мой $ sugg_fee = 0;
если (! $ tx_size_ok ||! $ out_amounts_ok) {
если (! $ tx_size_ok) {печать " Сделка слишком большой ($ tx_size байт), плата рекомендуется \ п"; }
если (! $ out_amounts_ok) {печать " Некоторые из выходов меньше 0,01 BTC ($ smallest_out), вознаграждение рекомендуется \ п"; }
мой $ rounded_tx_size = INT ($ tx_size / 1000); $ Rounded_tx_size ++;
$ Sugg_fee = $ MIN_FEE * $ rounded_tx_size;
}
если (! $ tx_prio_ok) {
Распечатать " Приоритет сделки слишком низкая ($ tx_prio), плата рекомендуется \ п";
$ Sugg_fee + = $ MIN_FEE;
}
Распечатать " Внимание: плата рекомендуются, но эта сделка не имеет выхода изменения, из которого вычтет плату \ п" если $ sugg_fee && ! $ Change_addr;
Распечатать " Предупреждение: предложили гонорар больше, чем выходное изменение \ п" если $ change_addr и $ sugg_fee > $ dests->{$ Change_addr};
Распечатать "\ NВведите желаемую плата (по умолчанию $ sugg_fee): "; мой $ плата = <>; $ Плата за чавкать; $ Плата || = $ sugg_fee;
если (! $ плату) {
Распечатать " Внимание: рекомендуется плата \ п" если $ sugg_fee;
вернуть;
}
умереть "Ошибка: нет выходного изменения, из которого вычтет плату \ п" если $ плата && ! $ Change_addr;
умереть "Ошибка: плата больше, чем выходное изменение \ п" если $ change_addr и $ плата > $ dests->{$ Change_addr};
если ($ стоимость == $ dests->{$ Change_addr}) {
удалить $ dests->{$ Change_addr}; ## упс, это изменяет размер ТХ, поэтому она потенциально влияет на саму плату
} Еще {
$ dests->{$ Change_addr} - = $ плата;
}
}
################################################## #
GetOptions \ Мои% Opts, '--list' или умереть "Getopt не удалось \ п";
мой $ = get_rpc RPC;
мой% addr_to_group = addr2grp $ RPC;
мой $ vouts = vouts $ или сделать RPC {печати "Никакие средства не \ п"; Выход; };
Printf кв.кв /% 3s% 12s% 35s% 8s% 3s% 66s \ п /, QW / IDX количество адресов btcdays GRP Vout /;
мой $ Индекс = 0;
@ $ Vouts = реверс рода {$ a->{'количество'} <знак равно> $ b->{ 'Сумма'}} @ $ vouts;
Foreach мой $ Vout (@ $ vouts) {
# Мой $ AMNT = $ vout->{'количество'}; если ($ AMNT ~ /\./!) {$ AMNT =. ''; } $ AMNT = '00000000'. $ AMNT = ~ s / (\ .. {8}) * / $ 1 /.
мой $ AMNT = Sprintf '% .8f', $ vout->{'количество'};
Printf кв.кв /% 2s)% 12s% 35s% 8.2f% 3s% s:% s \ п /, $ индекс, $ AMNT, @ $ Vout {дш / адрес btcdays /} $ addr_to_group {$ vout->{ 'Адрес'}} @ $ {Vout дш / TXID Vout /};
$ Индекс ++;
}
выход, если $ выбирает { «список»};
мой @selected_ins = get_selected_outs $ # $ vouts;
мой @selected = @ $ vouts [@selected_ins];
мой $ available_amnt = карта сумма {$ _->{ 'Сумма'}} @selected;
мой% dests = get_dests $ RPC, $ available_amnt;
мой $ txamnt = сумма значений% dests;
мой $ нераспределенные = Sprintf '% .8f', $ available_amnt - $ txamnt;
мой $ change_addr;
если ($ Unassigned >= 1e-8) {
## $ Unassigned может иметь дополнительные десятичные места из-за проблемы с плавающей точкой, увидеть, если эти десятичные дроби
## уже присутствуют в этих переменных, или они появляются в вычитании выше
Распечатать " Debug: входы общая сумма '$ available_amnt', присваивается '$ txamnt' \ п \ п";
{
Распечатать "Введите адрес, куда отправить $ присвоенных в качестве изменения: "; $ Change_addr = <>; чавкать $ change_addr;
если ( 'новый' эк $ change_addr) {
$ Change_addr = $ rPC->getnewaddress;
Распечатать "\ П Изменение будет идти в «$ change_addr» \ п";
}
если (! $ rPC->validateaddress ($ change_addr) ->{ 'IsValid'}) {предупредить "адрес «$ change_addr» недействительно \ п"; повтор; }
если (существует $ dests {$ change_addr}) {предупредить "есть уже выход на этот адрес \ п"; повтор; }
$ Dests {$ change_addr} = 0 + $ неприсвоенный;
последний;
}
Распечатать "\ п";
}
плата \ @selected, \% dests, $ change_addr;
мои $ INS = [перетасовать карты {{TXID => $ _->{ 'TXID'}, Vout => 0 + $ _->{ 'Vout'}}} @selected];
мои $ ауты = \% dests;
мой $ Тх = $ rPC->createrawtransaction ([$ ины, $ аутов]);
печать «Введите бумажник ключевую фразу (необходимый для подписания сделки):»;
Система «Запущенная -echo» и умереть "вилка / Exec: $!"; ## это может быть улучшено
мой $ WPP = <>; чавкать $ WPP; Распечатать "\ п";
Система «Запущенная эхо» и умереть "вилка / Exec: $!";
$ rPC->walletpassphrase ($ WPP, 1);
мой $ signed_tx = $ rPC->signrawtransaction ($ ТХ) ->{ 'Шестигранной'};
мой $ декодируется = $ rPC->decoderawtransaction ($ signed_tx);
Печать данных :: Dumper->Свалка (суб {\ @_} ->(\ $ Декодируется), [ 'Транзакция']);
Распечатать "Сырье: $ signed_tx \ п";
END {система «Запущенная эхо»; }