static void test_privkey_valid_dec(const char *base58_str, cstring *payload, bool compress, bool is_testnet) { assert(payload != NULL); cstring *pl = cstr_new_sz(payload->len + 1); cstr_append_buf(pl, payload->str, payload->len); if (compress) cstr_append_c(pl, 1); unsigned char addrtype; cstring *dec = base58_decode_check(&addrtype, base58_str); assert(dec != NULL); if (is_testnet) assert(addrtype == PRIVKEY_ADDRESS_TEST); else assert(addrtype == PRIVKEY_ADDRESS); if (compress) { assert(dec->len == 33); assert(dec->str[32] == 1); } else assert(dec->len == 32); assert(dec->len == pl->len); assert(memcmp(dec->str, pl->str, pl->len) == 0); cstr_free(dec, true); cstr_free(pl, true); cstr_free(payload, true); }
// check for validity of curve point in case of public data not performed int hdnode_deserialize(const char *str, HDNode *node) { uint8_t node_data[78]; memset(node, 0, sizeof(HDNode)); if (!base58_decode_check(str, node_data, sizeof(node_data))) { return -1; } uint32_t version = read_be(node_data); if (version == 0x0488B21E) { // public node memcpy(node->public_key, node_data + 45, 33); } else if (version == 0x0488ADE4) { // private node if (node_data[45]) { // invalid data return -2; } memcpy(node->private_key, node_data + 46, 32); hdnode_fill_public_key(node); } else { return -3; // invalid version } node->depth = node_data[4]; node->fingerprint = read_be(node_data + 5); node->child_num = read_be(node_data + 9); memcpy(node->chain_code, node_data + 13, 32); return 0; }
bool coinExtractAddressType(const CoinType *coin, const char *addr, uint32_t *address_type) { if (!addr) return false; uint8_t addr_raw[MAX_ADDR_RAW_SIZE]; int len = base58_decode_check(addr, addr_raw, MAX_ADDR_RAW_SIZE); if (len >= 21) { return coinExtractAddressTypeRaw(coin, addr_raw, address_type); } return false; }
static void runtest_keys_invalid(const char *json_base_fn) { char *json_fn = test_filename(json_base_fn); cJSON *tests = read_json(json_fn); assert((tests->type & 0xFF) == cJSON_Array); unsigned int idx; for (idx = 0; idx < cJSON_GetArraySize(tests); idx++) { cJSON *test = cJSON_GetArrayItem(tests, idx); assert((test->type & 0xFF) == cJSON_Array); assert(cJSON_GetArraySize(test) == 1); cJSON *j_base58 = cJSON_GetArrayItem(test, 0); assert((j_base58->type & 0xFF) == cJSON_String); unsigned char addrtype; cstring *payload = base58_decode_check(&addrtype, j_base58->valuestring); bool is_valid = (payload != NULL); if (is_valid) if ((addrtype == PUBKEY_ADDRESS_TEST) || (addrtype == PUBKEY_ADDRESS) || (addrtype == SCRIPT_ADDRESS_TEST) || (addrtype == SCRIPT_ADDRESS)) is_valid = (payload->len == RIPEMD160_DIGEST_LENGTH); else if ((addrtype == PRIVKEY_ADDRESS_TEST) || (addrtype == PRIVKEY_ADDRESS)) is_valid = (payload->len == 32 || (payload->len == 33 && payload->str[32] == 1)); else is_valid = false; cstr_free(payload, true); assert(!is_valid); } free(json_fn); cJSON_Delete(tests); }
static void append_output(char *addr_str, char *amount_str) { unsigned char addrtype = 0; cstring *payload = base58_decode_check(&addrtype, addr_str); bool is_script = is_script_addr(addrtype); uint64_t amt = (uint64_t) strtoull(amount_str, NULL, 10); struct bp_txout *txout = calloc(1, sizeof(struct bp_txout)); if (!txout || !payload) { fprintf(stderr, "OOM\n"); exit(1); } txout->nValue = amt; if (is_script) txout->scriptPubKey = bsp_make_scripthash(payload); else txout->scriptPubKey = bsp_make_pubkeyhash(payload); parr_add(tx.vout, txout); }
static void test_pubkey_valid_dec(const char *base58_str, cstring *payload, const char *addrtype_str, bool is_testnet) { assert(payload != NULL); bool addrtype_pubkey = (strcmp(addrtype_str, "pubkey") == 0); bool addrtype_script = (strcmp(addrtype_str, "script") == 0); assert(addrtype_pubkey || addrtype_script); enum bitc_address_type addrtype; if (addrtype_pubkey) { if (is_testnet) addrtype = PUBKEY_ADDRESS_TEST; else addrtype = PUBKEY_ADDRESS; } else { if (is_testnet) addrtype = SCRIPT_ADDRESS_TEST; else addrtype = SCRIPT_ADDRESS; } unsigned char addrtype_dec; cstring *dec = base58_decode_check(&addrtype_dec, base58_str); assert(dec != NULL); assert(addrtype == addrtype_dec); assert(dec->len == RIPEMD160_DIGEST_LENGTH); assert(payload->len == dec->len); assert(memcmp(payload->str, dec->str, dec->len) == 0); cstr_free(dec, true); cstr_free(payload, true); }
static error_t parse_opt (int key, char *arg, struct argp_state *state) { switch(key) { case 1001: // --locktime=NNNNN opt_locktime = arg; break; case 1002: // --nversion=NNNNN opt_version = arg; break; case 1003: // --blank opt_blank = true; break; case 1030: // --output-json opt_decode_json = true; break; case 1040: // --strict-free opt_strict_free = true; break; case 1010: { // --txin=TXID:VOUT char *colon = strchr(arg, ':'); if (!colon) return ARGP_ERR_UNKNOWN; if ((colon - arg) != 64) return ARGP_ERR_UNKNOWN; if (!is_digitstr(colon + 1)) return ARGP_ERR_UNKNOWN; char hexstr[65]; memcpy(hexstr, arg, 64); hexstr[64] = 0; if (!is_hexstr(hexstr, false)) return ARGP_ERR_UNKNOWN; opt_txin = clist_append(opt_txin, strdup(arg)); break; } case 1011: { // --delete-txin=INDEX if (!is_digitstr(arg)) return ARGP_ERR_UNKNOWN; opt_del_txin = clist_append(opt_del_txin, int_to_ptr(atoi(arg))); break; } case 1020: { // --txout=ADDRESS:AMOUNT char *colon = strchr(arg, ':'); if (!colon) return ARGP_ERR_UNKNOWN; unsigned int partlen = colon - arg; if (!is_digitstr(colon + 1)) return ARGP_ERR_UNKNOWN; char addrstr[partlen + 1]; memcpy(addrstr, arg, partlen); addrstr[partlen] = 0; cstring *payload = base58_decode_check(NULL, addrstr); bool payload_invalid = (!payload || (payload->len != 21)); cstr_free(payload, true); if (payload_invalid) return ARGP_ERR_UNKNOWN; opt_txout = clist_append(opt_txout, strdup(arg)); break; } case 1021: { // --delete-txout=INDEX if (!is_digitstr(arg)) return ARGP_ERR_UNKNOWN; opt_del_txout = clist_append(opt_del_txout, int_to_ptr(atoi(arg))); break; } case ARGP_KEY_ARG: if (opt_hexdata) return ARGP_ERR_UNKNOWN; opt_hexdata = arg; break; default: return ARGP_ERR_UNKNOWN; } return 0; }