<h2>This solution is used by Bitcoin Core</h2>
<h3>base58.h</h3>
<pre><code>// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2015 The Bitcoin Core developers
// Copyright (c) 2023 Loopite.

#ifndef CRYPTO_BASE58_H
#define CRYPTO_BASE58_H

#include &lt;string&gt;
#include &lt;vector&gt;

/**
 * Encode a byte sequence as a base58-encoded string.
 * pbegin and pend cannot be NULL, unless both are.
 */
std::string encodeBase58(const unsigned char* pbegin, const unsigned char* pend);

/**
 * Encode a byte vector as a base58-encoded string
 */
std::string encodeBase58(const std::vector&lt;unsigned char&gt;&amp; vch);

/**
 * Decode a base58-encoded string (psz) into a byte vector (vchRet).
 * return true if decoding is successful.
 * psz cannot be NULL.
 */
bool decodeBase58(const char* psz, std::vector&lt;unsigned char&gt;&amp; vchRet);

/**
 * Decode a base58-encoded string (str) into a byte vector (vchRet).
 * return true if decoding is successful.
 */
bool decodeBase58(const std::string&amp; str, std::vector&lt;unsigned char&gt;&amp; vchRet);

#endif // CRYPTO_BASE58_H
</code></pre>
<h3>base58.cpp</h3>
<pre><code>// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2015 The Bitcoin Core developers
// Copyright (c) 2023 Loopite

#include &quot;base58.h&quot;

#include &lt;iterator&gt;
#include &lt;cstring&gt;

#include &lt;cassert&gt;

/** All alphanumeric characters except for &quot;0&quot;, &quot;I&quot;, &quot;O&quot;, and &quot;l&quot; */
static const char* pszBase58 { &quot;123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz&quot; };

std::string encodeBase58(const unsigned char* pbegin, const unsigned char* pend)
{
    // Skip &amp; count leading zeroes.
    int zeroes = 0;
    int length = 0;
    while (pbegin != pend &amp;&amp; *pbegin == 0) {
        pbegin++;
        zeroes++;
    }
    // Allocate enough space in big-endian base58 representation.
    int size = (pend - pbegin) * 138 / 100 + 1; // log(256) / log(58), rounded up.
    std::vector&lt;unsigned char&gt; b58(size);
    // Process the bytes.
    while (pbegin != pend) {
        int carry = *pbegin;
        int i = 0;
        // Apply &quot;b58 = b58 * 256 + ch&quot;.
        for (auto it = b58.rbegin(); (carry != 0 || i &lt; length) &amp;&amp; (it != b58.rend()); it++, i++) {
            carry += 256 * (*it);
            *it = carry % 58;
            carry /= 58;
        }

        assert(carry == 0);
        length = i;
        pbegin++;
    }
    // Skip leading zeroes in base58 result.
    auto it = b58.begin() + (size - length);
    while (it != b58.end() &amp;&amp; *it == 0)
        it++;
    // Translate the result into a string.
    std::string str;
    str.reserve(zeroes + (b58.end() - it));
    str.assign(zeroes, '1');
    while (it != b58.end())
        str += pszBase58[*(it++)];
    return str;
}

std::string encodeBase58(const std::vector&lt;unsigned char&gt;&amp; vch)
{
    return encodeBase58(&amp;vch[0], &amp;vch[0] + vch.size());
}

