-
Notifications
You must be signed in to change notification settings - Fork 0
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
Redundant? #1
Comments
I think either I was not aware of the existence of libbase58 (given that Bitcoin Core does not use it), or I did not realize that libbase58 actually implements Base58Check encoding. (The latter would, of course, be a case of inexcusable ignorance, given that the README is very clear, now that I'm looking at it.) In any case, both projects appear to be complete, so it could just as easily be argued that libbase58 has been made redundant by libbase58check. 😉 I see that you are the author of libbase58. I assure you, I honestly did not intend to imply any opinion about your work by implementing my own. I had never looked at yours until now. After a cursory inspection of libbase58, here is my attempt to compare the feature sets of the two libraries… Advantages of libbase58 over libbase58check:
Advantages of libbase58check over libbase58:
libbase58check is "licensed" under the WTFPL, so please feel free to take and use anything you like from it. 😉 I actually cannot figure out how to make libbase58's command-line utility decode a Base58Check encoding:
For comparison, libbase58check's command-line utility works fine:
Incidentally, Here are the benchmark figures to support my speed claims above:
And here is the program I used to produce those benchmarks: #include <err.h>
#include <locale.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sysexits.h>
#include <time.h>
#include <base58check.h>
#include <libbase58.h>
#include <openssl/sha.h>
#define ITERATIONS 1000000
static bool my_sha256(void *digest, const void *data, size_t datasz) {
return !!SHA256(data, datasz, digest);
}
static void benchmark_libbase58_encode() {
unsigned char data[32];
for (size_t i = 0; i < sizeof data; ++i) data[i] = (unsigned char) i;
struct timespec start, stop;
clock_gettime(CLOCK_MONOTONIC, &start);
for (unsigned i = 0; i < ITERATIONS; ++i) {
char b58c[64];
size_t b58c_sz = sizeof b58c;
if (!b58check_enc(b58c, &b58c_sz, data[0], data + 1, sizeof data - 1)) {
errx(EX_SOFTWARE, "b58check_enc failed");
}
}
clock_gettime(CLOCK_MONOTONIC, &stop);
uint64_t ns = (stop.tv_sec - start.tv_sec) * 1000000000 + (stop.tv_nsec - start.tv_nsec);
printf("%15s %s: %'15" PRIu64 " ns\n", "libbase58", "encode", ns);
}
static void benchmark_libbase58check_encode() {
unsigned char data[32];
for (size_t i = 0; i < sizeof data; ++i) data[i] = (unsigned char) i;
struct timespec start, stop;
clock_gettime(CLOCK_MONOTONIC, &start);
for (unsigned i = 0; i < ITERATIONS; ++i) {
char out[64], *out_ptr = out;
size_t n_out = sizeof out;
if (base58check_encode(&out_ptr, &n_out, data, sizeof data, 0) < 0) {
errx(EX_SOFTWARE, "base58check_encode failed");
}
}
clock_gettime(CLOCK_MONOTONIC, &stop);
uint64_t ns = (stop.tv_sec - start.tv_sec) * 1000000000 + (stop.tv_nsec - start.tv_nsec);
printf("%15s %s: %'15" PRIu64 " ns\n", "libbase58check", "encode", ns);
}
static void benchmark_libbase58_decode() {
const char *b58 = "16qJFWMMHFy3xDdLmvUeyc2S6FrWRhJP51HsvDYdz9d1FsYG";
size_t b58sz = strlen(b58);
struct timespec start, stop;
clock_gettime(CLOCK_MONOTONIC, &start);
for (unsigned i = 0; i < ITERATIONS; ++i) {
unsigned char bin[36];
size_t binsz = sizeof bin;
if (!b58tobin(bin, &binsz, b58, b58sz)) {
errx(EX_SOFTWARE, "b58tobin failed");
}
if (b58check(bin, binsz, b58, b58sz) < 0) {
errx(EX_SOFTWARE, "b58check failed");
}
}
clock_gettime(CLOCK_MONOTONIC, &stop);
uint64_t ns = (stop.tv_sec - start.tv_sec) * 1000000000 + (stop.tv_nsec - start.tv_nsec);
printf("%15s %s: %'15" PRIu64 " ns\n", "libbase58", "decode", ns);
}
static void benchmark_libbase58check_decode() {
const char *in = "16qJFWMMHFy3xDdLmvUeyc2S6FrWRhJP51HsvDYdz9d1FsYG";
size_t n_in = strlen(in);
struct timespec start, stop;
clock_gettime(CLOCK_MONOTONIC, &start);
for (unsigned i = 0; i < ITERATIONS; ++i) {
unsigned char out[36], *out_ptr = out;
size_t n_out = sizeof out;
if (base58check_decode(&out_ptr, &n_out, in, n_in, 0) < 0) {
errx(EX_SOFTWARE, "base58check_decode failed");
}
}
clock_gettime(CLOCK_MONOTONIC, &stop);
uint64_t ns = (stop.tv_sec - start.tv_sec) * 1000000000 + (stop.tv_nsec - start.tv_nsec);
printf("%15s %s: %'15" PRIu64 " ns\n", "libbase58check", "decode", ns);
}
int main() {
setlocale(LC_NUMERIC, "");
b58_sha256_impl = my_sha256;
printf("%'u iterations...\n", ITERATIONS);
for (int i = 0; i < 2; ++i) {
putchar('\n');
benchmark_libbase58_encode();
benchmark_libbase58check_encode();
benchmark_libbase58_decode();
benchmark_libbase58check_decode();
}
return 0;
} |
I'd also add that libbase58 has fewer dependencies (I am surprised a GMP implementation performs better). OpenSSL in particular is not a GPL-compatible dependency. And WTFPL is non-free since it requires you to act on impulse ;p |
There are smart ways to use GMP and dumb ways. I use only its low-level functions, which really can't be beaten except by inlining the assembly, but that would give up too much maintainability for very little gain in performance. OpenSSL is licensed under Apache 2.0, which is quite permissive. I don't believe I am violating the terms of that license, am I? GPL is non-free since it is copyleft/infectious. I usually avoid making use of GPL code for that reason. LGPL is as far as I'll go in that direction.
I did laugh at this. Interesting argument. Maybe I should switch back to CC0. |
Why not just use (improve?) libbase58?
The text was updated successfully, but these errors were encountered: