解码比特币Base58地址到字节数组
Decoding Bitcoin Base58 address to byte array
我正试图将Base58字符串中的比特币地址解码为字节数组,为此,我重写了Satoshi存储库中的原始函数(https://github.com/bitcoin/bitcoin/blob/master/src/base58.cpp),用c++编写,到c#(我正在使用)。
原始代码
static const char* pszBase58 = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
bool DecodeBase58(const char *psz, std::vector<unsigned char>& vch) {
// Skip leading spaces.
while (*psz && isspace(*psz))
psz++;
// Skip and count leading '1's.
int zeroes = 0;
while (*psz == '1') {
zeroes++;
psz++;
}
// Allocate enough space in big-endian base256 representation.
std::vector<unsigned char> b256(strlen(psz) * 733 / 1000 + 1); // log(58) / log(256), rounded up.
// Process the characters.
while (*psz && !isspace(*psz)) {
// Decode base58 character
const char *ch = strchr(pszBase58, *psz);
if (ch == NULL)
return false;
// Apply "b256 = b256 * 58 + ch".
int carry = ch - pszBase58;
for (std::vector<unsigned char>::reverse_iterator it = b256.rbegin(); it != b256.rend(); it++) {
carry += 58 * (*it);
*it = carry % 256;
carry /= 256;
}
assert(carry == 0);
psz++;
}
// Skip trailing spaces.
while (isspace(*psz))
psz++;
if (*psz != 0)
return false;
// Skip leading zeroes in b256.
std::vector<unsigned char>::iterator it = b256.begin();
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;
}
Mine重写c版本
private static string Base58characters = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
public static bool Decode(string source, ref byte[] destination)
{
int i = 0;
while (i < source.Length)
{
if (source[i] == 0 || !Char.IsWhiteSpace(source[i]))
{
break;
}
i++;
}
int zeros = 0;
while (source[i] == '1')
{
zeros++;
i++;
}
byte[] b256 = new byte[(source.Length - i) * 733 / 1000 + 1];
while (i < source.Length && !Char.IsWhiteSpace(source[i]))
{
int ch = Base58characters.IndexOf(source[i]);
if (ch == -1) //null
{
return false;
}
int carry = Base58characters.IndexOf(source[i]);
for (int k = b256.Length - 1; k > 0; k--)
{
carry += 58 * b256[k];
b256[k] = (byte)(carry % 256);
carry /= 256;
}
i++;
}
while (i < source.Length && Char.IsWhiteSpace(source[i]))
{
i++;
}
if (i != source.Length)
{
return false;
}
int j = 0;
while (j < b256.Length && b256[j] == 0)
{
j++;
}
destination = new byte[zeros + (b256.Length - j)];
for (int kk = 0; kk < destination.Length; kk++)
{
if (kk < zeros)
{
destination[kk] = 0x00;
}
else
{
destination[kk] = b256[j++];
}
}
return true;
}
我用于从字节数组转换为HexString 的函数
public static string ByteArrayToHexString(byte[] source)
{
return BitConverter.ToString(source).Replace("-", "");
}
为了测试是否一切正常,我使用了在线的测试用例(https://github.com/ThePiachu/Bitcoin-Unit-Tests/blob/master/Address/Address%20Generation%20Test%201.txt)。好的是,这个测试有97%是正确通过的,但对于3,有一个小错误,我不知道它是从哪里来的。所以我要你们指出,这些测试可能出了什么问题,或者我在重写时哪里出错了。提前谢谢。
出现错误的测试用例为1、21和25。
1。输入:16UwLL9风险3QfPqBUvKofHmBq7wMtjvM输出:000966776006953D5567439E5E39F86A0D273BEED61967F6应为:00010966776006953D5567439E5E39F86A0D273BEED61967F6
21。输入:1v3VUYGogXD7S1E8ipahj7QXgC568dz1输出:0008201462985DF5255E4A6C9D493C932FAC98EF791E2F22应为:000A08201462985DF5255E4A6C9D493C932FAC98EF791E2F22
25。输入:1axVFjCkMWDFCHjQHf99AsszXTuzxLxxg输出:006C0B8995C7464E89F6760900EA6978DF18157388421561应为:00066C0B8995C7464E89F6760900EA6978DF18157388421561
在for循环中:
for (int k = b256.Length - 1; k > 0; k--)
循环条件应该是k >= 0
,这样就不会跳过b256
中的第一个字节。
- 使用 swig 追加到字节数组
- 是否通过向封闭对象的地址添加字节偏移量来访问子对象
- Ascii .txt文件到字节数组 - C++
- static_casting基对象的地址到派生类的指针
- 将 CByteArray 复制到字节数组中会导致访问冲突
- 将HICON / HCURSOR复制到字节数组中
- 将 QImage 保存到字节数组
- 如何将数据复制到字节数组的某些部分
- 将数据流到字节数组中
- 如何将任何值转换为字节数组并将其附加到字节列表
- 以C++(Arduino)为单位比较指针到字节
- C++BigInteger到字节数组
- 从套接字到字节数组的读取数据中的意外字符
- C++结构到字节*引发错误
- std ::字符串到字节[]
- 如何从iStream的开头便移到字节中的偏移
- 将结构添加到字节向量,然后添加另一个
- crypto++将密钥保存到字节队列并返回到密钥
- 从INT64到字节数组
- 解码比特币Base58地址到字节数组