2020-12-31 18:50:11 +01: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
2014-08-01 08:39:06 +02:00
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
2014-06-24 05:10:24 +02:00
2020-03-19 23:46:56 +01:00
# include <core_io.h>
2014-09-14 12:43:56 +02:00
2024-10-21 19:59:23 +02:00
# include <consensus/amount.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 <consensus/validation.h>
# include <key_io.h>
2020-03-19 23:46:56 +01:00
# include <primitives/transaction.h>
# include <script/script.h>
# include <script/standard.h>
# include <serialize.h>
# include <streams.h>
2020-12-24 15:32:02 +01:00
# include <undo.h>
2020-03-19 23:46:56 +01:00
# include <univalue.h>
2020-12-24 15:32:02 +01:00
# include <util/check.h>
2021-06-27 08:33:13 +02:00
# include <util/strencodings.h>
2021-03-03 19:04:21 +01:00
# include <util/system.h>
2014-06-24 05:10:24 +02:00
2023-09-18 20:39:11 +02:00
# include <addressindex.h>
2020-03-19 23:46:56 +01:00
# include <spentindex.h>
2019-06-11 13:42:17 +02:00
2023-07-24 18:39:38 +02:00
# include <evo/assetlocktx.h>
2020-03-19 23:46:56 +01:00
# include <evo/cbtx.h>
2021-12-11 21:00:27 +01:00
# include <evo/mnhftx.h>
2020-03-19 23:46:56 +01:00
# include <evo/providertx.h>
# include <evo/specialtx.h>
2021-10-02 19:32:24 +02:00
# include <llmq/commitment.h>
2019-06-11 13:42:17 +02:00
2021-03-03 19:04:21 +01:00
UniValue ValueFromAmount ( const CAmount amount )
2017-08-08 11:27:15 +02:00
{
2021-03-03 19:04:21 +01:00
static_assert ( COIN > 1 ) ;
int64_t quotient = amount / COIN ;
int64_t remainder = amount % COIN ;
if ( amount < 0 ) {
quotient = - quotient ;
remainder = - remainder ;
}
2017-08-08 11:27:15 +02:00
return UniValue ( UniValue : : VNUM ,
2021-03-03 19:04:21 +01:00
strprintf ( " %s%d.%08d " , amount < 0 ? " - " : " " , quotient , remainder ) ) ;
2017-08-08 11:27:15 +02:00
}
2014-08-23 05:09:47 +02:00
2017-01-30 13:13:07 +01:00
std : : string FormatScript ( const CScript & script )
2014-09-20 03:13:04 +02:00
{
2017-01-30 13:13:07 +01:00
std : : string ret ;
2014-09-20 03:13:04 +02:00
CScript : : const_iterator it = script . begin ( ) ;
opcodetype op ;
while ( it ! = script . end ( ) ) {
CScript : : const_iterator it2 = it ;
2017-01-30 13:13:07 +01:00
std : : vector < unsigned char > vch ;
2018-04-23 21:08:42 +02:00
if ( script . GetOp ( it , op , vch ) ) {
2014-09-20 03:13:04 +02:00
if ( op = = OP_0 ) {
ret + = " 0 " ;
continue ;
} else if ( ( op > = OP_1 & & op < = OP_16 ) | | op = = OP_1NEGATE ) {
ret + = strprintf ( " %i " , op - OP_1NEGATE - 1 ) ;
continue ;
2016-04-05 14:54:18 +02:00
} else if ( op > = OP_NOP & & op < = OP_NOP10 ) {
2017-01-30 13:13:07 +01:00
std : : string str ( GetOpName ( op ) ) ;
if ( str . substr ( 0 , 3 ) = = std : : string ( " OP_ " ) ) {
ret + = str . substr ( 3 , std : : string : : npos ) + " " ;
2014-09-20 03:13:04 +02:00
continue ;
}
}
if ( vch . size ( ) > 0 ) {
2020-06-24 17:26:47 +02:00
ret + = strprintf ( " 0x%x 0x%x " , HexStr ( std : : vector < uint8_t > ( it2 , it - vch . size ( ) ) ) ,
HexStr ( std : : vector < uint8_t > ( it - vch . size ( ) , it ) ) ) ;
2014-09-20 03:13:04 +02:00
} else {
2020-06-24 17:26:47 +02:00
ret + = strprintf ( " 0x%x " , HexStr ( std : : vector < uint8_t > ( it2 , it ) ) ) ;
2014-09-20 03:13:04 +02:00
}
continue ;
}
2020-06-24 17:26:47 +02:00
ret + = strprintf ( " 0x%x " , HexStr ( std : : vector < uint8_t > ( it2 , script . end ( ) ) ) ) ;
2014-09-20 03:13:04 +02:00
break ;
}
2022-02-14 10:08:34 +01:00
return ret . substr ( 0 , ret . empty ( ) ? ret . npos : ret . size ( ) - 1 ) ;
2014-09-20 03:13:04 +02:00
}
2017-06-08 19:35:28 +02:00
const std : : map < unsigned char , std : : string > mapSigHashTypes = {
{ static_cast < unsigned char > ( SIGHASH_ALL ) , std : : string ( " ALL " ) } ,
{ static_cast < unsigned char > ( SIGHASH_ALL | SIGHASH_ANYONECANPAY ) , std : : string ( " ALL|ANYONECANPAY " ) } ,
{ static_cast < unsigned char > ( SIGHASH_NONE ) , std : : string ( " NONE " ) } ,
{ static_cast < unsigned char > ( SIGHASH_NONE | SIGHASH_ANYONECANPAY ) , std : : string ( " NONE|ANYONECANPAY " ) } ,
{ static_cast < unsigned char > ( SIGHASH_SINGLE ) , std : : string ( " SINGLE " ) } ,
{ static_cast < unsigned char > ( SIGHASH_SINGLE | SIGHASH_ANYONECANPAY ) , std : : string ( " SINGLE|ANYONECANPAY " ) } ,
} ;
2015-07-31 01:56:00 +02:00
2021-07-13 18:30:17 +02:00
std : : string SighashToStr ( unsigned char sighash_type )
{
const auto & it = mapSigHashTypes . find ( sighash_type ) ;
if ( it = = mapSigHashTypes . end ( ) ) return " " ;
return it - > second ;
}
2015-07-31 01:56:00 +02:00
/**
* Create the assembly string representation of a CScript object .
* @ param [ in ] script CScript object to convert into the asm string representation .
* @ param [ in ] fAttemptSighashDecode Whether to attempt to decode sighash types on data within the script that matches the format
* of a signature . Only pass true for scripts you believe could contain signatures . For example ,
* pass false , or omit the this argument ( defaults to false ) , for scriptPubKeys .
*/
2017-01-30 13:13:07 +01:00
std : : string ScriptToAsmStr ( const CScript & script , const bool fAttemptSighashDecode )
2015-07-31 01:56:00 +02:00
{
2017-01-30 13:13:07 +01:00
std : : string str ;
2015-07-31 01:56:00 +02:00
opcodetype opcode ;
2017-01-30 13:13:07 +01:00
std : : vector < unsigned char > vch ;
2015-07-31 01:56:00 +02:00
CScript : : const_iterator pc = script . begin ( ) ;
while ( pc < script . end ( ) ) {
if ( ! str . empty ( ) ) {
str + = " " ;
}
if ( ! script . GetOp ( pc , opcode , vch ) ) {
str + = " [error] " ;
return str ;
}
if ( 0 < = opcode & & opcode < = OP_PUSHDATA4 ) {
2017-01-30 13:13:07 +01:00
if ( vch . size ( ) < = static_cast < std : : vector < unsigned char > : : size_type > ( 4 ) ) {
2015-07-31 01:56:00 +02:00
str + = strprintf ( " %d " , CScriptNum ( vch , false ) . getint ( ) ) ;
} else {
// the IsUnspendable check makes sure not to try to decode OP_RETURN data that may match the format of a signature
if ( fAttemptSighashDecode & & ! script . IsUnspendable ( ) ) {
2017-01-30 13:13:07 +01:00
std : : string strSigHashDecode ;
2015-07-31 01:56:00 +02:00
// goal: only attempt to decode a defined sighash type from data that looks like a signature within a scriptSig.
// this won't decode correctly formatted public keys in Pubkey or Multisig scripts due to
// the restrictions on the pubkey formats (see IsCompressedOrUncompressedPubKey) being incongruous with the
// checks in CheckSignatureEncoding.
2019-08-06 05:08:33 +02:00
if ( CheckSignatureEncoding ( vch , SCRIPT_VERIFY_STRICTENC , nullptr ) ) {
2015-07-31 01:56:00 +02:00
const unsigned char chSigHashType = vch . back ( ) ;
2020-09-05 13:43:33 +02:00
const auto it = mapSigHashTypes . find ( chSigHashType ) ;
if ( it ! = mapSigHashTypes . end ( ) ) {
strSigHashDecode = " [ " + it - > second + " ] " ;
2015-07-31 01:56:00 +02:00
vch . pop_back ( ) ; // remove the sighash type byte. it will be replaced by the decode.
}
}
str + = HexStr ( vch ) + strSigHashDecode ;
} else {
str + = HexStr ( vch ) ;
}
}
} else {
str + = GetOpName ( opcode ) ;
}
}
return str ;
}
2017-01-30 13:13:07 +01:00
std : : string EncodeHexTx ( const CTransaction & tx )
2014-06-24 05:10:24 +02:00
{
CDataStream ssTx ( SER_NETWORK , PROTOCOL_VERSION ) ;
ssTx < < tx ;
2021-05-18 19:17:10 +02:00
return HexStr ( ssTx ) ;
2014-06-24 05:10:24 +02:00
}
2021-07-13 18:30:17 +02:00
void ScriptToUniv ( const CScript & script , UniValue & out , bool include_address )
{
out . pushKV ( " asm " , ScriptToAsmStr ( script ) ) ;
out . pushKV ( " hex " , HexStr ( script ) ) ;
std : : vector < std : : vector < unsigned char > > solns ;
2022-09-15 16:24:07 +02:00
TxoutType type = Solver ( script , solns ) ;
2021-07-13 18:30:17 +02:00
out . pushKV ( " type " , GetTxnOutputType ( type ) ) ;
CTxDestination address ;
2022-09-15 16:24:07 +02:00
if ( include_address & & ExtractDestination ( script , address ) & & type ! = TxoutType : : PUBKEY ) {
2021-07-13 18:30:17 +02:00
out . pushKV ( " address " , EncodeDestination ( address ) ) ;
}
}
2024-06-23 17:51:21 +02:00
// TODO: from v21 ("addresses" and "reqSigs" deprecated) this method should be refactored to remove the `include_addresses` option
// this method can also be combined with `ScriptToUniv` as they will overlap
2014-07-29 17:12:44 +02:00
void ScriptPubKeyToUniv ( const CScript & scriptPubKey ,
2024-06-23 17:51:21 +02:00
UniValue & out , bool fIncludeHex , bool include_addresses )
2014-07-29 17:12:44 +02:00
{
2022-09-15 16:24:07 +02:00
TxoutType type ;
2024-06-23 17:51:21 +02:00
CTxDestination address ;
2017-01-30 13:13:07 +01:00
std : : vector < CTxDestination > addresses ;
2014-07-29 17:12:44 +02:00
int nRequired ;
2015-07-31 01:56:00 +02:00
out . pushKV ( " asm " , ScriptToAsmStr ( scriptPubKey ) ) ;
2014-07-29 17:12:44 +02:00
if ( fIncludeHex )
2021-05-18 19:17:10 +02:00
out . pushKV ( " hex " , HexStr ( scriptPubKey ) ) ;
2014-07-29 17:12:44 +02:00
2022-09-15 16:24:07 +02:00
if ( ! ExtractDestinations ( scriptPubKey , type , addresses , nRequired ) | | type = = TxoutType : : PUBKEY ) {
2014-07-29 17:12:44 +02:00
out . pushKV ( " type " , GetTxnOutputType ( type ) ) ;
return ;
}
2024-06-23 17:51:21 +02:00
if ( ExtractDestination ( scriptPubKey , address ) ) {
out . pushKV ( " address " , EncodeDestination ( address ) ) ;
}
2014-07-29 17:12:44 +02:00
out . pushKV ( " type " , GetTxnOutputType ( type ) ) ;
2024-06-23 17:51:21 +02:00
if ( include_addresses ) {
UniValue a ( UniValue : : VARR ) ;
for ( const CTxDestination & addr : addresses ) {
a . push_back ( EncodeDestination ( addr ) ) ;
}
out . pushKV ( " addresses " , a ) ;
out . pushKV ( " reqSigs " , nRequired ) ;
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
}
2014-07-29 17:12:44 +02:00
}
2024-06-23 17:51:21 +02:00
void TxToUniv ( const CTransaction & tx , const uint256 & hashBlock , bool include_addresses , UniValue & entry , bool include_hex , const CTxUndo * txundo , const CSpentIndexTxInfo * ptxSpentInfo )
2014-07-29 17:12:44 +02:00
{
2019-06-11 13:42:17 +02:00
uint256 txid = tx . GetHash ( ) ;
entry . pushKV ( " txid " , txid . GetHex ( ) ) ;
2020-07-16 21:33:13 +02:00
// Transaction version is actually unsigned in consensus checks, just signed in memory,
// so cast to unsigned before giving it to the user.
entry . pushKV ( " version " , static_cast < int64_t > ( static_cast < uint16_t > ( tx . nVersion ) ) ) ;
2019-08-28 09:54:44 +02:00
entry . pushKV ( " type " , tx . nType ) ;
2018-09-11 09:09:57 +02:00
entry . pushKV ( " size " , ( int ) : : GetSerializeSize ( tx , PROTOCOL_VERSION ) ) ;
2014-07-29 17:12:44 +02:00
entry . pushKV ( " locktime " , ( int64_t ) tx . nLockTime ) ;
UniValue vin ( UniValue : : VARR ) ;
2020-12-24 15:32:02 +01:00
// If available, use Undo data to calculate the fee. Note that txundo == nullptr
// for coinbase transactions and for transactions where undo data is unavailable.
const bool calculate_fee = txundo ! = nullptr ;
CAmount amt_total_in = 0 ;
CAmount amt_total_out = 0 ;
for ( unsigned int i = 0 ; i < tx . vin . size ( ) ; i + + ) {
const CTxIn & txin = tx . vin [ i ] ;
2014-07-29 17:12:44 +02:00
UniValue in ( UniValue : : VOBJ ) ;
2020-12-24 15:32:02 +01:00
if ( tx . IsCoinBase ( ) ) {
2021-05-18 19:17:10 +02:00
in . pushKV ( " coinbase " , HexStr ( txin . scriptSig ) ) ;
2020-12-24 15:32:02 +01:00
} else {
2014-07-29 17:12:44 +02:00
in . pushKV ( " txid " , txin . prevout . hash . GetHex ( ) ) ;
in . pushKV ( " vout " , ( int64_t ) txin . prevout . n ) ;
UniValue o ( UniValue : : VOBJ ) ;
2015-07-31 01:56:00 +02:00
o . pushKV ( " asm " , ScriptToAsmStr ( txin . scriptSig , true ) ) ;
2021-05-18 19:17:10 +02:00
o . pushKV ( " hex " , HexStr ( txin . scriptSig ) ) ;
2014-07-29 17:12:44 +02:00
in . pushKV ( " scriptSig " , o ) ;
2019-06-11 13:42:17 +02:00
// Add address and value info if spentindex enabled
if ( ptxSpentInfo ! = nullptr ) {
CSpentIndexKey spentKey ( txin . prevout . hash , txin . prevout . n ) ;
auto it = ptxSpentInfo - > mSpentInfo . find ( spentKey ) ;
if ( it ! = ptxSpentInfo - > mSpentInfo . end ( ) ) {
auto spentInfo = it - > second ;
2023-09-18 19:17:33 +02:00
in . pushKV ( " value " , ValueFromAmount ( spentInfo . m_amount ) ) ;
in . pushKV ( " valueSat " , spentInfo . m_amount ) ;
2023-09-25 17:19:15 +02:00
if ( spentInfo . m_address_type = = AddressType : : P2PK_OR_P2PKH ) {
2023-09-18 19:17:33 +02:00
in . pushKV ( " address " , EncodeDestination ( PKHash ( spentInfo . m_address_bytes ) ) ) ;
} else if ( spentInfo . m_address_type = = AddressType : : P2SH ) {
in . pushKV ( " address " , EncodeDestination ( ScriptHash ( spentInfo . m_address_bytes ) ) ) ;
2019-06-11 13:42:17 +02:00
}
}
}
2014-07-29 17:12:44 +02:00
}
2020-12-24 15:32:02 +01:00
if ( calculate_fee ) {
const CTxOut & prev_txout = txundo - > vprevout [ i ] . out ;
amt_total_in + = prev_txout . nValue ;
}
2014-07-29 17:12:44 +02:00
in . pushKV ( " sequence " , ( int64_t ) txin . nSequence ) ;
vin . push_back ( in ) ;
}
entry . pushKV ( " vin " , vin ) ;
UniValue vout ( UniValue : : VARR ) ;
for ( unsigned int i = 0 ; i < tx . vout . size ( ) ; i + + ) {
const CTxOut & txout = tx . vout [ i ] ;
UniValue out ( UniValue : : VOBJ ) ;
2017-08-08 11:27:15 +02:00
out . pushKV ( " value " , ValueFromAmount ( txout . nValue ) ) ;
2019-06-11 13:42:17 +02:00
out . pushKV ( " valueSat " , txout . nValue ) ;
2014-07-29 17:12:44 +02:00
out . pushKV ( " n " , ( int64_t ) i ) ;
UniValue o ( UniValue : : VOBJ ) ;
2024-06-23 17:51:21 +02:00
ScriptPubKeyToUniv ( txout . scriptPubKey , o , true , include_addresses ) ;
2014-07-29 17:12:44 +02:00
out . pushKV ( " scriptPubKey " , o ) ;
2019-06-11 13:42:17 +02:00
// Add spent information if spentindex is enabled
if ( ptxSpentInfo ! = nullptr ) {
CSpentIndexKey spentKey ( txid , i ) ;
auto it = ptxSpentInfo - > mSpentInfo . find ( spentKey ) ;
if ( it ! = ptxSpentInfo - > mSpentInfo . end ( ) ) {
auto spentInfo = it - > second ;
2023-09-18 19:17:33 +02:00
out . pushKV ( " spentTxId " , spentInfo . m_tx_hash . GetHex ( ) ) ;
out . pushKV ( " spentIndex " , ( int ) spentInfo . m_tx_index ) ;
out . pushKV ( " spentHeight " , spentInfo . m_block_height ) ;
2019-06-11 13:42:17 +02:00
}
}
2014-07-29 17:12:44 +02:00
vout . push_back ( out ) ;
2020-12-24 15:32:02 +01:00
if ( calculate_fee ) {
amt_total_out + = txout . nValue ;
}
2014-07-29 17:12:44 +02:00
}
entry . pushKV ( " vout " , vout ) ;
2019-06-11 13:42:17 +02:00
if ( ! tx . vExtraPayload . empty ( ) ) {
2020-06-18 11:17:23 +02:00
entry . pushKV ( " extraPayloadSize " , ( int ) tx . vExtraPayload . size ( ) ) ;
entry . pushKV ( " extraPayload " , HexStr ( tx . vExtraPayload ) ) ;
2019-06-11 13:42:17 +02:00
}
if ( tx . nType = = TRANSACTION_PROVIDER_REGISTER ) {
2024-01-12 04:43:01 +01:00
if ( const auto opt_proTx = GetTxPayload < CProRegTx > ( tx ) ) {
entry . pushKV ( " proRegTx " , opt_proTx - > ToJson ( ) ) ;
2019-06-11 13:42:17 +02:00
}
} else if ( tx . nType = = TRANSACTION_PROVIDER_UPDATE_SERVICE ) {
2024-01-12 04:43:01 +01:00
if ( const auto opt_proTx = GetTxPayload < CProUpServTx > ( tx ) ) {
entry . pushKV ( " proUpServTx " , opt_proTx - > ToJson ( ) ) ;
2019-06-11 13:42:17 +02:00
}
} else if ( tx . nType = = TRANSACTION_PROVIDER_UPDATE_REGISTRAR ) {
2024-01-12 04:43:01 +01:00
if ( const auto opt_proTx = GetTxPayload < CProUpRegTx > ( tx ) ) {
entry . pushKV ( " proUpRegTx " , opt_proTx - > ToJson ( ) ) ;
2019-06-11 13:42:17 +02:00
}
} else if ( tx . nType = = TRANSACTION_PROVIDER_UPDATE_REVOKE ) {
2024-01-12 04:43:01 +01:00
if ( const auto opt_proTx = GetTxPayload < CProUpRevTx > ( tx ) ) {
entry . pushKV ( " proUpRevTx " , opt_proTx - > ToJson ( ) ) ;
2019-06-11 13:42:17 +02:00
}
} else if ( tx . nType = = TRANSACTION_COINBASE ) {
2024-01-12 04:43:01 +01:00
if ( const auto opt_cbTx = GetTxPayload < CCbTx > ( tx ) ) {
entry . pushKV ( " cbTx " , opt_cbTx - > ToJson ( ) ) ;
2019-06-11 13:42:17 +02:00
}
} else if ( tx . nType = = TRANSACTION_QUORUM_COMMITMENT ) {
2024-01-12 04:43:01 +01:00
if ( const auto opt_qcTx = GetTxPayload < llmq : : CFinalCommitmentTxPayload > ( tx ) ) {
entry . pushKV ( " qcTx " , opt_qcTx - > ToJson ( ) ) ;
2019-06-11 13:42:17 +02:00
}
2021-12-11 21:00:27 +01:00
} else if ( tx . nType = = TRANSACTION_MNHF_SIGNAL ) {
2024-01-12 04:43:01 +01:00
if ( const auto opt_mnhfTx = GetTxPayload < MNHFTxPayload > ( tx ) ) {
entry . pushKV ( " mnhfTx " , opt_mnhfTx - > ToJson ( ) ) ;
2021-12-11 21:00:27 +01:00
}
2023-07-24 18:39:38 +02:00
} else if ( tx . nType = = TRANSACTION_ASSET_LOCK ) {
2024-01-12 04:43:01 +01:00
if ( const auto opt_assetLockTx = GetTxPayload < CAssetLockPayload > ( tx ) ) {
entry . pushKV ( " assetLockTx " , opt_assetLockTx - > ToJson ( ) ) ;
2023-07-24 18:39:38 +02:00
}
} else if ( tx . nType = = TRANSACTION_ASSET_UNLOCK ) {
2024-01-12 04:43:01 +01:00
if ( const auto opt_assetUnlockTx = GetTxPayload < CAssetUnlockPayload > ( tx ) ) {
entry . pushKV ( " assetUnlockTx " , opt_assetUnlockTx - > ToJson ( ) ) ;
2023-07-24 18:39:38 +02:00
}
2019-06-11 13:42:17 +02:00
}
2020-12-24 15:32:02 +01:00
if ( calculate_fee ) {
2024-10-22 13:56:14 +02:00
CAmount fee = amt_total_in - amt_total_out ;
2024-10-22 16:48:05 +02:00
if ( tx . IsPlatformTransfer ( ) ) {
2024-10-22 18:51:50 +02:00
auto payload = GetTxPayload < CAssetUnlockPayload > ( tx ) ;
CHECK_NONFATAL ( payload ) ;
fee = payload - > getFee ( ) ;
2024-10-22 13:56:14 +02:00
}
2020-12-24 15:32:02 +01:00
CHECK_NONFATAL ( MoneyRange ( fee ) ) ;
entry . pushKV ( " fee " , ValueFromAmount ( fee ) ) ;
}
2014-12-15 09:11:16 +01:00
if ( ! hashBlock . IsNull ( ) )
2014-07-29 17:12:44 +02:00
entry . pushKV ( " blockhash " , hashBlock . GetHex ( ) ) ;
2014-11-04 19:01:41 +01:00
2020-01-22 11:36:22 +01:00
if ( include_hex ) {
2018-03-21 16:16:28 +01:00
entry . pushKV ( " hex " , EncodeHexTx ( tx ) ) ; // The hex-encoded transaction. Used the name "hex" to be consistent with the verbose output of "getrawtransaction".
2020-01-22 11:36:22 +01:00
}
2014-07-29 17:12:44 +02:00
}