#include "utils.h" #include #include #include #include #include #include #include static char to_hex_digit(unsigned int v) { if (v < 10U) { return (char)('0' + v); } return (char)('a' + (v - 10U)); } void sb_init(StrBuf *sb) { sb->data = NULL; sb->len = 0; sb->cap = 0; } void sb_free(StrBuf *sb) { free(sb->data); sb->data = NULL; sb->len = 0; sb->cap = 0; } int sb_reserve(StrBuf *sb, size_t extra) { size_t need; size_t new_cap; char *p; need = sb->len + extra + 1; if (need <= sb->cap) { return 1; } new_cap = (sb->cap == 0) ? 128 : sb->cap; while (new_cap < need) { new_cap *= 2; } p = (char *)realloc(sb->data, new_cap); if (p == NULL) { return 0; } sb->data = p; sb->cap = new_cap; if (sb->len == 0) { sb->data[0] = '\0'; } return 1; } int sb_append(StrBuf *sb, const char *s) { size_t n = strlen(s); if (sb_reserve(sb, n) == 0) { return 0; } memcpy(sb->data + sb->len, s, n + 1); sb->len += n; return 1; } int sb_append_n(StrBuf *sb, const char *s, size_t n) { if (sb_reserve(sb, n) == 0) { return 0; } memcpy(sb->data + sb->len, s, n); sb->len += n; sb->data[sb->len] = '\0'; return 1; } int sb_append_byte_hex(StrBuf *sb, uint8_t b) { char tmp[3]; tmp[0] = to_hex_digit((unsigned int)(b >> 4)); tmp[1] = to_hex_digit((unsigned int)(b & 0x0F)); tmp[2] = '\0'; return sb_append(sb, tmp); } char *sb_take(StrBuf *sb) { char *out = sb->data; sb->data = NULL; sb->len = 0; sb->cap = 0; return out; } int hex_char_to_val(char c) { if (c >= '0' && c <= '9') { return c - '0'; } if (c >= 'a' && c <= 'f') { return 10 + (c - 'a'); } if (c >= 'A' && c <= 'F') { return 10 + (c - 'A'); } return -1; } int hex_to_bytes(const char *hex, uint8_t **out, size_t *out_len) { size_t n; size_t i; uint8_t *buf; if (hex == NULL || out == NULL || out_len == NULL) { return 0; } n = strlen(hex); if ((n % 2) != 0) { return 0; } buf = (uint8_t *)malloc(n / 2); if (buf == NULL) { return 0; } for (i = 0; i < n; i += 2) { int hi = hex_char_to_val(hex[i]); int lo = hex_char_to_val(hex[i + 1]); if (hi < 0 || lo < 0) { free(buf); return 0; } buf[i / 2] = (uint8_t)((hi << 4) | lo); } *out = buf; *out_len = n / 2; return 1; } int hex_to_fixed_bytes(const char *hex, uint8_t *out, size_t out_len) { size_t n; size_t i; if (hex == NULL || out == NULL) { return 0; } n = strlen(hex); if (n != out_len * 2) { return 0; } for (i = 0; i < n; i += 2) { int hi = hex_char_to_val(hex[i]); int lo = hex_char_to_val(hex[i + 1]); if (hi < 0 || lo < 0) { return 0; } out[i / 2] = (uint8_t)((hi << 4) | lo); } return 1; } char *bytes_to_hex(const uint8_t *data, size_t len) { static const char tab[] = "0123456789abcdef"; char *out; size_t i; out = (char *)malloc(len * 2 + 1); if (out == NULL) { return NULL; } for (i = 0; i < len; ++i) { out[2 * i] = tab[data[i] >> 4]; out[2 * i + 1] = tab[data[i] & 0x0F]; } out[len * 2] = '\0'; return out; } void reverse_bytes(uint8_t *data, size_t n) { size_t i; for (i = 0; i < n / 2; ++i) { uint8_t t = data[i]; data[i] = data[n - 1 - i]; data[n - 1 - i] = t; } } void double_sha256(const uint8_t *data, size_t len, uint8_t out[32]) { uint8_t tmp[SHA256_DIGEST_LENGTH]; SHA256(data, len, tmp); SHA256(tmp, SHA256_DIGEST_LENGTH, out); } int encode_varint_hex(uint64_t value, StrBuf *sb) { uint8_t bytes[9]; size_t n = 0; size_t i; if (value < 0xFD) { bytes[n++] = (uint8_t)value; } else if (value <= 0xFFFFULL) { bytes[n++] = 0xFD; bytes[n++] = (uint8_t)(value & 0xFF); bytes[n++] = (uint8_t)((value >> 8) & 0xFF); } else if (value <= 0xFFFFFFFFULL) { bytes[n++] = 0xFE; bytes[n++] = (uint8_t)(value & 0xFF); bytes[n++] = (uint8_t)((value >> 8) & 0xFF); bytes[n++] = (uint8_t)((value >> 16) & 0xFF); bytes[n++] = (uint8_t)((value >> 24) & 0xFF); } else { bytes[n++] = 0xFF; bytes[n++] = (uint8_t)(value & 0xFF); bytes[n++] = (uint8_t)((value >> 8) & 0xFF); bytes[n++] = (uint8_t)((value >> 16) & 0xFF); bytes[n++] = (uint8_t)((value >> 24) & 0xFF); bytes[n++] = (uint8_t)((value >> 32) & 0xFF); bytes[n++] = (uint8_t)((value >> 40) & 0xFF); bytes[n++] = (uint8_t)((value >> 48) & 0xFF); bytes[n++] = (uint8_t)((value >> 56) & 0xFF); } for (i = 0; i < n; ++i) { if (sb_append_byte_hex(sb, bytes[i]) == 0) { return 0; } } return 1; } static char *bn_to_fixed_hex64(const BIGNUM *bn) { char *tmp; char *out; size_t n; size_t i; tmp = BN_bn2hex(bn); if (tmp == NULL) { return NULL; } n = strlen(tmp); if (n > 64) { OPENSSL_free(tmp); return NULL; } out = (char *)malloc(65); if (out == NULL) { OPENSSL_free(tmp); return NULL; } for (i = 0; i < 64; ++i) { out[i] = '0'; } out[64] = '\0'; for (i = 0; i < n; ++i) { char c = tmp[i]; if (isupper((unsigned char)c)) { c = (char)tolower((unsigned char)c); } out[64 - n + i] = c; } OPENSSL_free(tmp); return out; } char *decode_nbits_hex(uint32_t nbits) { BN_CTX *ctx; BIGNUM *bn; BIGNUM *sig; char *out; uint32_t exponent; uint32_t significand; exponent = (nbits >> 24) & 0xFF; significand = nbits & 0x007FFFFF; ctx = BN_CTX_new(); bn = BN_new(); sig = BN_new(); if (ctx == NULL || bn == NULL || sig == NULL) { BN_CTX_free(ctx); BN_free(bn); BN_free(sig); return NULL; } BN_set_word(sig, significand); BN_copy(bn, sig); if (exponent >= 3) { BN_lshift(bn, bn, 8 * ((int)exponent - 3)); } else { BN_rshift(bn, bn, 8 * (3 - (int)exponent)); } out = bn_to_fixed_hex64(bn); BN_CTX_free(ctx); BN_free(bn); BN_free(sig); return out; } char *calculate_target_hex(const char *bits_hex, double difficulty_factor, const char *network) { static const char *MAX_TARGET_HEX = "00000000ffff0000000000000000000000000000000000000000000000000000"; BIGNUM *max_bn; BIGNUM *limit_bn; BIGNUM *num_bn; BIGNUM *den_bn; BIGNUM *result_bn; BN_CTX *ctx; char *original; char *out; uint64_t scaled_factor; const uint64_t SCALE = 1000000000ULL; uint32_t nbits; if (bits_hex == NULL || network == NULL) { return NULL; } nbits = (uint32_t)strtoul(bits_hex, NULL, 16); original = decode_nbits_hex(nbits); if (original == NULL) { return NULL; } if (strcmp(network, "regtest") == 0) { if (difficulty_factor < 0.0) { difficulty_factor = 0.1; } } else { difficulty_factor = 1.0; } if (difficulty_factor == 0.0) { return original; } scaled_factor = (uint64_t)llround(difficulty_factor * (double)SCALE); if (scaled_factor == 0ULL) { scaled_factor = 1ULL; } ctx = BN_CTX_new(); max_bn = BN_new(); limit_bn = BN_new(); num_bn = BN_new(); den_bn = BN_new(); result_bn = BN_new(); if (ctx == NULL || max_bn == NULL || limit_bn == NULL || num_bn == NULL || den_bn == NULL || result_bn == NULL) { BN_CTX_free(ctx); BN_free(max_bn); BN_free(limit_bn); BN_free(num_bn); BN_free(den_bn); BN_free(result_bn); free(original); return NULL; } BN_hex2bn(&max_bn, MAX_TARGET_HEX); BN_hex2bn(&limit_bn, "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); BN_copy(num_bn, max_bn); BN_mul_word(num_bn, (BN_ULONG)SCALE); BN_set_word(den_bn, (BN_ULONG)scaled_factor); BN_div(result_bn, NULL, num_bn, den_bn, ctx); if (BN_cmp(result_bn, limit_bn) > 0) { BN_copy(result_bn, limit_bn); } out = bn_to_fixed_hex64(result_bn); BN_CTX_free(ctx); BN_free(max_bn); BN_free(limit_bn); BN_free(num_bn); BN_free(den_bn); BN_free(result_bn); free(original); return out; } char *hex_add_width(const char *base_hex, int add_value) { static const char *hex_digits = "0123456789abcdef"; char *out; size_t n; int carry; size_t pos; if (base_hex == NULL || add_value < 0) { return NULL; } n = strlen(base_hex); if (n == 0) { return NULL; } out = strdup(base_hex); if (out == NULL) { return NULL; } carry = add_value; pos = n; while (pos > 0 && carry > 0) { int digit = hex_char_to_val(out[pos - 1]); int sum; if (digit < 0) { free(out); return NULL; } sum = digit + carry; out[pos - 1] = hex_digits[sum & 0x0F]; carry = sum >> 4; --pos; } return out; }