bool decodeBase58(const char* psz, std::vector&lt;unsigned char&gt;&amp; vch)
{
    // Skip leading spaces.
    while (*psz &amp;&amp; isspace(*psz))
        psz++;
    // Skip and count leading '1's.
    int zeroes = 0;
    int length = 0;
    while (*psz == '1') {
        zeroes++;
        psz++;
    }
    // Allocate enough space in big-endian base256 representation.
    int size = strlen(psz) * 733 /1000 + 1; // log(58) / log(256), rounded up.
    std::vector&lt;unsigned char&gt; b256(size);
    // Process the characters.
    while (*psz &amp;&amp; !isspace(*psz)) {
        // Decode base58 character
        const char* ch = strchr(pszBase58, *psz);
        if (ch == nullptr)
            return false;
        // Apply &quot;b256 = b256 * 58 + ch&quot;.
        int carry = ch - pszBase58;
        int i = 0;
        for (auto it = b256.rbegin(); (carry != 0 || i &lt; length) &amp;&amp; (it != b256.rend()); ++it, ++i) {
            carry += 58 * (*it);
            *it = carry % 256;
            carry /= 256;
        }
        assert(carry == 0);
        length = i;
        psz++;
    }
    // Skip trailing spaces.
    while (isspace(*psz))
        psz++;
    if (*psz != 0)
        return false;
    // Skip leading zeroes in b256.
    auto it = b256.begin() + (size - length);
    while (it != b256.end() &amp;&amp; *it == 0)
        it++;
    // Copy result into output vector.
    vch.reserve(zeroes + (b256.end() - it));
    vch.assign(zeroes, 0x00);
    while (it != b256.end())
        vch.push_back(*(it++));
    return true;
}

bool decodeBase58(const std::string&amp; str, std::vector&lt;unsigned char&gt;&amp; vchRet)
{
    return decodeBase58(str.c_str(), vchRet);
}
</code></pre>
<h3>Tests</h3>
<pre><code>[ RUN      ] App.base58_Basics
00b9454405a39efcb023127cd6daacf9c133b84df30ce3172d
[       OK ] App.base58_Basics (0 ms)
</code></pre>
<p>From C++ code:</p>
<pre><code>/**
 * @Author: Loopite
 * @Description: Test for base58 encodings
 */

#include &lt;gtest/gtest.h&gt;

#include &quot;crypto/base58.h&quot;

#include &lt;set&gt;

TEST(App, base58_Basics)
{
    /*
     * Decode
     */
    const std::string data
    {
        &quot;1Htcz9y5sVuztuwTnfpWR4dhqirhLMcK7r&quot; // P2PKH address
    };

    std::vector&lt;unsigned char&gt; decodedContent;
    decodeBase58(data, decodedContent);

    // ...Print content of decoded data...
    for (unsigned char i : decodedContent)
        std::cout &lt;&lt; std::hex &lt;&lt; std::setfill('0') &lt;&lt; std::setw(2) &lt;&lt; static_cast&lt;unsigned int&gt;(i);

    std::cout &lt;&lt; std::endl;
}
</code></pre>
<h2>NOTE</h2>
<p>The output is <code>00b9454405a39efcb023127cd6daacf9c133b84df30ce3172d</code> NOT <code>00b9454405a39efcb023127cd6daacf9c133b84df3</code> for the string <code>1Htcz9y5sVuztuwTnfpWR4dhqirhLMcK7r</code>. See <a href="https://appdevtools.com/base58-encoder-decoder" rel="nofollow noreferrer">https://appdevtools.com/base58-encoder-decoder</a>.</p>

