static int vg_prefix_test(vg_exec_context_t *vxcp) { vg_prefix_context_t *vcpp = (vg_prefix_context_t *) vxcp->vxc_vc; vg_prefix_t *vp; int res = 0; /* * We constrain the prefix so that we can check for * a match without generating the lower four byte * check code. */ BN_bin2bn(vxcp->vxc_binres, 25, &vxcp->vxc_bntarg); research: vp = vg_prefix_avl_search(&vcpp->vcp_avlroot, &vxcp->vxc_bntarg); if (vp) { if (vg_exec_context_upgrade_lock(vxcp)) goto research; vg_exec_context_consolidate_key(vxcp); // vcpp->base.vc_output_match(&vcpp->base, vxcp->vxc_key, // vp->vp_pattern, &combined_compressed); vcpp->base.vc_output_match(&vcpp->base, vxcp, vp->vp_pattern); vcpp->base.vc_found++; if (vcpp->base.vc_only_one) { return 2; } if (vcpp->base.vc_remove_on_match) { /* Subtract the range from the difficulty */ vg_prefix_range_sum(vp, &vxcp->vxc_bntarg, &vxcp->vxc_bntmp); BN_sub(&vxcp->vxc_bntmp, &vcpp->vcp_difficulty, &vxcp->vxc_bntarg); BN_copy(&vcpp->vcp_difficulty, &vxcp->vxc_bntmp); vg_prefix_delete(&vcpp->vcp_avlroot,vp); vcpp->base.vc_npatterns--; if (!avl_root_empty(&vcpp->vcp_avlroot)) vg_prefix_context_next_difficulty( vcpp, &vxcp->vxc_bntmp, &vxcp->vxc_bntmp2, vxcp->vxc_bnctx); vcpp->base.vc_pattern_generation++; } res = 1; } if (avl_root_empty(&vcpp->vcp_avlroot)) { return 2; } return res; }
static void vg_prefix_context_clear_all_patterns(vg_context_t *vcp) { vg_prefix_context_t *vcpp = (vg_prefix_context_t *) vcp; vg_prefix_t *vp; unsigned long npfx_left = 0; while (!avl_root_empty(&vcpp->vcp_avlroot)) { vp = avl_item_entry(vcpp->vcp_avlroot.ar_root, vg_prefix_t, vp_item); vg_prefix_delete(&vcpp->vcp_avlroot, vp); npfx_left++; } assert(npfx_left == vcpp->base.vc_npatterns); vcpp->base.vc_npatterns = 0; vcpp->base.vc_npatterns_start = 0; vcpp->base.vc_found = 0; BN_clear(&vcpp->vcp_difficulty); }
static vg_prefix_t * vg_prefix_add_ranges(avl_root_t *rootp, const char *pattern, BIGNUM **ranges, vg_prefix_t *master) { vg_prefix_t *vp, *vp2 = NULL; assert(ranges[0]); vp = vg_prefix_add(rootp, pattern, ranges[0], ranges[1]); if (!vp) return NULL; if (ranges[2]) { vp2 = vg_prefix_add(rootp, pattern, ranges[2], ranges[3]); if (!vp2) { vg_prefix_delete(rootp, vp); return NULL; } } if (!master) { vp->vp_sibling = vp2; if (vp2) vp2->vp_sibling = vp; } else if (vp2) { vp->vp_sibling = vp2; vp2->vp_sibling = (master->vp_sibling ? master->vp_sibling : master); master->vp_sibling = vp; } else { vp->vp_sibling = (master->vp_sibling ? master->vp_sibling : master); master->vp_sibling = vp; } return vp; }
static int vg_prefix_context_add_patterns(vg_context_t *vcp, const char ** const patterns, int npatterns) { vg_prefix_context_t *vcpp = (vg_prefix_context_t *) vcp; prefix_case_iter_t caseiter; vg_prefix_t *vp, *vp2; BN_CTX *bnctx; BIGNUM bntmp, bntmp2, bntmp3; BIGNUM *ranges[4]; int ret = 0; int i, impossible = 0; int case_impossible; unsigned long npfx; char *dbuf; bnctx = BN_CTX_new(); BN_init(&bntmp); BN_init(&bntmp2); BN_init(&bntmp3); npfx = 0; for (i = 0; i < npatterns; i++) { if (!vcpp->vcp_caseinsensitive) { vp = NULL; ret = get_prefix_ranges(vcpp->base.vc_addrtype, patterns[i], ranges, bnctx); if (!ret) { vp = vg_prefix_add_ranges(&vcpp->vcp_avlroot, patterns[i], ranges, NULL); } } else { /* Case-enumerate the prefix */ if (!prefix_case_iter_init(&caseiter, patterns[i])) { fprintf(stderr, "Prefix '%s' is too long\n", patterns[i]); continue; } if (caseiter.ci_nbits > 16) { fprintf(stderr, "WARNING: Prefix '%s' has " "2^%d case-varied derivatives\n", patterns[i], caseiter.ci_nbits); } case_impossible = 0; vp = NULL; do { ret = get_prefix_ranges(vcpp->base.vc_addrtype, caseiter.ci_prefix, ranges, bnctx); if (ret == -2) { case_impossible++; ret = 0; continue; } if (ret) break; vp2 = vg_prefix_add_ranges(&vcpp->vcp_avlroot, patterns[i], ranges, vp); if (!vp2) { ret = -1; break; } if (!vp) vp = vp2; } while (prefix_case_iter_next(&caseiter)); if (!vp && case_impossible) ret = -2; if (ret && vp) { vg_prefix_delete(&vcpp->vcp_avlroot, vp); vp = NULL; } } if (ret == -2) { fprintf(stderr, "Prefix '%s' not possible\n", patterns[i]); impossible++; } if (!vp) continue; npfx++; /* Determine the probability of finding a match */ vg_prefix_range_sum(vp, &bntmp, &bntmp2); BN_add(&bntmp2, &vcpp->vcp_difficulty, &bntmp); BN_copy(&vcpp->vcp_difficulty, &bntmp2); if (vcp->vc_verbose > 1) { BN_clear(&bntmp2); BN_set_bit(&bntmp2, 192); BN_div(&bntmp3, NULL, &bntmp2, &bntmp, bnctx); dbuf = BN_bn2dec(&bntmp3); fprintf(stderr, "Prefix difficulty: %20s %s\n", dbuf, patterns[i]); OPENSSL_free(dbuf); } } vcpp->base.vc_npatterns += npfx; vcpp->base.vc_npatterns_start += npfx; if (!npfx && impossible) { const char *ats = "bitcoin", *bw = "\"1\""; switch (vcpp->base.vc_addrtype) { case 5: ats = "bitcoin script"; bw = "\"3\""; break; case 111: ats = "testnet"; bw = "\"m\" or \"n\""; break; case 52: ats = "namecoin"; bw = "\"M\" or \"N\""; break; default: break; } fprintf(stderr, "Hint: valid %s addresses begin with %s\n", ats, bw); } if (npfx) vg_prefix_context_next_difficulty(vcpp, &bntmp, &bntmp2, bnctx); ret = (npfx != 0); BN_clear_free(&bntmp); BN_clear_free(&bntmp2); BN_clear_free(&bntmp3); BN_CTX_free(bnctx); return ret; }