MCPcopy Create free account
hub / github.com/ElementsProject/elements / GetGroup

Method GetGroup

src/netaddress.cpp:766–824  ·  view source on GitHub ↗

* Get the canonical identifier of our network group * * The groups are assigned in a way where it should be costly for an attacker to * obtain addresses with many different group identifiers, even if it is cheap * to obtain addresses with the same identifier. * * @note No two connections will be attempted to addresses with the same network * group. */

Source from the content-addressed store, hash-verified

764 * group.
765 */
766std::vector<unsigned char> CNetAddr::GetGroup(const std::vector<bool> &asmap) const
767{
768 std::vector<unsigned char> vchRet;
769 uint32_t net_class = GetNetClass();
770 // If non-empty asmap is supplied and the address is IPv4/IPv6,
771 // return ASN to be used for bucketing.
772 uint32_t asn = GetMappedAS(asmap);
773 if (asn != 0) { // Either asmap was empty, or address has non-asmappable net class (e.g. TOR).
774 vchRet.push_back(NET_IPV6); // IPv4 and IPv6 with same ASN should be in the same bucket
775 for (int i = 0; i < 4; i++) {
776 vchRet.push_back((asn >> (8 * i)) & 0xFF);
777 }
778 return vchRet;
779 }
780
781 vchRet.push_back(net_class);
782 int nBits{0};
783
784 if (IsLocal()) {
785 // all local addresses belong to the same group
786 } else if (IsInternal()) {
787 // all internal-usage addresses get their own group
788 nBits = ADDR_INTERNAL_SIZE * 8;
789 } else if (!IsRoutable()) {
790 // all other unroutable addresses belong to the same group
791 } else if (HasLinkedIPv4()) {
792 // IPv4 addresses (and mapped IPv4 addresses) use /16 groups
793 uint32_t ipv4 = GetLinkedIPv4();
794 vchRet.push_back((ipv4 >> 24) & 0xFF);
795 vchRet.push_back((ipv4 >> 16) & 0xFF);
796 return vchRet;
797 } else if (IsTor() || IsI2P()) {
798 nBits = 4;
799 } else if (IsCJDNS()) {
800 // Treat in the same way as Tor and I2P because the address in all of
801 // them is "random" bytes (derived from a public key). However in CJDNS
802 // the first byte is a constant 0xfc, so the random bytes come after it.
803 // Thus skip the constant 8 bits at the start.
804 nBits = 12;
805 } else if (IsHeNet()) {
806 // for he.net, use /36 groups
807 nBits = 36;
808 } else {
809 // for the rest of the IPv6 network, use /32 groups
810 nBits = 32;
811 }
812
813 // Push our address onto vchRet.
814 const size_t num_bytes = nBits / 8;
815 vchRet.insert(vchRet.end(), m_addr.begin(), m_addr.begin() + num_bytes);
816 nBits %= 8;
817 // ...for the last byte, push nBits and for the rest of the byte push 1's
818 if (nBits > 0) {
819 assert(num_bytes < m_addr.size());
820 vchRet.push_back(m_addr[num_bytes] | ((1 << (8 - nBits)) - 1));
821 }
822
823 return vchRet;

Callers 4

GetNewBucketMethod · 0.80
ThreadOpenConnectionsMethod · 0.80
BOOST_AUTO_TEST_CASEFunction · 0.80

Calls 6

IsLocalFunction · 0.85
push_backMethod · 0.45
insertMethod · 0.45
endMethod · 0.45
beginMethod · 0.45
sizeMethod · 0.45

Tested by 1

BOOST_AUTO_TEST_CASEFunction · 0.64