CC BY-SA 4.0
2023-08-16T09:52:41.113Z
I see but that includes with hexadecimal value + checksum right? Well i dont want the checksum value, i only want the hexadecimal value
just.callme.client
CC BY-SA 4.0
2023-08-16T10:22:13.437Z
The thing is P2PKH has this structure: networkFlag (1 byte) + address (20 bytes since it has been hashed by RIPEMD-160) + checksum (4 bytes). Therefore the checksum is required. However if you WANT the hexadecimal value WITHOUT checksum you can process like this:
``1Htcz9y5sVuztuwTnfpWR4dhqirhLMcK7r`` <=>
``00b9454405a39efcb023127cd6daacf9c133b84df30ce3172d`` (With checksum) <=>
``00b9454405a39efcb023127cd6daacf9c133b84df3`` (Without checksum) <=>
``13ahvXA4uoeMuX4iKJW1mQkYjCWbt`` (Encoded in base58)
You just have to parse output to get networkFlag and address separatly by using substr.
Loopite
CC BY-SA 4.0
2023-08-16T10:27:38.190Z
/!\. You should know that the checksum is REQUIRED. So you'll have to keep it from LEGACY addresses. It's part of the protocol. Functions you see above allow you to encode/decode base58 sequence. That's it.
Loopite
CC BY-SA 4.0
2023-08-16T11:10:05.540Z
So what youre trying to say is that i need to include the checksum in order to make a raw transactions?
just.callme.client
CC BY-SA 4.0
2023-08-16T11:43:35.580Z
In a raw transaction this is different. You'll have just to provide the address. This field can be determined from the Base58Check (1Htcz9y5sVuztuwTnfpWR4dhqirhLMcK7r).
_To sum up:_ Base58**Check** requires a **checksum**. But raw txs need address only.
Loopite
CC BY-SA 4.0
2023-08-16T12:04:38.940Z
yeah i see, thanks for your help:)
just.callme.client
CC BY-SA 4.0
2023-08-16T13:03:23.460Z
hello sir, sorry to bother you but i face some issue with your code, the result from decodeBase58() only can be print through for loop, now heres the problem. How can i store the result inside a viarable?
just.callme.client
CC BY-SA 4.0
2023-08-16T13:11:31.173Z
decodeBase58 returns nothing. However, it takes a vector of unsigned char in **reference** : ``decodeBase58(..., std::vector<unsigned char>& vchRet);``. For example, in my 'Tests' section, I store the result in my ``decodedContent`` variable. Then you can read data inside. But this is a **variable of bytes**. You can do whatever you want with it. Besides, I used here a for each loop in order to print the result of decoding operation (It was a debug option to give you the decoded result).
Loopite
CC BY-SA 4.0
2023-08-16T13:37:07.010Z
Ahh i see, you i cant store them in viarable?
just.callme.client
CC BY-SA 4.0
2023-08-16T14:02:58.803Z
Of course you can. It was done in my example as ``decodedContent`` variable. But that's a matter for the code. I recommend that you ask any other questions about this on the stackoverflow C++ forum unless you have other questions about **Bitcoin**.
Loopite
CC BY-SA 4.0
2023-08-16T07:12:02.757Z
2023-08-16T07:12:02.757Z
Loopite
<p>its been a while after i done with my python bitcoin miner</p>
<p>And i realize that python is slower to do mining stuff, so i decided to rebuild it in c++ as you guys know c++ the faster than other programming language</p>
<p>But i have a problem to use base58 decode to hexadecimal in c++</p>
<p><strong>Python code</strong></p>
<pre><code>import base58

BtcAddr: str = &quot;1Htcz9y5sVuztuwTnfpWR4dhqirhLMcK7r&quot;

base58.b58decode_check(BtcAddr).hex()
</code></pre>
<p>And the output will be this</p>
<blockquote>
<p>00b9454405a39efcb023127cd6daacf9c133b84df3</p>
</blockquote>
<p>But i need that in c++ code, i already search online but i didnt find anything helpful</p>
<p>Can you guys help me? I really need the source code in c++</p>

<address><c++><p2pkh><base58><base58check>
How to use the base58 in c++
just.callme.client
# How to use the base58 in c++

(Asked by: username_0 on 2023-08-16)

its been a while after i done with my python bitcoin miner
And i realize that python is slower to do mining stuff, so i decided to rebuild it in c++ as you guys know c++ the faster than other programming language
But i have a problem to use base58 decode to hexadecimal in c++
Python code
import base58

BtcAddr: str = "1Htcz9y5sVuztuwTnfpWR4dhqirhLMcK7r"

base58.b58decode_check(BtcAddr).hex()

And the output will be this

00b9454405a39efcb023127cd6daacf9c133b84df3

But i need that in c++ code, i already search online but i didnt find anything helpful
Can you guys help me? I really need the source code in c++

**Tags:** address, c++, p2pkh, base58, base58check


---

## 1 answers

### Answer by username_1 on 2023-08-16. Score: 1 | Accepted answer

