diff --git a/src/Makefile.am b/src/Makefile.am index 32cc689a67..a2dae0bae2 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -204,9 +204,11 @@ BITCOIN_CORE_H = \ merkleblock.h \ names/applications.h \ names/common.h \ + names/domain.h \ names/encoding.h \ names/main.h \ names/mempool.h \ + names/records.h \ net.h \ net_permissions.h \ net_processing.h \ @@ -718,7 +720,9 @@ libbitcoin_common_a_SOURCES = \ merkleblock.cpp \ names/applications.cpp \ names/common.cpp \ + names/domain.cpp \ names/encoding.cpp \ + names/records.cpp \ net_types.cpp \ netaddress.cpp \ netbase.cpp \ diff --git a/src/Makefile.test.include b/src/Makefile.test.include index 3e3b01e5e5..63dc55c61e 100644 --- a/src/Makefile.test.include +++ b/src/Makefile.test.include @@ -112,7 +112,9 @@ BITCOIN_TESTS =\ test/multisig_tests.cpp \ test/name_tests.cpp \ test/name_applications_tests.cpp \ + test/name_domain_tests.cpp \ test/name_mempool_tests.cpp \ + test/name_records_tests.cpp \ test/net_peer_connection_tests.cpp \ test/net_peer_eviction_tests.cpp \ test/net_tests.cpp \ diff --git a/src/names/applications.cpp b/src/names/applications.cpp index ad4c82ced9..ab8419fb61 100644 --- a/src/names/applications.cpp +++ b/src/names/applications.cpp @@ -5,12 +5,14 @@ #include #include - -#include - #include - #include +#include + +#include +#include + +#include namespace { @@ -181,25 +183,27 @@ DescFromName (const valtype& name, NameNamespace ns) } bool -IsValidJSONOrEmptyString (const std::string& text){ +IsValidJSONOrEmptyString (const std::string& text) +{ UniValue v; return text.empty() || v.read(text); -} +} bool -IsMinimalJSONOrEmptyString (const std::string& text){ +IsMinimalJSONOrEmptyString (const std::string& text) +{ UniValue v; if(text.empty()){ return true; - } + } - if(!v.read(text)){ + if(!v.read(text)){ return false; - } + } const std::string minimalJSON = GetMinimalJSON(text); - + const bool isMinimal = (text == minimalJSON); if(!isMinimal){ @@ -210,10 +214,56 @@ IsMinimalJSONOrEmptyString (const std::string& text){ } std::string -GetMinimalJSON (const std::string& text){ +GetMinimalJSON (const std::string& text) +{ UniValue v; v.read(text); return v.write(0,0); } + +bool +IsValidIPV4 (const std::string& text) +{ + boost::system::error_code ec; + boost::asio::ip::address_v4 ipv4; + + ipv4 = boost::asio::ip::make_address_v4(text, ec); + + return !ec; +} + +bool +IsValidIPV6 (const std::string& text) +{ + boost::system::error_code ec; + boost::asio::ip::address_v6 ipv6; + + ipv6 = boost::asio::ip::make_address_v6(text, ec); + + return !ec; +} + +bool +IsValidOnionAddress(const std::string& text) +{ + if(!text.ends_with(".onion")){ + return false; + } else { + CNetAddr cnet; + return cnet.SetSpecial(text); + } +} + +bool +IsValidI2PAddress(const std::string& text) +{ + if(!text.ends_with(".b32.i2p")){ + return false; + } else { + CNetAddr cnet; + return cnet.SetSpecial(text); + } + +} diff --git a/src/names/applications.h b/src/names/applications.h index 525d90f182..3aa739c393 100644 --- a/src/names/applications.h +++ b/src/names/applications.h @@ -29,4 +29,13 @@ bool IsMinimalJSONOrEmptyString (const std::string& text); std::string GetMinimalJSON (const std::string& text); +bool IsValidIPV4 (const std::string& text); + +bool IsValidIPV6 (const std::string& text); + +bool IsValidOnionAddress(const std::string& text); + +bool IsValidI2PAddress(const std::string& text); + + #endif // H_BITCOIN_NAMES_APPLICATIONS diff --git a/src/names/domain.cpp b/src/names/domain.cpp new file mode 100644 index 0000000000..3d87f8f67e --- /dev/null +++ b/src/names/domain.cpp @@ -0,0 +1,45 @@ +// Copyright (c) 2024 Rose Turing +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include + +#include +#include + +#include +#include + +std::string Domain::getName(){ + return name; +} + +void Domain::setName(const std::string& text){ + this->name = text; +} + +std::list Domain::getIPv4s(){ + return this->ipv4s; +} + +void Domain::setIPv4s(const std::list ipv4s){ + this->ipv4s = ipv4s; +} + +std::list Domain::getIPv6s(){ + return this->ipv6s; +} + +void Domain::setIPv6s(const std::list ipv6s){ + this->ipv6s = ipv6s; +} + +Domain::Domain(const std::string& name){ + this->name = name; +} + +Domain::Domain(){ + this->name = ""; +} + + diff --git a/src/names/domain.h b/src/names/domain.h new file mode 100644 index 0000000000..3346d2f47b --- /dev/null +++ b/src/names/domain.h @@ -0,0 +1,35 @@ +// Copyright (c) 2024 Rose Turing +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#ifndef H_BITCOIN_NAMES_DOMAIN +#define H_BITCOIN_NAMES_DOMAIN + +#include "applications.h" +#include "records.h" + +#include +#include + +class Domain{ + + private: + std::string name; + std::list ipv4s; + std::list ipv6s; + + public: + std::string getName(); + void setName(const std::string& text); + + std::list getIPv4s(); + void setIPv4s(const std::list ipv4s); + + std::list getIPv6s(); + void setIPv6s(const std::list ipv6s); + + Domain(const std::string& name); + Domain(); +}; + +#endif //H_BITCOIN_NAMES_DOMAIN diff --git a/src/names/records.cpp b/src/names/records.cpp new file mode 100644 index 0000000000..21a7a2f544 --- /dev/null +++ b/src/names/records.cpp @@ -0,0 +1,46 @@ +// Copyright (c) 2024 Rose Turing +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include "records.h" +#include "applications.h" + +#include + +std::string DomainRecord::getDomain(){ + return domain; +} + +void DomainRecord::setDomain(const std::string& text){ + domain = text; +} + +DomainRecord::DomainRecord(std::string& domain){ + this->domain = domain; +} + +DomainRecord::DomainRecord(){ + this->domain = ""; +} + +AddressRecord::AddressRecord(std::string& domain, std::string& address) + :DomainRecord(domain) +{ + this->address = address; +} + +std::string AddressRecord::getAddress(){ + return address; +} + +void AddressRecord::setAddress(const std::string& text){ + this->address = text; +} + +bool IPv4Record::validate() { + return IsValidIPV4(this->getAddress()); +} + +bool IPv6Record::validate() { + return IsValidIPV6(this->getAddress()); +} diff --git a/src/names/records.h b/src/names/records.h new file mode 100644 index 0000000000..910817d81a --- /dev/null +++ b/src/names/records.h @@ -0,0 +1,55 @@ +// Copyright (c) 2024 Rose Turing +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php + +#ifndef H_BITCOIN_NAMES_RECORDS +#define H_BITCOIN_NAMES_RECORDS + +#include + +class DomainRecord{ + + private: + std::string domain; + + public: + std::string getDomain(); + void setDomain(const std::string& text); + + DomainRecord(std::string& domain); + DomainRecord(); + + virtual bool validate() = 0; + +}; + +class AddressRecord : public DomainRecord{ + + private: + std::string address; + + public: + std::string getAddress(); + void setAddress(const std::string& text); + + using DomainRecord::DomainRecord; + AddressRecord(std::string& domain, std::string& address); + + virtual bool validate() override = 0; +}; + +class IPv4Record : public AddressRecord{ + + public: + using AddressRecord::AddressRecord; + bool validate() override; +}; + +class IPv6Record : public AddressRecord{ + + public: + using AddressRecord::AddressRecord; + bool validate() override; +}; + +#endif //H_BITCOIN_NAMES_RECORDS diff --git a/src/test/name_applications_tests.cpp b/src/test/name_applications_tests.cpp index 72cb7bc7d7..ea6136ceda 100644 --- a/src/test/name_applications_tests.cpp +++ b/src/test/name_applications_tests.cpp @@ -141,4 +141,54 @@ BOOST_AUTO_TEST_CASE( minimal_json ) BOOST_CHECK_EQUAL(IsMinimalJSONOrEmptyString("{\"bar\":[1, 2, 3]}"), false); } +BOOST_AUTO_TEST_CASE( valid_ipv4 ) +{ + BOOST_CHECK_EQUAL(IsValidIPV4("192.168.1.1"), true); + + BOOST_CHECK_EQUAL(IsValidIPV4("256.168.1.1"), false); + + BOOST_CHECK_EQUAL(IsValidIPV4("010.011.002.012"), false); + + BOOST_CHECK_EQUAL(IsValidIPV4("0x7f.0x0.0x0.0x1"), false); + + BOOST_CHECK_EQUAL(IsValidIPV4("0:0:0:0:0:0:0:1"), false); +} + +BOOST_AUTO_TEST_CASE( valid_ipv6 ) +{ + BOOST_CHECK_EQUAL(IsValidIPV6("192.168.1.1"), false); + + BOOST_CHECK_EQUAL(IsValidIPV6("0:0:0:0:0:0:0:1"), true); +} + +BOOST_AUTO_TEST_CASE( valid_onion ) +{ + BOOST_CHECK_EQUAL(IsValidOnionAddress("https://google.com"), false); + + BOOST_CHECK_EQUAL(IsValidOnionAddress("https://2gzyxa5ihm7nsggfxnu52rck2vv4rvmdlkiu3zzui5du4xyclen53wid.onion"), false); + + BOOST_CHECK_EQUAL(IsValidOnionAddress("https://i2p-projekt.i2p"), false); + + BOOST_CHECK_EQUAL(IsValidOnionAddress("google.com"), false); + + BOOST_CHECK_EQUAL(IsValidOnionAddress("2gzyxa5ihm7nsggfxnu52rck2vv4rvmdlkiu3zzui5du4xyclen53wid.onion"), true); + + BOOST_CHECK_EQUAL(IsValidOnionAddress("i2p-projekt.i2p"), false); +} + +BOOST_AUTO_TEST_CASE( valid_i2p ) +{ + BOOST_CHECK_EQUAL(IsValidI2PAddress("https://google.com"), false); + + BOOST_CHECK_EQUAL(IsValidI2PAddress("https://2gzyxa5ihm7nsggfxnu52rck2vv4rvmdlkiu3zzui5du4xyclen53wid.onion"), false); + + BOOST_CHECK_EQUAL(IsValidI2PAddress("https://udhdrtrcetjm5sxzskjyr5ztpeszydbh4dpl3pl4utgqqw2v4jna.b32.i2p"), false); + + BOOST_CHECK_EQUAL(IsValidI2PAddress("google.com"), false); + + BOOST_CHECK_EQUAL(IsValidI2PAddress("2gzyxa5ihm7nsggfxnu52rck2vv4rvmdlkiu3zzui5du4xyclen53wid.onion"), false); + + BOOST_CHECK_EQUAL(IsValidI2PAddress("udhdrtrcetjm5sxzskjyr5ztpeszydbh4dpl3pl4utgqqw2v4jna.b32.i2p"), true); +} + BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/name_domain_tests.cpp b/src/test/name_domain_tests.cpp new file mode 100644 index 0000000000..a811781dc1 --- /dev/null +++ b/src/test/name_domain_tests.cpp @@ -0,0 +1,35 @@ +// Copyright (c) 2024 Rose Turing +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include "../names/domain.h" + +#include "../names/records.h" +#include + +#include + +#include +#include + +BOOST_AUTO_TEST_SUITE(name_domain_tests) + +Domain test_domain; +BOOST_AUTO_TEST_CASE( domain_tests ){ + + std::list test_ipv4_list; + + std::list test_ipv6_list; + + test_domain.setName("namecoin.bit"); + BOOST_CHECK(test_domain.getName() == "namecoin.bit"); + + test_domain.setIPv4s(test_ipv4_list); + BOOST_CHECK(test_domain.getIPv4s() == test_ipv4_list); + + test_domain.setIPv6s(test_ipv6_list); + BOOST_CHECK(test_domain.getIPv6s() == test_ipv6_list); + +}; + +BOOST_AUTO_TEST_SUITE_END() diff --git a/src/test/name_records_tests.cpp b/src/test/name_records_tests.cpp new file mode 100644 index 0000000000..d310942eb6 --- /dev/null +++ b/src/test/name_records_tests.cpp @@ -0,0 +1,47 @@ +// Copyright (c) 2024 Rose Turing +// Distributed under the MIT software license, see the accompanying +// file COPYING or http://www.opensource.org/licenses/mit-license.php. + +#include "../names/records.h" + +#include + +#include + +#include + +BOOST_AUTO_TEST_SUITE(name_records_tests) + +IPv4Record test_ipv4_record; + +BOOST_AUTO_TEST_CASE( ipv4_record_tests ){ + + test_ipv4_record.setDomain("namecoin.bit"); + BOOST_CHECK(test_ipv4_record.getDomain() == "namecoin.bit"); + + test_ipv4_record.setAddress("192.168.1.1"); + BOOST_CHECK(test_ipv4_record.getAddress() == "192.168.1.1"); + + BOOST_CHECK_EQUAL(test_ipv4_record.validate(), true); + + test_ipv4_record.setAddress("1"); + BOOST_CHECK_EQUAL(test_ipv4_record.validate(), false); + +} + +IPv6Record test_ipv6_record; + +BOOST_AUTO_TEST_CASE( ipv6_record_tests ){ + + test_ipv6_record.setAddress("0:0:0:0:0:0:0:1"); + BOOST_CHECK(test_ipv6_record.getAddress() == "0:0:0:0:0:0:0:1"); + + BOOST_CHECK_EQUAL(test_ipv6_record.validate(), true); + + test_ipv6_record.setAddress("1"); + BOOST_CHECK_EQUAL(test_ipv6_record.validate(), false); + +} + +BOOST_AUTO_TEST_SUITE_END() +