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; }
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(); }
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_; }