This solution is used by Bitcoin Core
base58.h
// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2015 The Bitcoin Core developers
// Copyright (c) 2023 username_1.

#ifndef CRYPTO_BASE58_H
#define CRYPTO_BASE58_H

#include 
#include 

/**
 * Encode a byte sequence as a base58-encoded string.
 * pbegin and pend cannot be NULL, unless both are.
 */
std::string encodeBase58(const unsigned char* pbegin, const unsigned char* pend);

/**
 * Encode a byte vector as a base58-encoded string
 */
std::string encodeBase58(const std::vector& vch);

/**
 * Decode a base58-encoded string (psz) into a byte vector (vchRet).
 * return true if decoding is successful.
 * psz cannot be NULL.
 */
bool decodeBase58(const char* psz, std::vector& vchRet);

/**
 * Decode a base58-encoded string (str) into a byte vector (vchRet).
 * return true if decoding is successful.
 */
bool decodeBase58(const std::string& str, std::vector& vchRet);

#endif // CRYPTO_BASE58_H

base58.cpp
// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2015 The Bitcoin Core developers
// Copyright (c) 2023 username_1

#include "base58.h"

#include 
#include 

#include 

/** All alphanumeric characters except for "0", "I", "O", and "l" */
static const char* pszBase58 { "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz" };

std::string encodeBase58(const unsigned char* pbegin, const unsigned char* pend)
{
    // Skip & count leading zeroes.
    int zeroes = 0;
    int length = 0;
    while (pbegin != pend && *pbegin == 0) {
        pbegin++;
        zeroes++;
    }
    // Allocate enough space in big-endian base58 representation.
    int size = (pend - pbegin) * 138 / 100 + 1; // log(256) / log(58), rounded up.
    std::vector b58(size);
    // Process the bytes.
    while (pbegin != pend) {
        int carry = *pbegin;
        int i = 0;
        // Apply "b58 = b58 * 256 + ch".
        for (auto it = b58.rbegin(); (carry != 0 || i < length) && (it != b58.rend()); it++, i++) {
            carry += 256 * (*it);
            *it = carry % 58;
            carry /= 58;
        }

        assert(carry == 0);
        length = i;
        pbegin++;
    }
    // Skip leading zeroes in base58 result.
    auto it = b58.begin() + (size - length);
    while (it != b58.end() && *it == 0)
        it++;
    // Translate the result into a string.
    std::string str;
    str.reserve(zeroes + (b58.end() - it));
    str.assign(zeroes, '1');
    while (it != b58.end())
        str += pszBase58[*(it++)];
    return str;
}

std::string encodeBase58(const std::vector& vch)
{
    return encodeBase58(&vch[0], &vch[0] + vch.size());
}

bool decodeBase58(const char* psz, std::vector& vch)
{
    // Skip leading spaces.
    while (*psz && isspace(*psz))
        psz++;
    // Skip and count leading '1's.
    int zeroes = 0;
    int length = 0;
    while (*psz == '1') {
        zeroes++;
        psz++;
    }
    // Allocate enough space in big-endian base256 representation.
    int size = strlen(psz) * 733 /1000 + 1; // log(58) / log(256), rounded up.
    std::vector b256(size);
    // Process the characters.
    while (*psz && !isspace(*psz)) {
        // Decode base58 character
        const char* ch = strchr(pszBase58, *psz);
        if (ch == nullptr)
            return false;
        // Apply "b256 = b256 * 58 + ch".
        int carry = ch - pszBase58;
        int i = 0;
        for (auto it = b256.rbegin(); (carry != 0 || i < length) && (it != b256.rend()); ++it, ++i) {
            carry += 58 * (*it);
            *it = carry % 256;
            carry /= 256;
        }
        assert(carry == 0);
        length = i;
        psz++;
    }
    // Skip trailing spaces.
    while (isspace(*psz))
        psz++;
    if (*psz != 0)
        return false;
    // Skip leading zeroes in b256.
    auto it = b256.begin() + (size - length);
    while (it != b256.end() && *it == 0)
        it++;
    // Copy result into output vector.
    vch.reserve(zeroes + (b256.end() - it));
    vch.assign(zeroes, 0x00);
    while (it != b256.end())
        vch.push_back(*(it++));
    return true;
}

