Example #1
0
ec_point secret_to_public_key(const ec_secret& secret,
    bool compressed)
{
    init.init();
    size_t size = ec_uncompressed_size;
    if (compressed)
        size = ec_compressed_size;

    ec_point out(size);
    int out_size;
    if (!secp256k1_ecdsa_pubkey_create(out.data(), &out_size, secret.data(),
            compressed))
        return ec_point();
    BITCOIN_ASSERT(size == static_cast<size_t>(out_size));
    return out;
}
Example #2
0
ec_point recover_compact(compact_signature signature,
    hash_digest hash, bool compressed)
{
    init.init();

    size_t public_key_size = ec_uncompressed_size;
    if (compressed)
        public_key_size = ec_compressed_size;

    ec_point out(public_key_size);
    int out_size;
    if (0 < secp256k1_ecdsa_recover_compact(hash.data(), hash.size(),
        signature.signature.data(), out.data(), &out_size, compressed,
        signature.recid))
    {
        BITCOIN_ASSERT(public_key_size == static_cast<size_t>(out_size));
        return out;
    }

    // Error case:
    return ec_point();
}
Example #3
0
bool stealth_address::set_encoded(const std::string& encoded_address)
{
    valid_ = false;
    data_chunk raw_address;
    if (!decode_base58(raw_address, encoded_address))
        return false;

    // Size is guarded until we get to N.
    auto required_size = min_address_size;
    if (raw_address.size() < required_size)
        return valid_;

    if (!verify_checksum(raw_address))
        return valid_;

    // Start walking the array.
    auto iter = raw_address.begin();

    // [version:1 = 0x2a]
    auto version = *iter;
    if (version != network::mainnet && version != network::testnet)
        return valid_;
    testnet_ = (version == network::testnet);
    ++iter;

    // [options:1]
    auto options = *iter;
    if (options != flags::none && options != flags::reuse_key)
        return valid_;
    ++iter;

    // [scan_pubkey:33]
    auto scan_key_begin = iter;
    iter += compressed_pubkey_size;
    scan_pubkey_ = ec_point(scan_key_begin, iter);

    // [N:1]
    auto number_spend_pubkeys = *iter;
    ++iter;

    // Adjust and retest required size. for pubkey list.
    required_size += number_spend_pubkeys * compressed_pubkey_size;
    if (raw_address.size() < required_size)
        return valid_;

    // We don't explicitly save 'reuse', instead we add to spend_pubkeys_.
    if (options == flags::reuse_key)
        spend_pubkeys_.emplace_back(scan_pubkey_);

    // [spend_pubkey_1:33]..[spend_pubkey_N:33]
    for (auto key = 0; key < number_spend_pubkeys; ++key)
    {
        auto spend_key_begin = iter;
        iter += compressed_pubkey_size;
        spend_pubkeys_.emplace_back(ec_point(spend_key_begin, iter));
    }

    // [number_signatures:1]
    signatures_ = *iter;
    ++iter;

    // [prefix_number_bits:1]
    auto prefix_number_bits = *iter;
    if (prefix_number_bits > max_prefix_bits)
        return valid_;
    ++iter;

    // [prefix:prefix_number_bits / 8, round up]
    // Adjust and retest required size for prefix bytes.
    auto prefix_bytes = (prefix_number_bits + (byte_bits - 1)) / byte_bits;
    required_size += prefix_bytes;
    if (raw_address.size() != required_size)
        return valid_;

    // Prefix not yet supported on server!
    //BITCOIN_ASSERT(prefix_number_bits == 0);
    //if (prefix_number_bits != 0)
    //    return valid_;

    // Deserialize the prefix bytes/blocks.
    data_chunk raw_prefix(iter, iter + prefix_bytes);
    prefix_ = binary_type(prefix_number_bits, raw_prefix);

    valid_ = true;
    return valid_;
}