2023-08-16 19:27:31 +02:00
// Copyright (c) 2009-2020 The Bitcoin Core developers
2014-12-13 05:09:33 +01:00
// Distributed under the MIT software license, see the accompanying
2015-04-03 00:51:08 +02:00
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
2016-02-04 13:41:58 +01:00
# if defined(HAVE_CONFIG_H)
2022-08-02 18:34:58 +02:00
# include <config/bitcoin-config.h>
2016-02-04 13:41:58 +01:00
# endif
2021-10-25 15:55:34 +02:00
# include <chainparams.h>
2020-03-19 23:46:56 +01:00
# include <clientversion.h>
# include <coins.h>
2022-06-13 21:43:22 +02:00
# include <compat.h>
2020-03-19 23:46:56 +01:00
# include <consensus/consensus.h>
# include <core_io.h>
Merge #11372: Address encoding cleanup
92f1f8b31 Split off key_io_tests from base58_tests (Pieter Wuille)
119b0f85e Split key_io (address/key encodings) off from base58 (Pieter Wuille)
ebfe217b1 Stop using CBase58Data for ext keys (Pieter Wuille)
32e69fa0d Replace CBitcoinSecret with {Encode,Decode}Secret (Pieter Wuille)
Pull request description:
This PR contains some of the changes left as TODO in #11167 (and built on top of that PR). They are not intended for backporting.
This removes the `CBase58`, `CBitcoinSecret`, `CBitcoinExtKey`, and `CBitcoinExtPubKey` classes, in favor of simple `Encode`/`Decode` functions. Furthermore, all Bitcoin-specific logic (addresses, WIF, BIP32) is moved to `key_io.{h,cpp}`, leaving `base58.{h,cpp}` as a pure utility that implements the base58 encoding/decoding logic.
Tree-SHA512: a5962c0ed27ad53cbe00f22af432cf11aa530e3efc9798e25c004bc9ed1b5673db5df3956e398ee2c085e3a136ac8da69fe7a7d97a05fb2eb3be0b60d0479655
Make linter happy
Dashify
2018-03-07 00:04:56 +01:00
# include <key_io.h>
2020-03-19 23:46:56 +01:00
# include <primitives/transaction.h>
# include <script/script.h>
# include <script/sign.h>
2022-07-13 05:46:31 +02:00
# include <script/signingprovider.h>
2015-09-04 16:11:34 +02:00
# include <univalue.h>
2021-06-27 08:33:13 +02:00
# include <util/moneystr.h>
# include <util/strencodings.h>
2022-12-15 20:17:05 +01:00
# include <util/string.h>
2022-03-24 05:13:51 +01:00
# include <util/system.h>
# include <util/translation.h>
2015-04-03 00:51:08 +02:00
2022-03-24 05:13:51 +01:00
# include <functional>
2018-04-02 20:31:40 +02:00
# include <memory>
fix: add missing includes and remove obsolete includes (#5562)
## Issue being fixed or feature implemented
Some headers or modules are used objects from STL without including it
directly, it cause compilation failures on some platforms for some
specific compilers such as #5554
## What was done?
Added missing includes and removed obsolete includes for `optional`,
`deque`, `tuple`, `unordered_set`, `unordered_map`, `set` and `atomic`.
Please, note, that this PR doesn't cover all cases, only cases when it
is obviously missing or obviously obsolete.
Also most of changes belongs to to dash specific code; but for cases of
original bitcoin code I keep it untouched, such as missing <map> in
`src/psbt.h`
I used this script to get a list of files/headers which looks suspicious
`./headers-scanner.sh std::optional optional`:
```bash
#!/bin/bash
set -e
function check_includes() {
obj=$1
header=$2
file=$3
used=0
included=0
grep "$obj" "$file" >/dev/null 2>/dev/null && used=1
grep "include <$header>" $file >/dev/null 2>/dev/null && included=1
if [ $used == 1 ] && [ $included == 0 ]
then echo "missing <$header> in $file"
fi
if [ $used == 0 ] && [ $included == 1 ]
then echo "obsolete <$header> in $file"
fi
}
export -f check_includes
obj=$1
header=$2
find src \( -name '*.h' -or -name '*.cpp' -or -name '*.hpp' \) -exec bash -c 'check_includes "$0" "$1" "$2"' "$obj" "$header" {} \;
```
## How Has This Been Tested?
Built code locally
## Breaking Changes
n/a
## Checklist:
- [x] I have performed a self-review of my own code
- [ ] I have commented my code, particularly in hard-to-understand areas
- [ ] I have added or updated relevant unit/integration/functional/e2e
tests
- [ ] I have made corresponding changes to the documentation
- [x] I have assigned this pull request to a milestone
2023-09-07 16:07:02 +02:00
# include <optional>
2015-04-03 00:51:08 +02:00
# include <stdio.h>
2020-03-19 23:46:56 +01:00
# include <stacktraces.h>
2019-02-21 19:37:16 +01:00
2015-04-03 00:51:08 +02:00
static bool fCreateBlank ;
2016-11-25 11:33:05 +01:00
static std : : map < std : : string , UniValue > registers ;
2016-11-11 06:16:39 +01:00
static const int CONTINUE_EXECUTION = - 1 ;
2015-04-03 00:51:08 +02:00
2018-08-25 20:20:30 +02:00
const std : : function < std : : string ( const char * ) > G_TRANSLATION_FUN = nullptr ;
2022-05-21 10:27:30 +02:00
static void SetupBitcoinTxArgs ( ArgsManager & argsman )
2021-03-19 16:00:24 +01:00
{
2022-05-21 10:27:30 +02:00
SetupHelpOptions ( argsman ) ;
2022-05-21 10:12:13 +02:00
2020-12-07 10:15:32 +01:00
argsman . AddArg ( " -version " , " Print version and exit " , ArgsManager : : ALLOW_ANY , OptionsCategory : : OPTIONS ) ;
2022-05-21 10:27:30 +02:00
argsman . AddArg ( " -create " , " Create new, empty TX. " , ArgsManager : : ALLOW_ANY , OptionsCategory : : OPTIONS ) ;
argsman . AddArg ( " -json " , " Select JSON output " , ArgsManager : : ALLOW_ANY , OptionsCategory : : OPTIONS ) ;
argsman . AddArg ( " -txid " , " Output only the hex-encoded transaction id of the resultant transaction. " , ArgsManager : : ALLOW_ANY , OptionsCategory : : OPTIONS ) ;
SetupChainParamsBaseOptions ( argsman ) ;
2021-03-19 16:00:24 +01:00
2022-05-21 10:27:30 +02:00
argsman . AddArg ( " delin=N " , " Delete input N from TX " , ArgsManager : : ALLOW_ANY , OptionsCategory : : COMMANDS ) ;
argsman . AddArg ( " delout=N " , " Delete output N from TX " , ArgsManager : : ALLOW_ANY , OptionsCategory : : COMMANDS ) ;
argsman . AddArg ( " in=TXID:VOUT(:SEQUENCE_NUMBER) " , " Add input to TX " , ArgsManager : : ALLOW_ANY , OptionsCategory : : COMMANDS ) ;
argsman . AddArg ( " locktime=N " , " Set TX lock time to N " , ArgsManager : : ALLOW_ANY , OptionsCategory : : COMMANDS ) ;
argsman . AddArg ( " nversion=N " , " Set TX version to N " , ArgsManager : : ALLOW_ANY , OptionsCategory : : COMMANDS ) ;
argsman . AddArg ( " outaddr=VALUE:ADDRESS " , " Add address-based output to TX " , ArgsManager : : ALLOW_ANY , OptionsCategory : : COMMANDS ) ;
argsman . AddArg ( " outdata=[VALUE:]DATA " , " Add data-based output to TX " , ArgsManager : : ALLOW_ANY , OptionsCategory : : COMMANDS ) ;
argsman . AddArg ( " outmultisig=VALUE:REQUIRED:PUBKEYS:PUBKEY1:PUBKEY2:....[:FLAGS] " , " Add Pay To n-of-m Multi-sig output to TX. n = REQUIRED, m = PUBKEYS. "
merge bitcoin#16097: Add Flags enum to ArgsManager class (#4569)
* merge bitcoin#16097: Check IsArgKnown() early
* merge bitcoin#16097: Refactor InterpretNegatedOption() function
* merge bitcoin#16097: Add Flags enum to ArgsManager
* scripted-diff: Use Flags enum in AddArg()
-BEGIN VERIFY SCRIPT-
sed -i 's/const bool debug_only,/unsigned int flags, &/' src/util/system.h src/util/system.cpp
sed -i -E 's/(true|false), OptionsCategory::/ArgsManager::ALLOW_ANY, &/' $(git grep --files-with-matches 'AddArg(' src)
-END VERIFY SCRIPT-
* scripted-diff: Use ArgsManager::DEBUG_ONLY flag
-BEGIN VERIFY SCRIPT-
sed -i 's/unsigned int flags, const bool debug_only,/unsigned int flags,/' src/util/system.h src/util/system.cpp
sed -i 's/ArgsManager::NONE, debug_only/flags, false/' src/util/system.cpp
sed -i 's/arg.second.m_debug_only/(arg.second.m_flags \& ArgsManager::DEBUG_ONLY)/' src/util/system.cpp
sed -i 's/ArgsManager::ALLOW_ANY, true, OptionsCategory::/ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::/' $(git grep --files-with-matches 'AddArg(' src)
sed -i 's/ArgsManager::ALLOW_ANY, false, OptionsCategory::/ArgsManager::ALLOW_ANY, OptionsCategory::/' $(git grep --files-with-matches 'AddArg(' src)
-END VERIFY SCRIPT-
* merge bitcoin#16097: Remove unused m_debug_only member from Arg struct
* merge bitcoin#16097: Use ArgsManager::NETWORK_ONLY flag
* merge bitcoin#16097: Replace IsArgKnown() with FlagsOfKnownArg()
* merge bitcoin#16097: Revamp option negating policy
* merge bitcoin#16097: Make tests arg type specific
2021-11-13 01:25:46 +01:00
" Optionally add the \" S \" flag to wrap the output in a pay-to-script-hash. " , ArgsManager : : ALLOW_ANY , OptionsCategory : : COMMANDS ) ;
2022-05-21 10:27:30 +02:00
argsman . AddArg ( " outpubkey=VALUE:PUBKEY[:FLAGS] " , " Add pay-to-pubkey output to TX. "
merge bitcoin#16097: Add Flags enum to ArgsManager class (#4569)
* merge bitcoin#16097: Check IsArgKnown() early
* merge bitcoin#16097: Refactor InterpretNegatedOption() function
* merge bitcoin#16097: Add Flags enum to ArgsManager
* scripted-diff: Use Flags enum in AddArg()
-BEGIN VERIFY SCRIPT-
sed -i 's/const bool debug_only,/unsigned int flags, &/' src/util/system.h src/util/system.cpp
sed -i -E 's/(true|false), OptionsCategory::/ArgsManager::ALLOW_ANY, &/' $(git grep --files-with-matches 'AddArg(' src)
-END VERIFY SCRIPT-
* scripted-diff: Use ArgsManager::DEBUG_ONLY flag
-BEGIN VERIFY SCRIPT-
sed -i 's/unsigned int flags, const bool debug_only,/unsigned int flags,/' src/util/system.h src/util/system.cpp
sed -i 's/ArgsManager::NONE, debug_only/flags, false/' src/util/system.cpp
sed -i 's/arg.second.m_debug_only/(arg.second.m_flags \& ArgsManager::DEBUG_ONLY)/' src/util/system.cpp
sed -i 's/ArgsManager::ALLOW_ANY, true, OptionsCategory::/ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::/' $(git grep --files-with-matches 'AddArg(' src)
sed -i 's/ArgsManager::ALLOW_ANY, false, OptionsCategory::/ArgsManager::ALLOW_ANY, OptionsCategory::/' $(git grep --files-with-matches 'AddArg(' src)
-END VERIFY SCRIPT-
* merge bitcoin#16097: Remove unused m_debug_only member from Arg struct
* merge bitcoin#16097: Use ArgsManager::NETWORK_ONLY flag
* merge bitcoin#16097: Replace IsArgKnown() with FlagsOfKnownArg()
* merge bitcoin#16097: Revamp option negating policy
* merge bitcoin#16097: Make tests arg type specific
2021-11-13 01:25:46 +01:00
" Optionally add the \" S \" flag to wrap the output in a pay-to-script-hash. " , ArgsManager : : ALLOW_ANY , OptionsCategory : : COMMANDS ) ;
2022-05-21 10:27:30 +02:00
argsman . AddArg ( " outscript=VALUE:SCRIPT[:FLAGS] " , " Add raw script output to TX. "
merge bitcoin#16097: Add Flags enum to ArgsManager class (#4569)
* merge bitcoin#16097: Check IsArgKnown() early
* merge bitcoin#16097: Refactor InterpretNegatedOption() function
* merge bitcoin#16097: Add Flags enum to ArgsManager
* scripted-diff: Use Flags enum in AddArg()
-BEGIN VERIFY SCRIPT-
sed -i 's/const bool debug_only,/unsigned int flags, &/' src/util/system.h src/util/system.cpp
sed -i -E 's/(true|false), OptionsCategory::/ArgsManager::ALLOW_ANY, &/' $(git grep --files-with-matches 'AddArg(' src)
-END VERIFY SCRIPT-
* scripted-diff: Use ArgsManager::DEBUG_ONLY flag
-BEGIN VERIFY SCRIPT-
sed -i 's/unsigned int flags, const bool debug_only,/unsigned int flags,/' src/util/system.h src/util/system.cpp
sed -i 's/ArgsManager::NONE, debug_only/flags, false/' src/util/system.cpp
sed -i 's/arg.second.m_debug_only/(arg.second.m_flags \& ArgsManager::DEBUG_ONLY)/' src/util/system.cpp
sed -i 's/ArgsManager::ALLOW_ANY, true, OptionsCategory::/ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::/' $(git grep --files-with-matches 'AddArg(' src)
sed -i 's/ArgsManager::ALLOW_ANY, false, OptionsCategory::/ArgsManager::ALLOW_ANY, OptionsCategory::/' $(git grep --files-with-matches 'AddArg(' src)
-END VERIFY SCRIPT-
* merge bitcoin#16097: Remove unused m_debug_only member from Arg struct
* merge bitcoin#16097: Use ArgsManager::NETWORK_ONLY flag
* merge bitcoin#16097: Replace IsArgKnown() with FlagsOfKnownArg()
* merge bitcoin#16097: Revamp option negating policy
* merge bitcoin#16097: Make tests arg type specific
2021-11-13 01:25:46 +01:00
" Optionally add the \" S \" flag to wrap the output in a pay-to-script-hash. " , ArgsManager : : ALLOW_ANY , OptionsCategory : : COMMANDS ) ;
2022-05-21 10:27:30 +02:00
argsman . AddArg ( " sign=SIGHASH-FLAGS " , " Add zero or more signatures to transaction. "
2021-03-19 18:23:58 +01:00
" This command requires JSON registers: "
" prevtxs=JSON object, "
" privatekeys=JSON object. "
merge bitcoin#16097: Add Flags enum to ArgsManager class (#4569)
* merge bitcoin#16097: Check IsArgKnown() early
* merge bitcoin#16097: Refactor InterpretNegatedOption() function
* merge bitcoin#16097: Add Flags enum to ArgsManager
* scripted-diff: Use Flags enum in AddArg()
-BEGIN VERIFY SCRIPT-
sed -i 's/const bool debug_only,/unsigned int flags, &/' src/util/system.h src/util/system.cpp
sed -i -E 's/(true|false), OptionsCategory::/ArgsManager::ALLOW_ANY, &/' $(git grep --files-with-matches 'AddArg(' src)
-END VERIFY SCRIPT-
* scripted-diff: Use ArgsManager::DEBUG_ONLY flag
-BEGIN VERIFY SCRIPT-
sed -i 's/unsigned int flags, const bool debug_only,/unsigned int flags,/' src/util/system.h src/util/system.cpp
sed -i 's/ArgsManager::NONE, debug_only/flags, false/' src/util/system.cpp
sed -i 's/arg.second.m_debug_only/(arg.second.m_flags \& ArgsManager::DEBUG_ONLY)/' src/util/system.cpp
sed -i 's/ArgsManager::ALLOW_ANY, true, OptionsCategory::/ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::/' $(git grep --files-with-matches 'AddArg(' src)
sed -i 's/ArgsManager::ALLOW_ANY, false, OptionsCategory::/ArgsManager::ALLOW_ANY, OptionsCategory::/' $(git grep --files-with-matches 'AddArg(' src)
-END VERIFY SCRIPT-
* merge bitcoin#16097: Remove unused m_debug_only member from Arg struct
* merge bitcoin#16097: Use ArgsManager::NETWORK_ONLY flag
* merge bitcoin#16097: Replace IsArgKnown() with FlagsOfKnownArg()
* merge bitcoin#16097: Revamp option negating policy
* merge bitcoin#16097: Make tests arg type specific
2021-11-13 01:25:46 +01:00
" See signrawtransactionwithkey docs for format of sighash flags, JSON objects. " , ArgsManager : : ALLOW_ANY , OptionsCategory : : COMMANDS ) ;
2021-03-19 18:23:58 +01:00
2022-05-21 10:27:30 +02:00
argsman . AddArg ( " load=NAME:FILENAME " , " Load JSON file FILENAME into register NAME " , ArgsManager : : ALLOW_ANY , OptionsCategory : : REGISTER_COMMANDS ) ;
argsman . AddArg ( " set=NAME:JSON-STRING " , " Set register NAME to given JSON-STRING " , ArgsManager : : ALLOW_ANY , OptionsCategory : : REGISTER_COMMANDS ) ;
2021-03-19 16:00:24 +01:00
}
2016-11-11 06:16:39 +01:00
//
// This function returns either one of EXIT_ codes when it's expected to stop the process or
// CONTINUE_EXECUTION when it's expected to continue further.
//
static int AppInitRawTx ( int argc , char * argv [ ] )
2015-04-03 00:51:08 +02:00
{
//
// Parameters
//
2022-05-21 10:27:30 +02:00
SetupBitcoinTxArgs ( gArgs ) ;
2018-05-30 19:42:58 +02:00
std : : string error ;
if ( ! gArgs . ParseParameters ( argc , argv , error ) ) {
2022-03-21 18:28:10 +01:00
tfm : : format ( std : : cerr , " Error parsing command line arguments: %s \n " , error ) ;
2018-05-30 19:42:58 +02:00
return EXIT_FAILURE ;
}
2015-04-03 00:51:08 +02:00
2019-07-02 06:16:11 +02:00
if ( gArgs . IsArgSet ( " -printcrashinfo " ) ) {
std : : cout < < GetCrashInfoStrFromSerializedStr ( gArgs . GetArg ( " -printcrashinfo " , " " ) ) < < std : : endl ;
return true ;
}
2019-09-10 11:42:52 +02:00
// Check for -chain, -testnet or -regtest parameter (Params() calls are only valid after this clause)
2015-05-25 09:00:17 +02:00
try {
2020-04-29 12:16:37 +02:00
SelectParams ( gArgs . GetChainName ( ) ) ;
2015-10-27 17:39:42 +01:00
} catch ( const std : : exception & e ) {
2021-10-24 12:51:47 +02:00
tfm : : format ( std : : cerr , " Error: %s \n " , e . what ( ) ) ;
2016-11-11 06:16:39 +01:00
return EXIT_FAILURE ;
2015-04-03 00:51:08 +02:00
}
2019-06-24 18:44:27 +02:00
fCreateBlank = gArgs . GetBoolArg ( " -create " , false ) ;
2015-04-03 00:51:08 +02:00
2020-12-07 10:15:32 +01:00
if ( argc < 2 | | HelpRequested ( gArgs ) | | gArgs . IsArgSet ( " -version " ) ) {
2015-04-03 00:51:08 +02:00
// First part of help message is specific to this utility
2020-12-07 10:15:32 +01:00
std : : string strUsage = PACKAGE_NAME " dash-tx utility version " + FormatFullVersion ( ) + " \n " ;
if ( ! gArgs . IsArgSet ( " -version " ) ) {
strUsage + = " \n "
" Usage: dash-tx [options] <hex-tx> [commands] Update hex-encoded dash transaction \n "
" or: dash-tx [options] -create [commands] Create hex-encoded dash transaction \n "
" \n " ;
strUsage + = gArgs . GetHelpMessage ( ) ;
}
2015-04-03 00:51:08 +02:00
2022-03-21 18:28:10 +01:00
tfm : : format ( std : : cout , " %s " , strUsage ) ;
2015-04-03 00:51:08 +02:00
2016-11-11 06:16:39 +01:00
if ( argc < 2 ) {
2021-10-24 12:51:47 +02:00
tfm : : format ( std : : cerr , " Error: too few parameters \n " ) ;
2016-11-11 06:16:39 +01:00
return EXIT_FAILURE ;
}
return EXIT_SUCCESS ;
2015-04-03 00:51:08 +02:00
}
2016-11-11 06:16:39 +01:00
return CONTINUE_EXECUTION ;
2015-04-03 00:51:08 +02:00
}
2016-11-25 11:33:05 +01:00
static void RegisterSetJson ( const std : : string & key , const std : : string & rawJson )
2015-04-03 00:51:08 +02:00
{
UniValue val ;
if ( ! val . read ( rawJson ) ) {
2016-11-25 11:33:05 +01:00
std : : string strErr = " Cannot parse JSON for key " + key ;
throw std : : runtime_error ( strErr ) ;
2015-04-03 00:51:08 +02:00
}
registers [ key ] = val ;
}
2016-11-25 11:33:05 +01:00
static void RegisterSet ( const std : : string & strInput )
2015-04-03 00:51:08 +02:00
{
// separate NAME:VALUE in string
size_t pos = strInput . find ( ' : ' ) ;
2016-11-25 11:33:05 +01:00
if ( ( pos = = std : : string : : npos ) | |
2015-04-03 00:51:08 +02:00
( pos = = 0 ) | |
( pos = = ( strInput . size ( ) - 1 ) ) )
2016-11-25 11:33:05 +01:00
throw std : : runtime_error ( " Register input requires NAME:VALUE " ) ;
2015-04-03 00:51:08 +02:00
2016-11-25 11:33:05 +01:00
std : : string key = strInput . substr ( 0 , pos ) ;
std : : string valStr = strInput . substr ( pos + 1 , std : : string : : npos ) ;
2015-04-03 00:51:08 +02:00
RegisterSetJson ( key , valStr ) ;
}
2016-11-25 11:33:05 +01:00
static void RegisterLoad ( const std : : string & strInput )
2015-04-03 00:51:08 +02:00
{
// separate NAME:FILENAME in string
size_t pos = strInput . find ( ' : ' ) ;
2016-11-25 11:33:05 +01:00
if ( ( pos = = std : : string : : npos ) | |
2015-04-03 00:51:08 +02:00
( pos = = 0 ) | |
( pos = = ( strInput . size ( ) - 1 ) ) )
2016-11-25 11:33:05 +01:00
throw std : : runtime_error ( " Register load requires NAME:FILENAME " ) ;
2015-04-03 00:51:08 +02:00
2016-11-25 11:33:05 +01:00
std : : string key = strInput . substr ( 0 , pos ) ;
std : : string filename = strInput . substr ( pos + 1 , std : : string : : npos ) ;
2015-04-03 00:51:08 +02:00
FILE * f = fopen ( filename . c_str ( ) , " r " ) ;
if ( ! f ) {
2016-11-25 11:33:05 +01:00
std : : string strErr = " Cannot open file " + filename ;
throw std : : runtime_error ( strErr ) ;
2015-04-03 00:51:08 +02:00
}
// load file chunks into one big buffer
2016-11-25 11:33:05 +01:00
std : : string valStr ;
2015-04-03 00:51:08 +02:00
while ( ( ! feof ( f ) ) & & ( ! ferror ( f ) ) ) {
char buf [ 4096 ] ;
int bread = fread ( buf , 1 , sizeof ( buf ) , f ) ;
if ( bread < = 0 )
break ;
valStr . insert ( valStr . size ( ) , buf , bread ) ;
}
2015-07-28 20:01:00 +02:00
int error = ferror ( f ) ;
fclose ( f ) ;
if ( error ) {
2016-11-25 11:33:05 +01:00
std : : string strErr = " Error reading file " + filename ;
throw std : : runtime_error ( strErr ) ;
2015-04-03 00:51:08 +02:00
}
// evaluate as JSON buffer register
RegisterSetJson ( key , valStr ) ;
}
2017-01-12 12:24:25 +01:00
static CAmount ExtractAndValidateValue ( const std : : string & strValue )
{
2022-12-20 17:14:58 +01:00
if ( std : : optional < CAmount > parsed = ParseMoney ( strValue ) ) {
return parsed . value ( ) ;
} else {
2017-01-12 12:24:25 +01:00
throw std : : runtime_error ( " invalid TX output value " ) ;
2022-12-20 17:14:58 +01:00
}
2017-01-12 12:24:25 +01:00
}
2016-11-25 11:33:05 +01:00
static void MutateTxVersion ( CMutableTransaction & tx , const std : : string & cmdVal )
2015-04-03 00:51:08 +02:00
{
2018-07-09 19:56:59 +02:00
int64_t newVersion ;
if ( ! ParseInt64 ( cmdVal , & newVersion ) | | newVersion < 1 | | newVersion > CTransaction : : MAX_STANDARD_VERSION )
throw std : : runtime_error ( " Invalid TX version requested: ' " + cmdVal + " ' " ) ;
2015-04-03 00:51:08 +02:00
tx . nVersion = ( int ) newVersion ;
}
2016-11-25 11:33:05 +01:00
static void MutateTxLocktime ( CMutableTransaction & tx , const std : : string & cmdVal )
2015-04-03 00:51:08 +02:00
{
2018-07-09 19:56:59 +02:00
int64_t newLocktime ;
if ( ! ParseInt64 ( cmdVal , & newLocktime ) | | newLocktime < 0LL | | newLocktime > 0xffffffffLL )
throw std : : runtime_error ( " Invalid TX locktime requested: ' " + cmdVal + " ' " ) ;
2015-04-03 00:51:08 +02:00
tx . nLockTime = ( unsigned int ) newLocktime ;
}
2016-11-25 11:33:05 +01:00
static void MutateTxAddInput ( CMutableTransaction & tx , const std : : string & strInput )
2015-04-03 00:51:08 +02:00
{
2022-12-24 14:35:24 +01:00
std : : vector < std : : string > vStrInputParts = SplitString ( strInput , ' : ' ) ;
2016-06-07 18:25:10 +02:00
2015-04-03 00:51:08 +02:00
// separate TXID:VOUT in string
2016-06-07 18:25:10 +02:00
if ( vStrInputParts . size ( ) < 2 )
2016-11-25 11:33:05 +01:00
throw std : : runtime_error ( " TX input missing separator " ) ;
2015-04-03 00:51:08 +02:00
// extract and validate TXID
2018-09-27 17:26:17 +02:00
uint256 txid ;
if ( ! ParseHashStr ( vStrInputParts [ 0 ] , txid ) ) {
2016-11-25 11:33:05 +01:00
throw std : : runtime_error ( " invalid TX input txid " ) ;
2018-09-27 17:26:17 +02:00
}
2015-04-03 00:51:08 +02:00
static const unsigned int minTxOutSz = 9 ;
2020-12-15 22:54:51 +01:00
static const unsigned int maxVout = MaxBlockSize ( ) / minTxOutSz ;
2015-04-03 00:51:08 +02:00
// extract and validate vout
2018-07-09 19:56:59 +02:00
const std : : string & strVout = vStrInputParts [ 1 ] ;
int64_t vout ;
if ( ! ParseInt64 ( strVout , & vout ) | | vout < 0 | | vout > static_cast < int64_t > ( maxVout ) )
throw std : : runtime_error ( " invalid TX input vout ' " + strVout + " ' " ) ;
2015-04-03 00:51:08 +02:00
2016-06-07 18:25:10 +02:00
// extract the optional sequence number
2021-07-28 16:16:46 +02:00
uint32_t nSequenceIn = CTxIn : : SEQUENCE_FINAL ;
2016-06-07 18:25:10 +02:00
if ( vStrInputParts . size ( ) > 2 )
2016-06-08 09:58:15 +02:00
nSequenceIn = std : : stoul ( vStrInputParts [ 2 ] ) ;
2016-06-07 18:25:10 +02:00
2015-04-03 00:51:08 +02:00
// append to transaction input list
2016-06-07 18:25:10 +02:00
CTxIn txin ( txid , vout , CScript ( ) , nSequenceIn ) ;
2015-04-03 00:51:08 +02:00
tx . vin . push_back ( txin ) ;
}
2016-11-25 11:33:05 +01:00
static void MutateTxAddOutAddr ( CMutableTransaction & tx , const std : : string & strInput )
2015-04-03 00:51:08 +02:00
{
2017-01-12 12:24:25 +01:00
// Separate into VALUE:ADDRESS
2022-12-24 14:35:24 +01:00
std : : vector < std : : string > vStrInputParts = SplitString ( strInput , ' : ' ) ;
2015-04-03 00:51:08 +02:00
2017-03-31 10:18:14 +02:00
if ( vStrInputParts . size ( ) ! = 2 )
throw std : : runtime_error ( " TX output missing or too many separators " ) ;
2017-01-12 12:24:25 +01:00
// Extract and validate VALUE
CAmount value = ExtractAndValidateValue ( vStrInputParts [ 0 ] ) ;
2015-04-03 00:51:08 +02:00
// extract and validate ADDRESS
2017-01-12 12:24:25 +01:00
std : : string strAddr = vStrInputParts [ 1 ] ;
Merge #11117: Prepare for non-Base58 addresses (#3294)
* Merge #11117: Prepare for non-Base58 addresses
864cd2787 Move CBitcoinAddress to base58.cpp (Pieter Wuille)
5c8ff0d44 Introduce wrappers around CBitcoinAddress (Pieter Wuille)
Pull request description:
This patch removes the need for the intermediary Base58 type `CBitcoinAddress`, by providing {`Encode`,`Decode`,`IsValid`}`Destination` functions that directly operate on the conversion between `std::string`s and `CTxDestination`.
As a side, it also fixes a number of indentation issues, and removes probably several unnecessary implicit `CTxDestination`<->`CBitcoinAddress` conversions.
This change is far from complete. In follow-ups I'd like to:
* Split off the specific address and key encoding logic from base58.h, and move it to a address.h or so.
* Replace `CTxDestination` with a non-`boost::variant` version (which can be more efficient as `boost::variant` allocates everything on the heap, and remove the need for `boost::get<...>` and `IsValidDestination` calls everywhere).
* Do the same for `CBitcoinSecret`, `CBitcoinExtKey`, and `CBitcoinExtPubKey`.
However, I've tried to keep this patch to be minimally invasive, but still enough to support non-Base58 addresses. Perhaps a smaller patch is possible to hack Bech32 support into `CBitcoinAddress`, but I would consider that a move in the wrong direction.
Tree-SHA512: c2c77ffb57caeadf2429b1c2562ce60e8c7be8aa9f8e51b591f354b6b441162625b2efe14c023a1ae485cf2ed417263afa35c892891dfaa7844e7fbabccab85e
* CBitcoinAddress -> EncodeDestination in providertx.h
Signed-off-by: Pasta <pasta@dashboost.org>
* more CBitcoinAddress -> EncodeDestination in providertx.h
Signed-off-by: Pasta <pasta@dashboost.org>
* more CBitcoinAddress -> EncodeDestination in providertx.h
Signed-off-by: Pasta <pasta@dashboost.org>
* more CBitcoinAddress -> EncodeDestination in providertx.h
Signed-off-by: Pasta <pasta@dashboost.org>
* fix CBitcoinAddress GetKeyID check
Signed-off-by: Pasta <pasta@dashboost.org>
* fix providertx.cpp
Signed-off-by: Pasta <pasta@dashboost.org>
* hopefully fix governance-classes.cpp
Signed-off-by: Pasta <pasta@dashboost.org>
* partially fix governance-validators.cpp, unable to resolve "address.IsScript()"
Signed-off-by: Pasta <pasta@dashboost.org>
* partially fix governance-classes.cpp, unable to resolve "address.IsScript()"
Signed-off-by: Pasta <pasta@dashboost.org>
* fix governance-classes.h
Signed-off-by: Pasta <pasta@dashboost.org>
* DecodeTransaction -> DecodeDestination, fix governance-validators.cpp
Signed-off-by: Pasta <pasta@dashboost.org>
* More fixes for 3294
* Move GetIndexKey into rpc/misc.cpp near getAddressesFromParams
No need to have it in base58.cpp anymore as this is only used in getAddressesFromParams
Co-authored-by: Wladimir J. van der Laan <laanwj@gmail.com>
Co-authored-by: UdjinM6 <UdjinM6@users.noreply.github.com>
Co-authored-by: Alexander Block <ablock84@gmail.com>
2020-01-22 11:35:04 +01:00
CTxDestination destination = DecodeDestination ( strAddr ) ;
if ( ! IsValidDestination ( destination ) ) {
2016-11-25 11:33:05 +01:00
throw std : : runtime_error ( " invalid TX output address " ) ;
Merge #11117: Prepare for non-Base58 addresses (#3294)
* Merge #11117: Prepare for non-Base58 addresses
864cd2787 Move CBitcoinAddress to base58.cpp (Pieter Wuille)
5c8ff0d44 Introduce wrappers around CBitcoinAddress (Pieter Wuille)
Pull request description:
This patch removes the need for the intermediary Base58 type `CBitcoinAddress`, by providing {`Encode`,`Decode`,`IsValid`}`Destination` functions that directly operate on the conversion between `std::string`s and `CTxDestination`.
As a side, it also fixes a number of indentation issues, and removes probably several unnecessary implicit `CTxDestination`<->`CBitcoinAddress` conversions.
This change is far from complete. In follow-ups I'd like to:
* Split off the specific address and key encoding logic from base58.h, and move it to a address.h or so.
* Replace `CTxDestination` with a non-`boost::variant` version (which can be more efficient as `boost::variant` allocates everything on the heap, and remove the need for `boost::get<...>` and `IsValidDestination` calls everywhere).
* Do the same for `CBitcoinSecret`, `CBitcoinExtKey`, and `CBitcoinExtPubKey`.
However, I've tried to keep this patch to be minimally invasive, but still enough to support non-Base58 addresses. Perhaps a smaller patch is possible to hack Bech32 support into `CBitcoinAddress`, but I would consider that a move in the wrong direction.
Tree-SHA512: c2c77ffb57caeadf2429b1c2562ce60e8c7be8aa9f8e51b591f354b6b441162625b2efe14c023a1ae485cf2ed417263afa35c892891dfaa7844e7fbabccab85e
* CBitcoinAddress -> EncodeDestination in providertx.h
Signed-off-by: Pasta <pasta@dashboost.org>
* more CBitcoinAddress -> EncodeDestination in providertx.h
Signed-off-by: Pasta <pasta@dashboost.org>
* more CBitcoinAddress -> EncodeDestination in providertx.h
Signed-off-by: Pasta <pasta@dashboost.org>
* more CBitcoinAddress -> EncodeDestination in providertx.h
Signed-off-by: Pasta <pasta@dashboost.org>
* fix CBitcoinAddress GetKeyID check
Signed-off-by: Pasta <pasta@dashboost.org>
* fix providertx.cpp
Signed-off-by: Pasta <pasta@dashboost.org>
* hopefully fix governance-classes.cpp
Signed-off-by: Pasta <pasta@dashboost.org>
* partially fix governance-validators.cpp, unable to resolve "address.IsScript()"
Signed-off-by: Pasta <pasta@dashboost.org>
* partially fix governance-classes.cpp, unable to resolve "address.IsScript()"
Signed-off-by: Pasta <pasta@dashboost.org>
* fix governance-classes.h
Signed-off-by: Pasta <pasta@dashboost.org>
* DecodeTransaction -> DecodeDestination, fix governance-validators.cpp
Signed-off-by: Pasta <pasta@dashboost.org>
* More fixes for 3294
* Move GetIndexKey into rpc/misc.cpp near getAddressesFromParams
No need to have it in base58.cpp anymore as this is only used in getAddressesFromParams
Co-authored-by: Wladimir J. van der Laan <laanwj@gmail.com>
Co-authored-by: UdjinM6 <UdjinM6@users.noreply.github.com>
Co-authored-by: Alexander Block <ablock84@gmail.com>
2020-01-22 11:35:04 +01:00
}
CScript scriptPubKey = GetScriptForDestination ( destination ) ;
2015-04-03 00:51:08 +02:00
// construct TxOut, append to transaction output list
CTxOut txout ( value , scriptPubKey ) ;
tx . vout . push_back ( txout ) ;
}
2017-01-12 12:24:25 +01:00
static void MutateTxAddOutPubKey ( CMutableTransaction & tx , const std : : string & strInput )
{
// Separate into VALUE:PUBKEY[:FLAGS]
2022-12-24 14:35:24 +01:00
std : : vector < std : : string > vStrInputParts = SplitString ( strInput , ' : ' ) ;
2017-01-12 12:24:25 +01:00
2017-03-31 10:18:14 +02:00
if ( vStrInputParts . size ( ) < 2 | | vStrInputParts . size ( ) > 3 )
throw std : : runtime_error ( " TX output missing or too many separators " ) ;
2017-01-12 12:24:25 +01:00
// Extract and validate VALUE
CAmount value = ExtractAndValidateValue ( vStrInputParts [ 0 ] ) ;
// Extract and validate PUBKEY
CPubKey pubkey ( ParseHex ( vStrInputParts [ 1 ] ) ) ;
if ( ! pubkey . IsFullyValid ( ) )
throw std : : runtime_error ( " invalid TX output pubkey " ) ;
CScript scriptPubKey = GetScriptForRawPubKey ( pubkey ) ;
// Extract and validate FLAGS
bool bScriptHash = false ;
if ( vStrInputParts . size ( ) = = 3 ) {
std : : string flags = vStrInputParts [ 2 ] ;
2018-01-29 13:51:03 +01:00
bScriptHash = ( flags . find ( ' S ' ) ! = std : : string : : npos ) ;
2017-01-12 12:24:25 +01:00
}
if ( bScriptHash ) {
Merge #11117: Prepare for non-Base58 addresses (#3294)
* Merge #11117: Prepare for non-Base58 addresses
864cd2787 Move CBitcoinAddress to base58.cpp (Pieter Wuille)
5c8ff0d44 Introduce wrappers around CBitcoinAddress (Pieter Wuille)
Pull request description:
This patch removes the need for the intermediary Base58 type `CBitcoinAddress`, by providing {`Encode`,`Decode`,`IsValid`}`Destination` functions that directly operate on the conversion between `std::string`s and `CTxDestination`.
As a side, it also fixes a number of indentation issues, and removes probably several unnecessary implicit `CTxDestination`<->`CBitcoinAddress` conversions.
This change is far from complete. In follow-ups I'd like to:
* Split off the specific address and key encoding logic from base58.h, and move it to a address.h or so.
* Replace `CTxDestination` with a non-`boost::variant` version (which can be more efficient as `boost::variant` allocates everything on the heap, and remove the need for `boost::get<...>` and `IsValidDestination` calls everywhere).
* Do the same for `CBitcoinSecret`, `CBitcoinExtKey`, and `CBitcoinExtPubKey`.
However, I've tried to keep this patch to be minimally invasive, but still enough to support non-Base58 addresses. Perhaps a smaller patch is possible to hack Bech32 support into `CBitcoinAddress`, but I would consider that a move in the wrong direction.
Tree-SHA512: c2c77ffb57caeadf2429b1c2562ce60e8c7be8aa9f8e51b591f354b6b441162625b2efe14c023a1ae485cf2ed417263afa35c892891dfaa7844e7fbabccab85e
* CBitcoinAddress -> EncodeDestination in providertx.h
Signed-off-by: Pasta <pasta@dashboost.org>
* more CBitcoinAddress -> EncodeDestination in providertx.h
Signed-off-by: Pasta <pasta@dashboost.org>
* more CBitcoinAddress -> EncodeDestination in providertx.h
Signed-off-by: Pasta <pasta@dashboost.org>
* more CBitcoinAddress -> EncodeDestination in providertx.h
Signed-off-by: Pasta <pasta@dashboost.org>
* fix CBitcoinAddress GetKeyID check
Signed-off-by: Pasta <pasta@dashboost.org>
* fix providertx.cpp
Signed-off-by: Pasta <pasta@dashboost.org>
* hopefully fix governance-classes.cpp
Signed-off-by: Pasta <pasta@dashboost.org>
* partially fix governance-validators.cpp, unable to resolve "address.IsScript()"
Signed-off-by: Pasta <pasta@dashboost.org>
* partially fix governance-classes.cpp, unable to resolve "address.IsScript()"
Signed-off-by: Pasta <pasta@dashboost.org>
* fix governance-classes.h
Signed-off-by: Pasta <pasta@dashboost.org>
* DecodeTransaction -> DecodeDestination, fix governance-validators.cpp
Signed-off-by: Pasta <pasta@dashboost.org>
* More fixes for 3294
* Move GetIndexKey into rpc/misc.cpp near getAddressesFromParams
No need to have it in base58.cpp anymore as this is only used in getAddressesFromParams
Co-authored-by: Wladimir J. van der Laan <laanwj@gmail.com>
Co-authored-by: UdjinM6 <UdjinM6@users.noreply.github.com>
Co-authored-by: Alexander Block <ablock84@gmail.com>
2020-01-22 11:35:04 +01:00
// Get the ID for the script, and then construct a P2SH destination for it.
2019-05-09 18:04:52 +02:00
scriptPubKey = GetScriptForDestination ( ScriptHash ( scriptPubKey ) ) ;
2017-01-12 12:24:25 +01:00
}
// construct TxOut, append to transaction output list
CTxOut txout ( value , scriptPubKey ) ;
tx . vout . push_back ( txout ) ;
}
static void MutateTxAddOutMultiSig ( CMutableTransaction & tx , const std : : string & strInput )
{
// Separate into VALUE:REQUIRED:NUMKEYS:PUBKEY1:PUBKEY2:....[:FLAGS]
2022-12-24 14:35:24 +01:00
std : : vector < std : : string > vStrInputParts = SplitString ( strInput , ' : ' ) ;
2017-01-12 12:24:25 +01:00
// Check that there are enough parameters
if ( vStrInputParts . size ( ) < 3 )
throw std : : runtime_error ( " Not enough multisig parameters " ) ;
// Extract and validate VALUE
CAmount value = ExtractAndValidateValue ( vStrInputParts [ 0 ] ) ;
// Extract REQUIRED
uint32_t required = stoul ( vStrInputParts [ 1 ] ) ;
// Extract NUMKEYS
uint32_t numkeys = stoul ( vStrInputParts [ 2 ] ) ;
// Validate there are the correct number of pubkeys
if ( vStrInputParts . size ( ) < numkeys + 3 )
throw std : : runtime_error ( " incorrect number of multisig pubkeys " ) ;
2018-10-20 04:02:20 +02:00
if ( required < 1 | | required > MAX_PUBKEYS_PER_MULTISIG | | numkeys < 1 | | numkeys > MAX_PUBKEYS_PER_MULTISIG | | numkeys < required )
2017-01-12 12:24:25 +01:00
throw std : : runtime_error ( " multisig parameter mismatch. Required " \
2022-12-15 20:17:05 +01:00
+ ToString ( required ) + " of " + ToString ( numkeys ) + " signatures. " ) ;
2017-01-12 12:24:25 +01:00
// extract and validate PUBKEYs
std : : vector < CPubKey > pubkeys ;
for ( int pos = 1 ; pos < = int ( numkeys ) ; pos + + ) {
CPubKey pubkey ( ParseHex ( vStrInputParts [ pos + 2 ] ) ) ;
if ( ! pubkey . IsFullyValid ( ) )
throw std : : runtime_error ( " invalid TX output pubkey " ) ;
pubkeys . push_back ( pubkey ) ;
}
// Extract FLAGS
bool bScriptHash = false ;
if ( vStrInputParts . size ( ) = = numkeys + 4 ) {
std : : string flags = vStrInputParts . back ( ) ;
2018-01-29 13:51:03 +01:00
bScriptHash = ( flags . find ( ' S ' ) ! = std : : string : : npos ) ;
2017-01-12 12:24:25 +01:00
}
else if ( vStrInputParts . size ( ) > numkeys + 4 ) {
// Validate that there were no more parameters passed
throw std : : runtime_error ( " Too many parameters " ) ;
}
CScript scriptPubKey = GetScriptForMultisig ( required , pubkeys ) ;
if ( bScriptHash ) {
2017-11-07 17:19:33 +01:00
if ( scriptPubKey . size ( ) > MAX_SCRIPT_ELEMENT_SIZE ) {
throw std : : runtime_error ( strprintf (
" redeemScript exceeds size limit: %d > %d " , scriptPubKey . size ( ) , MAX_SCRIPT_ELEMENT_SIZE ) ) ;
}
Merge #11117: Prepare for non-Base58 addresses (#3294)
* Merge #11117: Prepare for non-Base58 addresses
864cd2787 Move CBitcoinAddress to base58.cpp (Pieter Wuille)
5c8ff0d44 Introduce wrappers around CBitcoinAddress (Pieter Wuille)
Pull request description:
This patch removes the need for the intermediary Base58 type `CBitcoinAddress`, by providing {`Encode`,`Decode`,`IsValid`}`Destination` functions that directly operate on the conversion between `std::string`s and `CTxDestination`.
As a side, it also fixes a number of indentation issues, and removes probably several unnecessary implicit `CTxDestination`<->`CBitcoinAddress` conversions.
This change is far from complete. In follow-ups I'd like to:
* Split off the specific address and key encoding logic from base58.h, and move it to a address.h or so.
* Replace `CTxDestination` with a non-`boost::variant` version (which can be more efficient as `boost::variant` allocates everything on the heap, and remove the need for `boost::get<...>` and `IsValidDestination` calls everywhere).
* Do the same for `CBitcoinSecret`, `CBitcoinExtKey`, and `CBitcoinExtPubKey`.
However, I've tried to keep this patch to be minimally invasive, but still enough to support non-Base58 addresses. Perhaps a smaller patch is possible to hack Bech32 support into `CBitcoinAddress`, but I would consider that a move in the wrong direction.
Tree-SHA512: c2c77ffb57caeadf2429b1c2562ce60e8c7be8aa9f8e51b591f354b6b441162625b2efe14c023a1ae485cf2ed417263afa35c892891dfaa7844e7fbabccab85e
* CBitcoinAddress -> EncodeDestination in providertx.h
Signed-off-by: Pasta <pasta@dashboost.org>
* more CBitcoinAddress -> EncodeDestination in providertx.h
Signed-off-by: Pasta <pasta@dashboost.org>
* more CBitcoinAddress -> EncodeDestination in providertx.h
Signed-off-by: Pasta <pasta@dashboost.org>
* more CBitcoinAddress -> EncodeDestination in providertx.h
Signed-off-by: Pasta <pasta@dashboost.org>
* fix CBitcoinAddress GetKeyID check
Signed-off-by: Pasta <pasta@dashboost.org>
* fix providertx.cpp
Signed-off-by: Pasta <pasta@dashboost.org>
* hopefully fix governance-classes.cpp
Signed-off-by: Pasta <pasta@dashboost.org>
* partially fix governance-validators.cpp, unable to resolve "address.IsScript()"
Signed-off-by: Pasta <pasta@dashboost.org>
* partially fix governance-classes.cpp, unable to resolve "address.IsScript()"
Signed-off-by: Pasta <pasta@dashboost.org>
* fix governance-classes.h
Signed-off-by: Pasta <pasta@dashboost.org>
* DecodeTransaction -> DecodeDestination, fix governance-validators.cpp
Signed-off-by: Pasta <pasta@dashboost.org>
* More fixes for 3294
* Move GetIndexKey into rpc/misc.cpp near getAddressesFromParams
No need to have it in base58.cpp anymore as this is only used in getAddressesFromParams
Co-authored-by: Wladimir J. van der Laan <laanwj@gmail.com>
Co-authored-by: UdjinM6 <UdjinM6@users.noreply.github.com>
Co-authored-by: Alexander Block <ablock84@gmail.com>
2020-01-22 11:35:04 +01:00
// Get the ID for the script, and then construct a P2SH destination for it.
2019-05-09 18:04:52 +02:00
scriptPubKey = GetScriptForDestination ( ScriptHash ( scriptPubKey ) ) ;
2017-01-12 12:24:25 +01:00
}
// construct TxOut, append to transaction output list
CTxOut txout ( value , scriptPubKey ) ;
tx . vout . push_back ( txout ) ;
}
2016-11-25 11:33:05 +01:00
static void MutateTxAddOutData ( CMutableTransaction & tx , const std : : string & strInput )
2015-06-29 20:14:43 +02:00
{
CAmount value = 0 ;
// separate [VALUE:]DATA in string
size_t pos = strInput . find ( ' : ' ) ;
if ( pos = = 0 )
2016-11-25 11:33:05 +01:00
throw std : : runtime_error ( " TX output value not specified " ) ;
2015-06-29 20:14:43 +02:00
2016-11-25 11:33:05 +01:00
if ( pos ! = std : : string : : npos ) {
2017-01-12 12:24:25 +01:00
// Extract and validate VALUE
value = ExtractAndValidateValue ( strInput . substr ( 0 , pos ) ) ;
2015-06-29 20:14:43 +02:00
}
// extract and validate DATA
2016-11-25 11:33:05 +01:00
std : : string strData = strInput . substr ( pos + 1 , std : : string : : npos ) ;
2015-06-29 20:14:43 +02:00
if ( ! IsHex ( strData ) )
2016-11-25 11:33:05 +01:00
throw std : : runtime_error ( " invalid TX output data " ) ;
2015-06-29 20:14:43 +02:00
std : : vector < unsigned char > data = ParseHex ( strData ) ;
CTxOut txout ( value , CScript ( ) < < OP_RETURN < < data ) ;
tx . vout . push_back ( txout ) ;
}
2016-11-25 11:33:05 +01:00
static void MutateTxAddOutScript ( CMutableTransaction & tx , const std : : string & strInput )
2015-04-03 00:51:08 +02:00
{
2017-01-12 12:24:25 +01:00
// separate VALUE:SCRIPT[:FLAGS]
2022-12-24 14:35:24 +01:00
std : : vector < std : : string > vStrInputParts = SplitString ( strInput , ' : ' ) ;
2017-01-12 12:24:25 +01:00
if ( vStrInputParts . size ( ) < 2 )
2016-11-25 11:33:05 +01:00
throw std : : runtime_error ( " TX output missing separator " ) ;
2015-04-03 00:51:08 +02:00
2017-01-12 12:24:25 +01:00
// Extract and validate VALUE
CAmount value = ExtractAndValidateValue ( vStrInputParts [ 0 ] ) ;
2015-04-03 00:51:08 +02:00
// extract and validate script
2017-01-12 12:24:25 +01:00
std : : string strScript = vStrInputParts [ 1 ] ;
CScript scriptPubKey = ParseScript ( strScript ) ;
// Extract FLAGS
bool bScriptHash = false ;
if ( vStrInputParts . size ( ) = = 3 ) {
std : : string flags = vStrInputParts . back ( ) ;
2018-01-29 13:51:03 +01:00
bScriptHash = ( flags . find ( ' S ' ) ! = std : : string : : npos ) ;
2017-01-12 12:24:25 +01:00
}
2017-11-07 17:19:33 +01:00
if ( scriptPubKey . size ( ) > MAX_SCRIPT_SIZE ) {
throw std : : runtime_error ( strprintf (
" script exceeds size limit: %d > %d " , scriptPubKey . size ( ) , MAX_SCRIPT_SIZE ) ) ;
}
2017-01-12 12:24:25 +01:00
if ( bScriptHash ) {
2017-11-07 17:19:33 +01:00
if ( scriptPubKey . size ( ) > MAX_SCRIPT_ELEMENT_SIZE ) {
throw std : : runtime_error ( strprintf (
" redeemScript exceeds size limit: %d > %d " , scriptPubKey . size ( ) , MAX_SCRIPT_ELEMENT_SIZE ) ) ;
}
2019-05-09 18:04:52 +02:00
scriptPubKey = GetScriptForDestination ( ScriptHash ( scriptPubKey ) ) ;
2017-01-12 12:24:25 +01:00
}
2015-04-03 00:51:08 +02:00
// construct TxOut, append to transaction output list
CTxOut txout ( value , scriptPubKey ) ;
tx . vout . push_back ( txout ) ;
}
2016-11-25 11:33:05 +01:00
static void MutateTxDelInput ( CMutableTransaction & tx , const std : : string & strInIdx )
2015-04-03 00:51:08 +02:00
{
// parse requested deletion index
2018-07-09 19:56:59 +02:00
int64_t inIdx ;
if ( ! ParseInt64 ( strInIdx , & inIdx ) | | inIdx < 0 | | inIdx > = static_cast < int64_t > ( tx . vin . size ( ) ) ) {
throw std : : runtime_error ( " Invalid TX input index ' " + strInIdx + " ' " ) ;
2015-04-03 00:51:08 +02:00
}
// delete input from transaction
tx . vin . erase ( tx . vin . begin ( ) + inIdx ) ;
}
2016-11-25 11:33:05 +01:00
static void MutateTxDelOutput ( CMutableTransaction & tx , const std : : string & strOutIdx )
2015-04-03 00:51:08 +02:00
{
// parse requested deletion index
2018-07-09 19:56:59 +02:00
int64_t outIdx ;
if ( ! ParseInt64 ( strOutIdx , & outIdx ) | | outIdx < 0 | | outIdx > = static_cast < int64_t > ( tx . vout . size ( ) ) ) {
throw std : : runtime_error ( " Invalid TX output index ' " + strOutIdx + " ' " ) ;
2015-04-03 00:51:08 +02:00
}
// delete output from transaction
tx . vout . erase ( tx . vout . begin ( ) + outIdx ) ;
}
static const unsigned int N_SIGHASH_OPTS = 6 ;
static const struct {
const char * flagStr ;
int flags ;
} sighashOptions [ N_SIGHASH_OPTS ] = {
{ " ALL " , SIGHASH_ALL } ,
{ " NONE " , SIGHASH_NONE } ,
{ " SINGLE " , SIGHASH_SINGLE } ,
{ " ALL|ANYONECANPAY " , SIGHASH_ALL | SIGHASH_ANYONECANPAY } ,
{ " NONE|ANYONECANPAY " , SIGHASH_NONE | SIGHASH_ANYONECANPAY } ,
{ " SINGLE|ANYONECANPAY " , SIGHASH_SINGLE | SIGHASH_ANYONECANPAY } ,
} ;
2016-11-25 11:33:05 +01:00
static bool findSighashFlags ( int & flags , const std : : string & flagStr )
2015-04-03 00:51:08 +02:00
{
flags = 0 ;
for ( unsigned int i = 0 ; i < N_SIGHASH_OPTS ; i + + ) {
if ( flagStr = = sighashOptions [ i ] . flagStr ) {
flags = sighashOptions [ i ] . flags ;
return true ;
}
}
return false ;
}
2016-03-31 14:54:58 +02:00
static CAmount AmountFromValue ( const UniValue & value )
{
if ( ! value . isNum ( ) & & ! value . isStr ( ) )
throw std : : runtime_error ( " Amount is not a number or string " ) ;
CAmount amount ;
if ( ! ParseFixedPoint ( value . getValStr ( ) , 8 , & amount ) )
throw std : : runtime_error ( " Invalid amount " ) ;
if ( ! MoneyRange ( amount ) )
throw std : : runtime_error ( " Amount out of range " ) ;
return amount ;
}
2016-11-25 11:33:05 +01:00
static void MutateTxSign ( CMutableTransaction & tx , const std : : string & flagStr )
2015-04-03 00:51:08 +02:00
{
int nHashType = SIGHASH_ALL ;
if ( flagStr . size ( ) > 0 )
if ( ! findSighashFlags ( nHashType , flagStr ) )
2016-11-25 11:33:05 +01:00
throw std : : runtime_error ( " unknown sighash flag/sign option " ) ;
2015-04-03 00:51:08 +02:00
// mergedTx will end up with all the signatures; it
// starts as a clone of the raw tx:
2018-04-13 16:50:48 +02:00
CMutableTransaction mergedTx { tx } ;
2018-05-23 19:04:25 +02:00
const CMutableTransaction txv { tx } ;
2015-04-03 00:51:08 +02:00
CCoinsView viewDummy ;
CCoinsViewCache view ( & viewDummy ) ;
if ( ! registers . count ( " privatekeys " ) )
2016-11-25 11:33:05 +01:00
throw std : : runtime_error ( " privatekeys register variable must be set. " ) ;
2022-07-13 05:46:31 +02:00
FillableSigningProvider tempKeystore ;
2015-04-03 00:51:08 +02:00
UniValue keysObj = registers [ " privatekeys " ] ;
2014-08-20 15:59:31 +02:00
for ( unsigned int kidx = 0 ; kidx < keysObj . size ( ) ; kidx + + ) {
2015-04-03 00:51:08 +02:00
if ( ! keysObj [ kidx ] . isStr ( ) )
2016-11-25 11:33:05 +01:00
throw std : : runtime_error ( " privatekey not a std::string " ) ;
Merge #11372: Address encoding cleanup
92f1f8b31 Split off key_io_tests from base58_tests (Pieter Wuille)
119b0f85e Split key_io (address/key encodings) off from base58 (Pieter Wuille)
ebfe217b1 Stop using CBase58Data for ext keys (Pieter Wuille)
32e69fa0d Replace CBitcoinSecret with {Encode,Decode}Secret (Pieter Wuille)
Pull request description:
This PR contains some of the changes left as TODO in #11167 (and built on top of that PR). They are not intended for backporting.
This removes the `CBase58`, `CBitcoinSecret`, `CBitcoinExtKey`, and `CBitcoinExtPubKey` classes, in favor of simple `Encode`/`Decode` functions. Furthermore, all Bitcoin-specific logic (addresses, WIF, BIP32) is moved to `key_io.{h,cpp}`, leaving `base58.{h,cpp}` as a pure utility that implements the base58 encoding/decoding logic.
Tree-SHA512: a5962c0ed27ad53cbe00f22af432cf11aa530e3efc9798e25c004bc9ed1b5673db5df3956e398ee2c085e3a136ac8da69fe7a7d97a05fb2eb3be0b60d0479655
Make linter happy
Dashify
2018-03-07 00:04:56 +01:00
CKey key = DecodeSecret ( keysObj [ kidx ] . getValStr ( ) ) ;
if ( ! key . IsValid ( ) ) {
2016-11-25 11:33:05 +01:00
throw std : : runtime_error ( " privatekey not valid " ) ;
Merge #11372: Address encoding cleanup
92f1f8b31 Split off key_io_tests from base58_tests (Pieter Wuille)
119b0f85e Split key_io (address/key encodings) off from base58 (Pieter Wuille)
ebfe217b1 Stop using CBase58Data for ext keys (Pieter Wuille)
32e69fa0d Replace CBitcoinSecret with {Encode,Decode}Secret (Pieter Wuille)
Pull request description:
This PR contains some of the changes left as TODO in #11167 (and built on top of that PR). They are not intended for backporting.
This removes the `CBase58`, `CBitcoinSecret`, `CBitcoinExtKey`, and `CBitcoinExtPubKey` classes, in favor of simple `Encode`/`Decode` functions. Furthermore, all Bitcoin-specific logic (addresses, WIF, BIP32) is moved to `key_io.{h,cpp}`, leaving `base58.{h,cpp}` as a pure utility that implements the base58 encoding/decoding logic.
Tree-SHA512: a5962c0ed27ad53cbe00f22af432cf11aa530e3efc9798e25c004bc9ed1b5673db5df3956e398ee2c085e3a136ac8da69fe7a7d97a05fb2eb3be0b60d0479655
Make linter happy
Dashify
2018-03-07 00:04:56 +01:00
}
2015-04-03 00:51:08 +02:00
tempKeystore . AddKey ( key ) ;
}
// Add previous txouts given in the RPC call:
if ( ! registers . count ( " prevtxs " ) )
2016-11-25 11:33:05 +01:00
throw std : : runtime_error ( " prevtxs register variable must be set. " ) ;
2015-04-03 00:51:08 +02:00
UniValue prevtxsObj = registers [ " prevtxs " ] ;
{
2014-08-20 15:59:31 +02:00
for ( unsigned int previdx = 0 ; previdx < prevtxsObj . size ( ) ; previdx + + ) {
2015-04-03 00:51:08 +02:00
UniValue prevOut = prevtxsObj [ previdx ] ;
if ( ! prevOut . isObject ( ) )
2016-11-25 11:33:05 +01:00
throw std : : runtime_error ( " expected prevtxs internal object " ) ;
2015-04-03 00:51:08 +02:00
2017-06-08 19:35:28 +02:00
std : : map < std : : string , UniValue : : VType > types = {
{ " txid " , UniValue : : VSTR } ,
{ " vout " , UniValue : : VNUM } ,
{ " scriptPubKey " , UniValue : : VSTR } ,
} ;
2015-04-03 00:51:08 +02:00
if ( ! prevOut . checkObject ( types ) )
2016-11-25 11:33:05 +01:00
throw std : : runtime_error ( " prevtxs internal object typecheck fail " ) ;
2015-04-03 00:51:08 +02:00
2018-09-27 17:26:17 +02:00
uint256 txid ;
if ( ! ParseHashStr ( prevOut [ " txid " ] . get_str ( ) , txid ) ) {
throw std : : runtime_error ( " txid must be hexadecimal string (not ' " + prevOut [ " txid " ] . get_str ( ) + " ') " ) ;
}
2015-04-03 00:51:08 +02:00
2018-07-09 19:56:59 +02:00
const int nOut = prevOut [ " vout " ] . get_int ( ) ;
2015-04-03 00:51:08 +02:00
if ( nOut < 0 )
2020-10-03 03:56:59 +02:00
throw std : : runtime_error ( " vout cannot be negative " ) ;
2015-04-03 00:51:08 +02:00
2017-06-02 00:47:58 +02:00
COutPoint out ( txid , nOut ) ;
2016-11-25 11:33:05 +01:00
std : : vector < unsigned char > pkData ( ParseHexUV ( prevOut [ " scriptPubKey " ] , " scriptPubKey " ) ) ;
2015-04-03 00:51:08 +02:00
CScript scriptPubKey ( pkData . begin ( ) , pkData . end ( ) ) ;
{
2017-06-02 00:47:58 +02:00
const Coin & coin = view . AccessCoin ( out ) ;
if ( ! coin . IsSpent ( ) & & coin . out . scriptPubKey ! = scriptPubKey ) {
2016-11-25 11:33:05 +01:00
std : : string err ( " Previous output scriptPubKey mismatch: \n " ) ;
2017-06-02 00:47:58 +02:00
err = err + ScriptToAsmStr ( coin . out . scriptPubKey ) + " \n vs: \n " +
2015-07-31 01:56:00 +02:00
ScriptToAsmStr ( scriptPubKey ) ;
2016-11-25 11:33:05 +01:00
throw std : : runtime_error ( err ) ;
2015-04-03 00:51:08 +02:00
}
2017-06-02 00:47:58 +02:00
Coin newcoin ;
newcoin . out . scriptPubKey = scriptPubKey ;
newcoin . out . nValue = 0 ; // we don't know the actual output value
2016-03-31 14:54:58 +02:00
if ( prevOut . exists ( " amount " ) ) {
newcoin . out . nValue = AmountFromValue ( prevOut [ " amount " ] ) ;
}
2017-06-02 00:47:58 +02:00
newcoin . nHeight = 1 ;
view . AddCoin ( out , std : : move ( newcoin ) , true ) ;
2015-04-03 00:51:08 +02:00
}
// if redeemScript given and private keys given,
// add redeemScript to the tempKeystore so it can be signed:
2016-08-26 13:23:57 +02:00
if ( scriptPubKey . IsPayToScriptHash ( ) & &
2015-04-03 00:51:08 +02:00
prevOut . exists ( " redeemScript " ) ) {
UniValue v = prevOut [ " redeemScript " ] ;
2016-11-25 11:33:05 +01:00
std : : vector < unsigned char > rsData ( ParseHexUV ( v , " redeemScript " ) ) ;
2015-04-03 00:51:08 +02:00
CScript redeemScript ( rsData . begin ( ) , rsData . end ( ) ) ;
tempKeystore . AddCScript ( redeemScript ) ;
}
}
}
2022-07-13 05:46:31 +02:00
const FillableSigningProvider & keystore = tempKeystore ;
2015-04-03 00:51:08 +02:00
bool fHashSingle = ( ( nHashType & ~ SIGHASH_ANYONECANPAY ) = = SIGHASH_SINGLE ) ;
// Sign what we can:
for ( unsigned int i = 0 ; i < mergedTx . vin . size ( ) ; i + + ) {
2018-06-05 18:46:12 +02:00
CTxIn & txin = mergedTx . vin [ i ] ;
2017-06-02 00:47:58 +02:00
const Coin & coin = view . AccessCoin ( txin . prevout ) ;
if ( coin . IsSpent ( ) ) {
2015-04-03 00:51:08 +02:00
continue ;
}
2017-06-02 00:47:58 +02:00
const CScript & prevPubKey = coin . out . scriptPubKey ;
2016-03-31 14:51:29 +02:00
const CAmount & amount = coin . out . nValue ;
2015-04-03 00:51:08 +02:00
2018-07-05 16:22:31 +02:00
SignatureData sigdata = DataFromTransaction ( mergedTx , i , coin . out ) ;
2015-04-03 00:51:08 +02:00
// Only sign SIGHASH_SINGLE if there's a corresponding output:
if ( ! fHashSingle | | ( i < mergedTx . vout . size ( ) ) )
2018-04-12 22:30:41 +02:00
ProduceSignature ( keystore , MutableTransactionSignatureCreator ( & mergedTx , i , amount , nHashType ) , prevPubKey , sigdata ) ;
2015-04-03 00:51:08 +02:00
2018-06-05 18:46:12 +02:00
UpdateInput ( txin , sigdata ) ;
2015-04-03 00:51:08 +02:00
}
tx = mergedTx ;
}
Update key.cpp to use new libsecp256k1
libsecp256k1's API changed, so update key.cpp to use it.
Libsecp256k1 now has explicit context objects, which makes it completely thread-safe.
In turn, keep an explicit context object in key.cpp, which is explicitly initialized
destroyed. This is not really pretty now, but it's more efficient than the static
initialized object in key.cpp (which made for example bitcoin-tx slow, as for most of
its calls, libsecp256k1 wasn't actually needed).
This also brings in the new blinding support in libsecp256k1. By passing in a random
seed, temporary variables during the elliptic curve computations are altered, in such
a way that if an attacker does not know the blind, observing the internal operations
leaks less information about the keys used. This was implemented by Greg Maxwell.
2015-04-22 23:28:26 +02:00
class Secp256k1Init
{
public :
2015-07-28 20:11:20 +02:00
Secp256k1Init ( ) {
ECC_Start ( ) ;
}
~ Secp256k1Init ( ) {
ECC_Stop ( ) ;
}
Update key.cpp to use new libsecp256k1
libsecp256k1's API changed, so update key.cpp to use it.
Libsecp256k1 now has explicit context objects, which makes it completely thread-safe.
In turn, keep an explicit context object in key.cpp, which is explicitly initialized
destroyed. This is not really pretty now, but it's more efficient than the static
initialized object in key.cpp (which made for example bitcoin-tx slow, as for most of
its calls, libsecp256k1 wasn't actually needed).
This also brings in the new blinding support in libsecp256k1. By passing in a random
seed, temporary variables during the elliptic curve computations are altered, in such
a way that if an attacker does not know the blind, observing the internal operations
leaks less information about the keys used. This was implemented by Greg Maxwell.
2015-04-22 23:28:26 +02:00
} ;
2016-11-25 11:33:05 +01:00
static void MutateTx ( CMutableTransaction & tx , const std : : string & command ,
const std : : string & commandVal )
2015-04-03 00:51:08 +02:00
{
2016-09-02 09:56:16 +02:00
std : : unique_ptr < Secp256k1Init > ecc ;
Update key.cpp to use new libsecp256k1
libsecp256k1's API changed, so update key.cpp to use it.
Libsecp256k1 now has explicit context objects, which makes it completely thread-safe.
In turn, keep an explicit context object in key.cpp, which is explicitly initialized
destroyed. This is not really pretty now, but it's more efficient than the static
initialized object in key.cpp (which made for example bitcoin-tx slow, as for most of
its calls, libsecp256k1 wasn't actually needed).
This also brings in the new blinding support in libsecp256k1. By passing in a random
seed, temporary variables during the elliptic curve computations are altered, in such
a way that if an attacker does not know the blind, observing the internal operations
leaks less information about the keys used. This was implemented by Greg Maxwell.
2015-04-22 23:28:26 +02:00
2015-04-03 00:51:08 +02:00
if ( command = = " nversion " )
MutateTxVersion ( tx , commandVal ) ;
else if ( command = = " locktime " )
MutateTxLocktime ( tx , commandVal ) ;
else if ( command = = " delin " )
MutateTxDelInput ( tx , commandVal ) ;
else if ( command = = " in " )
MutateTxAddInput ( tx , commandVal ) ;
else if ( command = = " delout " )
MutateTxDelOutput ( tx , commandVal ) ;
else if ( command = = " outaddr " )
MutateTxAddOutAddr ( tx , commandVal ) ;
2017-04-26 12:24:48 +02:00
else if ( command = = " outpubkey " ) {
2017-10-12 23:49:44 +02:00
ecc . reset ( new Secp256k1Init ( ) ) ;
2017-01-12 12:24:25 +01:00
MutateTxAddOutPubKey ( tx , commandVal ) ;
2017-04-26 12:24:48 +02:00
} else if ( command = = " outmultisig " ) {
2017-10-12 23:49:44 +02:00
ecc . reset ( new Secp256k1Init ( ) ) ;
2017-01-12 12:24:25 +01:00
MutateTxAddOutMultiSig ( tx , commandVal ) ;
2017-04-26 12:24:48 +02:00
} else if ( command = = " outscript " )
2015-04-03 00:51:08 +02:00
MutateTxAddOutScript ( tx , commandVal ) ;
2017-01-12 12:24:25 +01:00
else if ( command = = " outdata " )
MutateTxAddOutData ( tx , commandVal ) ;
2015-04-03 00:51:08 +02:00
Update key.cpp to use new libsecp256k1
libsecp256k1's API changed, so update key.cpp to use it.
Libsecp256k1 now has explicit context objects, which makes it completely thread-safe.
In turn, keep an explicit context object in key.cpp, which is explicitly initialized
destroyed. This is not really pretty now, but it's more efficient than the static
initialized object in key.cpp (which made for example bitcoin-tx slow, as for most of
its calls, libsecp256k1 wasn't actually needed).
This also brings in the new blinding support in libsecp256k1. By passing in a random
seed, temporary variables during the elliptic curve computations are altered, in such
a way that if an attacker does not know the blind, observing the internal operations
leaks less information about the keys used. This was implemented by Greg Maxwell.
2015-04-22 23:28:26 +02:00
else if ( command = = " sign " ) {
2017-10-12 23:49:44 +02:00
ecc . reset ( new Secp256k1Init ( ) ) ;
2015-04-03 00:51:08 +02:00
MutateTxSign ( tx , commandVal ) ;
Update key.cpp to use new libsecp256k1
libsecp256k1's API changed, so update key.cpp to use it.
Libsecp256k1 now has explicit context objects, which makes it completely thread-safe.
In turn, keep an explicit context object in key.cpp, which is explicitly initialized
destroyed. This is not really pretty now, but it's more efficient than the static
initialized object in key.cpp (which made for example bitcoin-tx slow, as for most of
its calls, libsecp256k1 wasn't actually needed).
This also brings in the new blinding support in libsecp256k1. By passing in a random
seed, temporary variables during the elliptic curve computations are altered, in such
a way that if an attacker does not know the blind, observing the internal operations
leaks less information about the keys used. This was implemented by Greg Maxwell.
2015-04-22 23:28:26 +02:00
}
2015-04-03 00:51:08 +02:00
else if ( command = = " load " )
RegisterLoad ( commandVal ) ;
else if ( command = = " set " )
RegisterSet ( commandVal ) ;
else
2016-11-25 11:33:05 +01:00
throw std : : runtime_error ( " unknown command " ) ;
2015-04-03 00:51:08 +02:00
}
static void OutputTxJSON ( const CTransaction & tx )
{
UniValue entry ( UniValue : : VOBJ ) ;
2014-12-15 09:11:16 +01:00
TxToUniv ( tx , uint256 ( ) , entry ) ;
2015-04-03 00:51:08 +02:00
2016-11-25 11:33:05 +01:00
std : : string jsonOutput = entry . write ( 4 ) ;
2022-03-21 18:28:10 +01:00
tfm : : format ( std : : cout , " %s \n " , jsonOutput ) ;
2015-04-03 00:51:08 +02:00
}
static void OutputTxHash ( const CTransaction & tx )
{
2016-11-25 11:33:05 +01:00
std : : string strHexHash = tx . GetHash ( ) . GetHex ( ) ; // the hex-encoded transaction hash (aka the transaction id)
2015-04-03 00:51:08 +02:00
2022-03-21 18:28:10 +01:00
tfm : : format ( std : : cout , " %s \n " , strHexHash ) ;
2015-04-03 00:51:08 +02:00
}
static void OutputTxHex ( const CTransaction & tx )
{
2016-11-25 11:33:05 +01:00
std : : string strHex = EncodeHexTx ( tx ) ;
2015-04-03 00:51:08 +02:00
2022-03-21 18:28:10 +01:00
tfm : : format ( std : : cout , " %s \n " , strHex ) ;
2015-04-03 00:51:08 +02:00
}
static void OutputTx ( const CTransaction & tx )
{
2019-06-24 18:44:27 +02:00
if ( gArgs . GetBoolArg ( " -json " , false ) )
2015-04-03 00:51:08 +02:00
OutputTxJSON ( tx ) ;
2019-06-24 18:44:27 +02:00
else if ( gArgs . GetBoolArg ( " -txid " , false ) )
2015-04-03 00:51:08 +02:00
OutputTxHash ( tx ) ;
else
OutputTxHex ( tx ) ;
}
2016-11-25 11:33:05 +01:00
static std : : string readStdin ( )
2015-04-03 00:51:08 +02:00
{
char buf [ 4096 ] ;
2016-11-25 11:33:05 +01:00
std : : string ret ;
2015-04-03 00:51:08 +02:00
while ( ! feof ( stdin ) ) {
size_t bread = fread ( buf , 1 , sizeof ( buf ) , stdin ) ;
ret . append ( buf , bread ) ;
if ( bread < sizeof ( buf ) )
break ;
}
if ( ferror ( stdin ) )
2016-11-25 11:33:05 +01:00
throw std : : runtime_error ( " error reading stdin " ) ;
2015-04-03 00:51:08 +02:00
2020-02-12 18:28:26 +01:00
return TrimString ( ret ) ;
2015-04-03 00:51:08 +02:00
}
static int CommandLineRawTx ( int argc , char * argv [ ] )
{
2016-11-25 11:33:05 +01:00
std : : string strPrint ;
2015-04-03 00:51:08 +02:00
int nRet = 0 ;
try {
// Skip switches; Permit common stdin convention "-"
while ( argc > 1 & & IsSwitchChar ( argv [ 1 ] [ 0 ] ) & &
( argv [ 1 ] [ 1 ] ! = 0 ) ) {
argc - - ;
argv + + ;
}
2016-12-05 08:01:20 +01:00
CMutableTransaction tx ;
2015-04-03 00:51:08 +02:00
int startArg ;
if ( ! fCreateBlank ) {
// require at least one param
if ( argc < 2 )
2016-11-25 11:33:05 +01:00
throw std : : runtime_error ( " too few parameters " ) ;
2015-04-03 00:51:08 +02:00
2015-04-05 23:56:58 +02:00
// param: hex-encoded dash transaction
2016-11-25 11:33:05 +01:00
std : : string strHexTx ( argv [ 1 ] ) ;
2015-04-03 00:51:08 +02:00
if ( strHexTx = = " - " ) // "-" implies standard input
strHexTx = readStdin ( ) ;
2016-12-05 08:01:20 +01:00
if ( ! DecodeHexTx ( tx , strHexTx ) )
2016-11-25 11:33:05 +01:00
throw std : : runtime_error ( " invalid transaction encoding " ) ;
2015-04-03 00:51:08 +02:00
startArg = 2 ;
} else
startArg = 1 ;
for ( int i = startArg ; i < argc ; i + + ) {
2016-11-25 11:33:05 +01:00
std : : string arg = argv [ i ] ;
std : : string key , value ;
2015-04-03 00:51:08 +02:00
size_t eqpos = arg . find ( ' = ' ) ;
2016-11-25 11:33:05 +01:00
if ( eqpos = = std : : string : : npos )
2015-04-03 00:51:08 +02:00
key = arg ;
else {
key = arg . substr ( 0 , eqpos ) ;
value = arg . substr ( eqpos + 1 ) ;
}
MutateTx ( tx , key , value ) ;
}
2021-10-11 17:06:49 +02:00
OutputTx ( CTransaction ( tx ) ) ;
2015-04-03 00:51:08 +02:00
}
2014-12-07 13:29:06 +01:00
catch ( const std : : exception & e ) {
2016-11-25 11:33:05 +01:00
strPrint = std : : string ( " error: " ) + e . what ( ) ;
2015-04-03 00:51:08 +02:00
nRet = EXIT_FAILURE ;
}
catch ( . . . ) {
2019-02-21 19:37:16 +01:00
PrintExceptionContinue ( std : : current_exception ( ) , " CommandLineRawTx() " ) ;
2015-04-03 00:51:08 +02:00
throw ;
}
if ( strPrint ! = " " ) {
2022-03-21 18:28:10 +01:00
tfm : : format ( nRet = = 0 ? std : : cout : std : : cerr , " %s \n " , strPrint ) ;
2015-04-03 00:51:08 +02:00
}
return nRet ;
}
2022-06-13 21:43:22 +02:00
MAIN_FUNCTION
2015-04-03 00:51:08 +02:00
{
2019-02-21 19:37:16 +01:00
RegisterPrettyTerminateHander ( ) ;
RegisterPrettySignalHandlers ( ) ;
2015-04-03 00:51:08 +02:00
SetupEnvironment ( ) ;
try {
2016-11-11 06:16:39 +01:00
int ret = AppInitRawTx ( argc , argv ) ;
if ( ret ! = CONTINUE_EXECUTION )
return ret ;
2015-04-03 00:51:08 +02:00
}
2014-12-07 13:29:06 +01:00
catch ( const std : : exception & e ) {
2019-02-21 19:37:16 +01:00
PrintExceptionContinue ( std : : current_exception ( ) , " AppInitRawTx() " ) ;
2015-04-03 00:51:08 +02:00
return EXIT_FAILURE ;
}
int ret = EXIT_FAILURE ;
try {
ret = CommandLineRawTx ( argc , argv ) ;
} catch ( . . . ) {
2019-02-21 19:37:16 +01:00
PrintExceptionContinue ( std : : current_exception ( ) , " CommandLineRawTx() " ) ;
2015-04-03 00:51:08 +02:00
}
return ret ;
}