diff --git a/src/cashaddrenc.cpp b/src/cashaddrenc.cpp --- a/src/cashaddrenc.cpp +++ b/src/cashaddrenc.cpp @@ -17,26 +17,53 @@ // Size of data-part in a pubkey/script cash address. // Consists of: 8 bits version + 160 bits hash. -const size_t CASHADDR_GROUPED_SIZE = 34; /* 5 bit representation */ -const size_t CASHADDR_BYTES = 21; /* 8 bit representation */ +const size_t CASHADDR_BYTES = 21; /* 8 bit representation */ namespace { // Convert the data part to a 5 bit representation. template -std::vector PackAddrData(const T &id, uint8_t type, - size_t expectedSize) { - std::vector data = {uint8_t(type << 3)}; +std::vector PackAddrData(const T &id, uint8_t type) { + uint8_t version_byte = uint8_t(type << 3); + auto size = id.size(); + uint8_t encoded_size = 0; + switch (size * 8) { + case 160: + encoded_size = 0; + break; + case 192: + encoded_size = 1; + break; + case 224: + encoded_size = 2; + break; + case 256: + encoded_size = 3; + break; + case 320: + encoded_size = 4; + break; + case 384: + encoded_size = 5; + break; + case 448: + encoded_size = 6; + break; + case 512: + encoded_size = 7; + break; + default: + throw std::runtime_error( + "Error packing cashaddr: invalid address length"); + } + version_byte |= encoded_size; + std::vector data = {version_byte}; data.insert(data.end(), id.begin(), id.end()); std::vector converted; - converted.reserve(expectedSize); + converted.reserve(((size + 1) * 8 + 4) / 5); ConvertBits<8, 5, true>(converted, begin(data), end(data)); - if (converted.size() != expectedSize) { - throw std::runtime_error("Error packing cashaddr"); - } - return converted; } @@ -46,14 +73,12 @@ CashAddrEncoder(const CChainParams &p) : params(p) {} std::string operator()(const CKeyID &id) const { - std::vector data = - PackAddrData(id, PUBKEY_TYPE, CASHADDR_GROUPED_SIZE); + std::vector data = PackAddrData(id, PUBKEY_TYPE); return cashaddr::Encode(params.CashAddrPrefix(), data); } std::string operator()(const CScriptID &id) const { - std::vector data = - PackAddrData(id, SCRIPT_TYPE, CASHADDR_GROUPED_SIZE); + std::vector data = PackAddrData(id, SCRIPT_TYPE); return cashaddr::Encode(params.CashAddrPrefix(), data); }