BCW_API bool hd_private_key::set_serialized(std::string encoded) { if (!is_base58(encoded)) return false; const data_chunk decoded = decode_base58(encoded); if (decoded.size() != serialized_length) return false; if (!verify_checksum(decoded)) return false; auto ds = make_deserializer(decoded.begin(), decoded.end()); auto prefix = ds.read_big_endian<uint32_t>(); if (prefix != mainnet_private_prefix && prefix != testnet_private_prefix) return false; valid_ = true; lineage_.testnet = prefix == testnet_private_prefix; lineage_.depth = ds.read_byte(); lineage_.parent_fingerprint = ds.read_little_endian<uint32_t>(); lineage_.child_number = ds.read_big_endian<uint32_t>(); c_ = ds.read_bytes<chain_code_size>(); ds.read_byte(); k_ = ds.read_bytes<ec_secret_size>(); K_ = secret_to_public_key(k_); return true; }
ec_secret wif_to_secret(const std::string& wif) { data_chunk decoded; if (!decode_base58(decoded, wif)) return ec_secret(); // 1 marker, 32 byte secret, optional 1 compressed flag, 4 checksum bytes if (decoded.size() != 1 + hash_size + 4 && decoded.size() != 1 + hash_size + 1 + 4) return ec_secret(); if (!verify_checksum(decoded)) return ec_secret(); // Check first byte is valid if (decoded[0] != payment_address::wif_version) return ec_secret(); // Checks passed. Drop the 0x80 start byte and checksum. decoded.erase(decoded.begin()); decoded.erase(decoded.end() - 4, decoded.end()); // If length is still 33 and last byte is 0x01, drop it. if (decoded.size() == 33 && decoded[32] == (uint8_t)0x01) decoded.erase(decoded.begin()+32); ec_secret secret; BITCOIN_ASSERT(secret.size() == decoded.size()); std::copy(decoded.begin(), decoded.end(), secret.begin()); return secret; }
bool is_wif_compressed(const std::string& wif) { data_chunk decoded; if (!decode_base58(decoded, wif)) return false; return decoded.size() == (1 + hash_size + 1 + 4) && decoded[33] == (uint8_t)0x01; }
bool payment_address::set_encoded(const std::string& encoded_address) { data_chunk decoded_address; if (!decode_base58(decoded_address, encoded_address)) return false; uint32_t checksum; return unwrap(version_, hash_, checksum, decoded_address); }
// For support of template implementation only, do not call directly. bool decode_base58_private(uint8_t* out, size_t out_size, const char* in) { data_chunk buffer; if (!decode_base58(buffer, in) || buffer.size() != out_size) return false; for (size_t i = 0; i < out_size; ++i) out[i] = buffer[i]; return true; }
bool payment_address::set_encoded(const std::string& encoded_address) { if (!is_base58(encoded_address)) return false; const data_chunk decoded_address = decode_base58(encoded_address); // version + 20 bytes short hash + 4 bytes checksum if (decoded_address.size() != 25) return false; if (!verify_checksum(decoded_address)) return false; version_ = decoded_address[0]; std::copy_n(decoded_address.begin() + 1, hash_.size(), hash_.begin()); return true; }
bool payment_address::set_encoded(const std::string& encoded_address) { const data_chunk decoded_address = decode_base58(encoded_address); // version + 20 bytes short hash + 4 bytes checksum if (decoded_address.size() != 25) return false; const uint8_t version = decoded_address[0]; if (!set_version(version)) return false; const data_chunk checksum_bytes( decoded_address.end() - 4, decoded_address.end()); // version + short hash const data_chunk main_body( decoded_address.begin(), decoded_address.end() - 4); // verify checksum bytes if (generate_sha256_checksum(main_body) != cast_chunk<uint32_t>(checksum_bytes)) return false; std::copy(main_body.begin() + 1, main_body.end(), hash_.begin()); return true; }
bool hd_public_key::set_encoded(const std::string& encoded) { data_chunk decoded; if (!decode_base58(decoded, encoded)) return false; if (decoded.size() != serialized_length) return false; if (!verify_checksum(decoded)) return false; auto ds = make_deserializer(decoded.begin(), decoded.end()); auto prefix = ds.read_big_endian<uint32_t>(); if (prefix != mainnet_public_prefix && prefix != testnet_public_prefix) return false; valid_ = true; lineage_.testnet = prefix == testnet_public_prefix; lineage_.depth = ds.read_byte(); lineage_.parent_fingerprint = ds.read_little_endian<uint32_t>(); lineage_.child_number = ds.read_big_endian<uint32_t>(); c_ = ds.read_bytes<chain_code_size>(); K_ = ds.read_data(33); return true; }
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_; }