/** * @brief Extension of cstring. * @param s pointer to csting that will be extended. * @param str string that will be used to exted cstring. * @param size lenght of string "str". * @return pointer to extended cstring s. * * Function extends cstring controls the behavior of the unsolicited reallocation. */ static cstring *append(cstring *s, char const *str, unsigned long size) { /* if(!s) { debug("cstring not given."); return NULL; } if(!str) { debug("str not given."); return NULL; }*/ /**If size will be exceeded, resize will be called, only if both statements * are true (needed size is bigger and enlargement fails) NULL will be returned. * @code * if (size >= s->tab_size && cstr_resize(s, size)) * return NULL; @endcode */ if (size >= s->tab_size && cstr_resize(s, size)) { debug("resize error\n"); return NULL; } if (s->size == 0) /// if str of cstring is empty strcpy(s->str, str); /// str will be copied else strcat(s->str, str); /// else it will be appended to end s->size = size; return s; }
cstring *bn_getvch(const mpz_t v) { /* get MPI format size */ size_t sz; char *buf = mpz_export(NULL, &sz, -1, 1, 1, 0, v); if (sz == 0) { free(buf); return cstr_new(NULL); } cstring *s_le = cstr_new_buf(buf, sz); free(buf); /* check if sign bit is available */ unsigned int msb = mpz_sizeinbase(v, 2); if ((!(msb & 0x07) && msb > 0)) { cstr_append_c(s_le, '\0'); sz++; } cstr_resize(s_le, sz); /* set sign bit */ if (mpz_sgn(v) == -1) { s_le->str[sz - 1] = (s_le->str[sz - 1] & 0xff) | 0x80; } return s_le; }
cstring *base58_decode_check(unsigned char *addrtype, const char *s_in) { /* decode base58 string */ cstring *s = base58_decode(s_in); if (!s) return NULL; if (s->len < 4) goto err_out; /* validate with trailing hash, then remove hash */ unsigned char md32[4]; bu_Hash4(md32, s->str, s->len - 4); if (memcmp(md32, &s->str[s->len - 4], 4)) goto err_out; cstr_resize(s, s->len - 4); /* if addrtype requested, remove from front of data string */ if (addrtype) { *addrtype = (unsigned char) s->str[0]; cstr_erase(s, 0, 1); } return s; err_out: cstr_free(s, true); return NULL; }
static void string_find_del(cstring *s, const struct buffer *buf) { /* wrap buffer in a script */ cstring *script = cstr_new_sz(buf->len + 8); bsp_push_data(script, buf->p, buf->len); /* search for script, as a substring of 's' */ void *p; unsigned int sublen = script->len; while ((p = memmem(s->str, s->len, script->str, sublen)) != NULL) { void *begin = s->str; void *end = begin + s->len; void *tail = p + sublen; unsigned int tail_len = end - tail; unsigned int new_len = s->len - sublen; memmove(p, tail, tail_len); cstr_resize(s, new_len); } cstr_free(script, true); }
logdb_bool logdb_record_deser_from_file(logdb_record* rec, logdb_log_db *db, enum logdb_error *error) { uint32_t len = 0; SHA256_CTX ctx = db->hashctx; /* prepare a copy of context that allows rollback */ SHA256_CTX ctx_final; uint8_t magic_buf[8]; uint8_t hashcheck[SHA256_DIGEST_LENGTH]; unsigned char check[SHA256_DIGEST_LENGTH]; /* prepate a buffer for the varint data (max 4 bytes) */ size_t buflen = sizeof(uint32_t); uint8_t readbuf[sizeof(uint32_t)]; *error = LOGDB_SUCCESS; /* read record magic */ if (fread(magic_buf, 8, 1, db->file) != 1) { /* very likely end of file reached */ return false; } sha256_Update(&ctx, magic_buf, 8); /* read start hash/magic per record */ if (fread(hashcheck, db->hashlen, 1, db->file) != 1) { *error = LOGDB_ERROR_DATASTREAM_ERROR; return false; } sha256_Update(&ctx, hashcheck, db->hashlen); /* read record mode (write / delete) */ if (fread(&rec->mode, 1, 1, db->file) != 1) { *error = LOGDB_ERROR_DATASTREAM_ERROR; return false; } sha256_Update(&ctx, (const uint8_t *)&rec->mode, 1); /* key */ if (!deser_varlen_file(&len, db->file, readbuf, &buflen)) { *error = LOGDB_ERROR_DATASTREAM_ERROR; return false; } sha256_Update(&ctx, readbuf, buflen); cstr_resize(rec->key, len); if (fread(rec->key->str, 1, len, db->file) != len) { *error = LOGDB_ERROR_DATASTREAM_ERROR; return false; } sha256_Update(&ctx, (const uint8_t *)rec->key->str, len); if (rec->mode == RECORD_TYPE_WRITE) { /* read value (not for delete mode) */ buflen = sizeof(uint32_t); if (!deser_varlen_file(&len, db->file, readbuf, &buflen)) { *error = LOGDB_ERROR_DATASTREAM_ERROR; return false; } sha256_Update(&ctx, readbuf, buflen); cstr_resize(rec->value, len); if (fread(rec->value->str, 1, len, db->file) != len) { *error = LOGDB_ERROR_DATASTREAM_ERROR; return false; } sha256_Update(&ctx, (const uint8_t *)rec->value->str, len); } /* read start hash/magic per record */ if (fread(hashcheck, db->hashlen, 1, db->file) != 1) { /* very likely end of file reached */ *error = LOGDB_ERROR_DATASTREAM_ERROR; return false; } sha256_Update(&ctx, hashcheck, db->hashlen); /* generate final checksum in a context copy */ ctx_final = ctx; sha256_Final(hashcheck, &ctx_final); /* read checksum from file, compare */ if (fread(check, 1, db->hashlen, db->file) != db->hashlen) { *error = LOGDB_ERROR_DATASTREAM_ERROR; return false; } if (memcmp(hashcheck,check,(size_t)db->hashlen) != 0) { *error = LOGDB_ERROR_CHECKSUM; return false; } /* mark record as written because we have just loaded it from disk */ rec->written = true; /* update sha256 context */ db->hashctx = ctx; return true; }
cstring *base58_encode(const void *data_, size_t data_len) { const unsigned char *data = data_; BIGNUM bn58, bn0, bn, dv, rem; BN_CTX *ctx; ctx = BN_CTX_new(); BN_init(&bn58); BN_init(&bn0); BN_init(&bn); BN_init(&dv); BN_init(&rem); BN_set_word(&bn58, 58); BN_set_word(&bn0, 0); unsigned char swapbuf[data_len + 1]; bu_reverse_copy(swapbuf, data, data_len); swapbuf[data_len] = 0; bn_setvch(&bn, swapbuf, sizeof(swapbuf)); cstring *rs = cstr_new_sz(data_len * 138 / 100 + 1); while (BN_cmp(&bn, &bn0) > 0) { if (!BN_div(&dv, &rem, &bn, &bn58, ctx)) goto err_out; BN_copy(&bn, &dv); unsigned int c = (int32_t)BN_get_word(&rem); cstr_append_c(rs, base58_chars[c]); } unsigned int i; for (i = 0; i < data_len; i++) { if (data[i] == 0) cstr_append_c(rs, base58_chars[0]); else break; } cstring *rs_swap = cstr_new_sz(rs->len); cstr_resize(rs_swap, rs->len); bu_reverse_copy((unsigned char *) rs_swap->str, (unsigned char *) rs->str, rs->len); cstr_free(rs, true); rs = rs_swap; out: BN_clear_free(&bn58); BN_clear_free(&bn0); BN_clear_free(&bn); BN_clear_free(&dv); BN_clear_free(&rem); BN_CTX_free(ctx); return rs; err_out: cstr_free(rs, true); rs = NULL; goto out; }
cstring *base58_decode(const char *s_in) { BIGNUM bn58, bn, bnChar; BN_CTX *ctx; cstring *ret = NULL; ctx = BN_CTX_new(); BN_init(&bn58); BN_init(&bn); BN_init(&bnChar); BN_set_word(&bn58, 58); BN_set_word(&bn, 0); while (isspace((int32_t)*s_in)) s_in++; const char *p; for (p = s_in; *p; p++) { const char *p1 = strchr(base58_chars, *p); if (!p1) { while (isspace((int32_t)*p)) p++; if (*p != '\0') goto out; break; } BN_set_word(&bnChar, p1 - base58_chars); if (!BN_mul(&bn, &bn, &bn58, ctx)) goto out; if (!BN_add(&bn, &bn, &bnChar)) goto out; } cstring *tmp = bn_getvch(&bn); if ((tmp->len >= 2) && (tmp->str[tmp->len - 1] == 0) && ((unsigned char)tmp->str[tmp->len - 2] >= 0x80)) cstr_resize(tmp, tmp->len - 1); unsigned int leading_zero = 0; for (p = s_in; *p == base58_chars[0]; p++) leading_zero++; unsigned int be_sz = (uint32_t)tmp->len + (uint32_t)leading_zero; cstring *tmp_be = cstr_new_sz(be_sz); cstr_resize(tmp_be, be_sz); memset(tmp_be->str, 0, be_sz); bu_reverse_copy((unsigned char *)tmp_be->str + leading_zero, (unsigned char *)tmp->str, tmp->len); cstr_free(tmp, true); ret = tmp_be; out: BN_clear_free(&bn58); BN_clear_free(&bn); BN_clear_free(&bnChar); BN_CTX_free(ctx); return ret; }
void test_cstr() { cstring* s1 = cstr_new("foo"); cstring* s2 = cstr_new("foo"); cstring* s3 = cstr_new("bar"); cstring* s4 = cstr_new("bar1"); cstring* s = cstr_new("foo"); assert(s != NULL); assert(s->len == 3); assert(strcmp(s->str, "foo") == 0); cstr_free(s, true); s = cstr_new_sz(200); assert(s != NULL); assert(s->alloc > 200); assert(s->len == 0); cstr_free(s, true); s = cstr_new_buf("foo", 2); assert(s != NULL); assert(s->len == 2); assert(strcmp(s->str, "fo") == 0); cstr_free(s, true); s = cstr_new(NULL); assert(s != NULL); cstr_append_buf(s, "f", 1); cstr_append_buf(s, "o", 1); cstr_append_buf(s, "o", 1); assert(s->len == 3); assert(strcmp(s->str, "foo") == 0); cstr_free(s, true); s = cstr_new("foo"); assert(s != NULL); cstr_resize(s, 2); cstr_resize(s, 2); cstr_alloc_minsize(s, 2); cstr_alloc_minsize(s, 1); assert(s->len == 2); assert(strcmp(s->str, "fo") == 0); cstr_resize(s, 4); assert(s->len == 4); assert(s->alloc > 4); memcpy(s->str, "food", 4); assert(strcmp(s->str, "food") == 0); cstr_free(s, true); assert(cstr_compare(s1, s2) == 0); assert(cstr_compare(s1, s3) == 1); assert(cstr_compare(s3, s1) == -1); assert(cstr_compare(s3, s4) == -1); assert(cstr_compare(s4, s3) == 1); assert(cstr_equal(s1, s2) == true); assert(cstr_equal(s1, s3) == false); assert(cstr_equal(s1, NULL) == false); assert(cstr_equal(s2, s3) == false); assert(cstr_equal(s3, s3) == true); assert(cstr_equal(s3, s4) == false); cstr_erase(s4, 0, 3); cstr_erase(s4, 110, 3); cstr_erase(s4, s4->len, 0); cstr_erase(s4, 0, 100); assert(strcmp(s4->str, "1") == 0); cstr_free(s1, true); cstr_free(s2, true); cstr_free(s3, true); cstr_free(s4, true); }
static void test_basic(void) { cstring *s = cstr_new("foo"); assert(s != NULL); assert(s->len == 3); assert(strcmp(s->str, "foo") == 0); cstr_free(s, true); s = cstr_new_sz(200); assert(s != NULL); assert(s->alloc > 200); assert(s->len == 0); cstr_free(s, true); s = cstr_new_buf("foo", 2); assert(s != NULL); assert(s->len == 2); assert(strcmp(s->str, "fo") == 0); cstr_free(s, true); s = cstr_new(NULL); assert(s != NULL); cstr_append_buf(s, "f", 1); cstr_append_buf(s, "o", 1); cstr_append_buf(s, "o", 1); assert(s->len == 3); assert(strcmp(s->str, "foo") == 0); cstr_free(s, true); s = cstr_new("foo"); assert(s != NULL); cstr_resize(s, 2); assert(s->len == 2); assert(strcmp(s->str, "fo") == 0); cstr_resize(s, 4); assert(s->len == 4); assert(s->alloc > 4); memcpy(s->str, "food", 4); assert(strcmp(s->str, "food") == 0); cstr_free(s, true); cstring *s1 = cstr_new("foo"); cstring *s2 = cstr_new("foo"); cstring *s3 = cstr_new("bar"); assert(cstr_equal(s1, s2) == true); assert(cstr_equal(s1, s3) == false); assert(cstr_equal(s2, s3) == false); assert(cstr_equal(s3, s3) == true); cstr_free(s1, true); cstr_free(s2, true); cstr_free(s3, true); }
btc_bool btc_tx_sighash(const btc_tx* tx_to, const cstring* fromPubKey, unsigned int in_num, int hashtype, uint8_t* hash) { if (in_num >= tx_to->vin->len) return false; btc_bool ret = true; btc_tx* tx_tmp = btc_tx_new(); btc_tx_copy(tx_tmp, tx_to); cstring* new_script = cstr_new_sz(fromPubKey->len); btc_script_copy_without_op_codeseperator(fromPubKey, new_script); unsigned int i; btc_tx_in* tx_in; for (i = 0; i < tx_tmp->vin->len; i++) { tx_in = vector_idx(tx_tmp->vin, i); cstr_resize(tx_in->script_sig, 0); if (i == in_num) cstr_append_buf(tx_in->script_sig, new_script->str, new_script->len); } cstr_free(new_script, true); /* Blank out some of the outputs */ if ((hashtype & 0x1f) == SIGHASH_NONE) { /* Wildcard payee */ if (tx_tmp->vout) vector_free(tx_tmp->vout, true); tx_tmp->vout = vector_new(1, btc_tx_out_free_cb); /* Let the others update at will */ for (i = 0; i < tx_tmp->vin->len; i++) { tx_in = vector_idx(tx_tmp->vin, i); if (i != in_num) tx_in->sequence = 0; } } else if ((hashtype & 0x1f) == SIGHASH_SINGLE) { /* Only lock-in the txout payee at same index as txin */ unsigned int n_out = in_num; if (n_out >= tx_tmp->vout->len) { //TODO: set error code ret = false; goto out; } vector_resize(tx_tmp->vout, n_out + 1); for (i = 0; i < n_out; i++) { btc_tx_out* tx_out; tx_out = vector_idx(tx_tmp->vout, i); tx_out->value = -1; if (tx_out->script_pubkey) { cstr_free(tx_out->script_pubkey, true); tx_out->script_pubkey = NULL; } } /* Let the others update at will */ for (i = 0; i < tx_tmp->vin->len; i++) { tx_in = vector_idx(tx_tmp->vin, i); if (i != in_num) tx_in->sequence = 0; } } /* Blank out other inputs completely; not recommended for open transactions */ if (hashtype & SIGHASH_ANYONECANPAY) { if (in_num > 0) vector_remove_range(tx_tmp->vin, 0, in_num); vector_resize(tx_tmp->vin, 1); } cstring* s = cstr_new_sz(512); btc_tx_serialize(s, tx_tmp); ser_s32(s, hashtype); sha256_Raw((const uint8_t*)s->str, s->len, hash); sha256_Raw(hash, 32, hash); cstr_free(s, true); out: btc_tx_free(tx_tmp); return ret; }