-
Notifications
You must be signed in to change notification settings - Fork 199
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Develop/holland01 #7
base: master
Are you sure you want to change the base?
Changes from 3 commits
a996f28
47a8592
4690c5d
ccb7b43
4aaeea0
ec288eb
7bd15e3
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,19 +5,31 @@ | |
* under the terms of the standard MIT license. See COPYING for more details. | ||
*/ | ||
|
||
#ifndef WIN32 | ||
#include "libbase58.h" | ||
|
||
#ifndef _WIN32 | ||
#include <arpa/inet.h> | ||
#else | ||
#include <winsock2.h> | ||
#include <malloc.h> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There doesn't seem to be any malloc.h on at least Mingw cross-compilers. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'll replace with an appropriate |
||
|
||
#include <stdio.h> | ||
|
||
#ifdef _WIN64 | ||
typedef int64_t ssize_t; | ||
#else | ||
typedef int32_t ssize_t; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Would prefer to just avoid There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm honestly wondering why There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Convenience; There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Moved this issue to #8; please review |
||
#endif | ||
#endif | ||
|
||
#include <stdbool.h> | ||
#include <stddef.h> | ||
#include <stdint.h> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We still need stdint.h here, as this file uses intN_t types. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, and it's included in the header file There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It should be included in files where it is used directly. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ok, fair enough. |
||
#include <string.h> | ||
#include <stdlib.h> | ||
|
||
#include <sys/types.h> | ||
|
||
#include "libbase58.h" | ||
|
||
|
||
bool (*b58_sha256_impl)(void *, const void *, size_t) = NULL; | ||
|
||
|
@@ -37,39 +49,69 @@ typedef uint32_t b58_almostmaxint_t; | |
#define b58_almostmaxint_bits (sizeof(b58_almostmaxint_t) * 8) | ||
static const b58_almostmaxint_t b58_almostmaxint_mask = ((((b58_maxint_t)1) << b58_almostmaxint_bits) - 1); | ||
|
||
// MSVC 2017 doesn't support the GCC (and probably clang) extension | ||
// for dynamic arrays in C | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Variable length arrays are a standard C99 feature, not an extension. The library is intentionally designed to not use malloc/calloc/free. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
That may be, but MSVC still doesn't support them. _alloca or the MSVC _malloca can be used if that's preferred - these perform stack allocation (though _malloca will allocate heap for sufficiently large sizes). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. AFAIK, MSVC is a C++ compiler, not a C compiler. I suppose it can't hurt to use _malloca or such, based on a failed configure check for standards compatibility... There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. A few years back they added C99 support. It's still subpar in comparison to MinGW/GCC, but it's better than it used to be - enough to where people who like C end up using it over C++. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Wrote a simple alternative in #9; can you check if it works? |
||
#ifdef _WIN32 | ||
#define b58_log_err(msg, ...) printf("[" __FUNCTION__ " - ERROR]: " msg, __VA_ARGS__) | ||
|
||
#define b58_alloc_mem(type, name, count) \ | ||
type *name = NULL; \ | ||
do { \ | ||
name = calloc(count, sizeof(type)); \ | ||
if (!name) { \ | ||
b58_log_err("%s", "Could not allocate " #name); \ | ||
return false; \ | ||
} \ | ||
} while (0) | ||
|
||
#define b58_free_mem(v) \ | ||
do { \ | ||
if ((v)) { \ | ||
free((v)); \ | ||
} \ | ||
} while (0) | ||
#else | ||
#define b58_alloc_mem(type, name, count) type name[count] | ||
#define b58_free_mem(v) | ||
#endif | ||
|
||
bool b58tobin(void *bin, size_t *binszp, const char *b58, size_t b58sz) | ||
{ | ||
size_t binsz = *binszp; | ||
const unsigned char *b58u = (void*)b58; | ||
unsigned char *binu = bin; | ||
size_t outisz = (binsz + sizeof(b58_almostmaxint_t) - 1) / sizeof(b58_almostmaxint_t); | ||
b58_almostmaxint_t outi[outisz]; | ||
|
||
// b58_almostmaxint_t outi[outisz]; | ||
|
||
b58_alloc_mem(b58_almostmaxint_t, outi, outisz); | ||
|
||
b58_maxint_t t; | ||
b58_almostmaxint_t c; | ||
size_t i, j; | ||
uint8_t bytesleft = binsz % sizeof(b58_almostmaxint_t); | ||
b58_almostmaxint_t zeromask = bytesleft ? (b58_almostmaxint_mask << (bytesleft * 8)) : 0; | ||
unsigned zerocount = 0; | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please don't mess with the formatting. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Apologies, I'll be sure to omit any of those in the future. |
||
if (!b58sz) | ||
b58sz = strlen(b58); | ||
|
||
for (i = 0; i < outisz; ++i) { | ||
outi[i] = 0; | ||
} | ||
|
||
// Leading zeros, just count | ||
for (i = 0; i < b58sz && b58u[i] == '1'; ++i) | ||
++zerocount; | ||
|
||
for ( ; i < b58sz; ++i) | ||
{ | ||
if (b58u[i] & 0x80) | ||
// High-bit set on invalid digit | ||
return false; | ||
goto ret_false; | ||
if (b58digits_map[b58u[i]] == -1) | ||
// Invalid base58 digit | ||
return false; | ||
goto ret_false; | ||
c = (unsigned)b58digits_map[b58u[i]]; | ||
for (j = outisz; j--; ) | ||
{ | ||
|
@@ -79,27 +121,27 @@ bool b58tobin(void *bin, size_t *binszp, const char *b58, size_t b58sz) | |
} | ||
if (c) | ||
// Output number too big (carry to the next int32) | ||
return false; | ||
goto ret_false; | ||
if (outi[0] & zeromask) | ||
// Output number too big (last int32 filled too far) | ||
return false; | ||
goto ret_false; | ||
} | ||
|
||
j = 0; | ||
if (bytesleft) { | ||
for (i = bytesleft; i > 0; --i) { | ||
*(binu++) = (outi[0] >> (8 * (i - 1))) & 0xff; | ||
} | ||
++j; | ||
} | ||
|
||
for (; j < outisz; ++j) | ||
{ | ||
for (i = sizeof(*outi); i > 0; --i) { | ||
*(binu++) = (outi[j] >> (8 * (i - 1))) & 0xff; | ||
} | ||
} | ||
|
||
// Count canonical base58 byte count | ||
binu = bin; | ||
for (i = 0; i < binsz; ++i) | ||
|
@@ -109,8 +151,13 @@ bool b58tobin(void *bin, size_t *binszp, const char *b58, size_t b58sz) | |
--*binszp; | ||
} | ||
*binszp += zerocount; | ||
|
||
|
||
b58_free_mem(outi); | ||
return true; | ||
|
||
ret_false: | ||
b58_free_mem(outi); | ||
return false; | ||
} | ||
|
||
static | ||
|
@@ -131,13 +178,13 @@ int b58check(const void *bin, size_t binsz, const char *base58str, size_t b58sz) | |
return -2; | ||
if (memcmp(&binc[binsz - 4], buf, 4)) | ||
return -1; | ||
|
||
// Check number of zeros is correct AFTER verifying checksum (to avoid possibility of accessing base58str beyond the end) | ||
for (i = 0; binc[i] == '\0' && base58str[i] == '1'; ++i) | ||
{} // Just finding the end of zeros, nothing to do in loop | ||
if (binc[i] == '\0' || base58str[i] == '1') | ||
return -3; | ||
|
||
return binc[0]; | ||
} | ||
|
||
|
@@ -149,14 +196,16 @@ bool b58enc(char *b58, size_t *b58sz, const void *data, size_t binsz) | |
int carry; | ||
ssize_t i, j, high, zcount = 0; | ||
size_t size; | ||
|
||
while (zcount < binsz && !bin[zcount]) | ||
++zcount; | ||
|
||
size = (binsz - zcount) * 138 / 100 + 1; | ||
uint8_t buf[size]; | ||
//uint8_t buf[size]; | ||
|
||
b58_alloc_mem(uint8_t, buf, size); | ||
memset(buf, 0, size); | ||
|
||
for (i = zcount, high = size - 1; i < binsz; ++i, high = j) | ||
{ | ||
for (carry = bin[i], j = size - 1; (j > high) || carry; --j) | ||
|
@@ -166,37 +215,49 @@ bool b58enc(char *b58, size_t *b58sz, const void *data, size_t binsz) | |
carry /= 58; | ||
} | ||
} | ||
|
||
for (j = 0; j < size && !buf[j]; ++j); | ||
|
||
if (*b58sz <= zcount + size - j) | ||
{ | ||
*b58sz = zcount + size - j + 1; | ||
return false; | ||
|
||
goto error; | ||
} | ||
|
||
if (zcount) | ||
memset(b58, '1', zcount); | ||
for (i = zcount; j < size; ++i, ++j) | ||
b58[i] = b58digits_ordered[buf[j]]; | ||
b58[i] = '\0'; | ||
*b58sz = i + 1; | ||
|
||
return true; | ||
|
||
error: | ||
b58_free_mem(buf); | ||
return false; | ||
} | ||
|
||
bool b58check_enc(char *b58c, size_t *b58c_sz, uint8_t ver, const void *data, size_t datasz) | ||
{ | ||
uint8_t buf[1 + datasz + 0x20]; | ||
//uint8_t buf[1 + datasz + 0x20]; | ||
|
||
b58_alloc_mem(uint8_t, buf, 1 + datasz + 0x20); | ||
|
||
uint8_t *hash = &buf[1 + datasz]; | ||
|
||
buf[0] = ver; | ||
memcpy(&buf[1], data, datasz); | ||
if (!my_dblsha256(hash, buf, datasz + 1)) | ||
{ | ||
*b58c_sz = 0; | ||
|
||
b58_free_mem(buf); | ||
return false; | ||
} | ||
|
||
return b58enc(b58c, b58c_sz, buf, 1 + datasz + 4); | ||
|
||
bool rc = b58enc(b58c, b58c_sz, buf, 1 + datasz + 4); | ||
b58_free_mem(buf); | ||
return rc; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,6 +3,7 @@ | |
|
||
#include <stdbool.h> | ||
#include <stddef.h> | ||
#include <stdint.h> | ||
|
||
#ifdef __cplusplus | ||
extern "C" { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is this being moved?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
stdint.h is in libbase58.h - see here.
stdint.h is needed in the header for msvc compilation.
I also didn't see any reason include 4 header files before the libbas58.h file, considering that most of those aren't necessary for the function declarations found in it.