bool decodeBase58(const std::string& str, std::vector& vchRet)
{
    return decodeBase58(str.c_str(), vchRet);
}

Tests
[ RUN      ] App.base58_Basics
00b9454405a39efcb023127cd6daacf9c133b84df30ce3172d
[       OK ] App.base58_Basics (0 ms)

From C++ code:
/**
 * @Author: username_1
 * @Description: Test for base58 encodings
 */

#include 

#include "crypto/base58.h"

#include 

TEST(App, base58_Basics)
{
    /*
     * Decode
     */
    const std::string data
    {
        "1Htcz9y5sVuztuwTnfpWR4dhqirhLMcK7r" // P2PKH address
    };

    std::vector decodedContent;
    decodeBase58(data, decodedContent);

    // ...Print content of decoded data...
    for (unsigned char i : decodedContent)
        std::cout << std::hex << std::setfill('0') << std::setw(2) << static_cast(i);

    std::cout << std::endl;
}

NOTE
The output is 00b9454405a39efcb023127cd6daacf9c133b84df30ce3172d NOT 00b9454405a39efcb023127cd6daacf9c133b84df3 for the string 1Htcz9y5sVuztuwTnfpWR4dhqirhLMcK7r. See https://appdevtools.com/base58-encoder-decoder.

> **Comments:**
> **username_0**: I see but that includes with hexadecimal value + checksum right? Well i dont want the checksum value, i only want the hexadecimal value  
> **username_1**: The thing is P2PKH has this structure: networkFlag (1 byte) + address (20 bytes since it has been hashed by RIPEMD-160) + checksum (4 bytes). Therefore the checksum is required. However if you WANT the hexadecimal value WITHOUT checksum you can process like this: ``1Htcz9y5sVuztuwTnfpWR4dhqirhLMcK7r`` <=> ``00b9454405a39efcb023127cd6daacf9c133b84df30ce3172d`` (With checksum) <=> ``00b9454405a39efcb023127cd6daacf9c133b84df3`` (Without checksum) <=> ``13ahvXA4uoeMuX4iKJW1mQkYjCWbt`` (Encoded in base58) You just have to parse output to get networkFlag and address separatly by using substr.  
> **username_1**: /!\. You should know that the checksum is REQUIRED. So you'll have to keep it from LEGACY addresses. It's part of the protocol. Functions you see above allow you to encode/decode base58 sequence. That's it.  
> **username_0**: So what youre trying to say is that i need to include the checksum in order to make a raw transactions?  
> **username_1**: In a raw transaction this is different. You'll have just to provide the address. This field can be determined from the Base58Check (1Htcz9y5sVuztuwTnfpWR4dhqirhLMcK7r). _To sum up:_ Base58**Check** requires a **checksum**. But raw txs need address only.  
> **username_0**: yeah i see, thanks for your help:)  
> **username_0**: hello sir, sorry to bother you but i face some issue with your code, the result from decodeBase58() only can be print through for loop, now heres the problem. How can i store the result inside a viarable?  
> **username_1**: decodeBase58 returns nothing. However, it takes a vector of unsigned char in **reference** : ``decodeBase58(..., std::vector<unsigned char>& vchRet);``. For example, in my 'Tests' section, I store the result in my ``decodedContent`` variable. Then you can read data inside. But this is a **variable of bytes**. You can do whatever you want with it. Besides, I used here a for each loop in order to print the result of decoding operation (It was a debug option to give you the decoded result).  
> **username_0**: Ahh i see, you i cant store them in viarable?  
> **username_1**: Of course you can. It was done in my example as ``decodedContent`` variable. But that's a matter for the code. I recommend that you ask any other questions about this on the stackoverflow C++ forum unless you have other questions about **Bitcoin**.  

---

