Преглед изворни кода

Speed up V1 identity verification a little, and add some comments.

Adam Ierymenko пре 5 година
родитељ
комит
fbfa99fac5
6 измењених фајлова са 145 додато и 88 уклоњено
  1. 5 2
      controller/DB.cpp
  2. 35 26
      node/Identity.cpp
  3. 1 1
      node/Identity.hpp
  4. 1 2
      node/MIMC52.cpp
  5. 3 3
      node/Tests.cpp
  6. 100 54
      node/Utils.hpp

+ 5 - 2
controller/DB.cpp

@@ -338,8 +338,11 @@ void DB::_networkChanged(nlohmann::json &old,nlohmann::json &networkConfig,bool
 
 void DB::_fillSummaryInfo(const std::shared_ptr<_Network> &nw,NetworkSummaryInfo &info)
 {
-	for(auto ab=nw->activeBridgeMembers.begin();ab!=nw->activeBridgeMembers.end();++ab)
-		info.activeBridges.push_back(Address(*ab));
+	for(auto ab=nw->activeBridgeMembers.begin();ab!=nw->activeBridgeMembers.end();++ab) {
+		const Address aba(*ab);
+		if (nw->authorizedMembers.count(aba) != 0)
+			info.activeBridges.push_back(aba);
+	}
 	std::sort(info.activeBridges.begin(),info.activeBridges.end());
 	for(auto ip=nw->allocatedIps.begin();ip!=nw->allocatedIps.end();++ip)
 		info.allocatedIps.push_back(*ip);

+ 35 - 26
node/Identity.cpp

@@ -89,11 +89,13 @@ bool Identity::generate(const Type t)
 
 	switch(t) {
 		case C25519: {
+			// Generate C25519/Ed25519 key pair whose hash satisfies a "hashcash" criterion and generate the
+			// address from the last 40 bits of this hash. This is different from the fingerprint hash for V0.
 			uint8_t digest[64];
 			char *const genmem = new char[ZT_V0_IDENTITY_GEN_MEMORY];
 			do {
 				C25519::generateSatisfying(_v0_identity_generate_cond(digest,genmem),_pub.c25519,_priv.c25519);
-				_address.setTo(digest + 59); // last 5 bytes are address
+				_address.setTo(digest + 59);
 			} while (_address.isReserved());
 			delete[] genmem;
 			_computeHash();
@@ -101,9 +103,15 @@ bool Identity::generate(const Type t)
 
 		case P384: {
 			for(;;) {
+				// Generate C25519, Ed25519, and NIST P-384 key pairs.
 				C25519::generate(_pub.c25519,_priv.c25519);
 				ECC384GenerateKey(_pub.p384,_priv.p384);
+
+				// Execute the MIMC52 verifiable delay function, resulting a near constant time delay relative
+				// to the speed of the current CPU. This result is incorporated into the final hash.
 				Utils::storeBigEndian(_pub.t1mimc52,mimc52Delay(&_pub,sizeof(_pub) - sizeof(_pub.t1mimc52),ZT_V1_IDENTITY_MIMC52_VDF_ROUNDS_BASE));
+
+				// Compute SHA384 fingerprint hash of keys and MIMC output and generate address directly from it.
 				_computeHash();
 				_address.setTo(_fp.data());
 				if (!_address.isReserved())
@@ -118,35 +126,36 @@ bool Identity::generate(const Type t)
 	return true;
 }
 
-bool Identity::locallyValidate() const
+bool Identity::locallyValidate() const noexcept
 {
-	if ((_address.isReserved())||(!_address))
-		return false;
-	switch (_type) {
+	try {
+		if ((!_address.isReserved()) && (_address)) {
+			switch (_type) {
+
+				case C25519: {
+					uint8_t digest[64];
+					char *genmem = new char[ZT_V0_IDENTITY_GEN_MEMORY];
+					_computeMemoryHardHash(_pub.c25519,ZT_C25519_PUBLIC_KEY_LEN,digest,genmem);
+					delete[] genmem;
+					return ((_address == Address(digest + 59)) && (digest[0] < 17));
+				}
 
-		case C25519:
-			try {
-				uint8_t digest[64];
-				char *genmem = new char[ZT_V0_IDENTITY_GEN_MEMORY];
-				_computeMemoryHardHash(_pub.c25519,ZT_C25519_PUBLIC_KEY_LEN,digest,genmem);
-				delete [] genmem;
-				return ((_address == Address(digest + 59))&&(digest[0] < 17));
-			} catch ( ... ) {}
-			break;
+				case P384:
+					if (_address == Address(_fp.data())) {
+						// The most significant 8 bits of the MIMC proof included with v1 identities can be used to store a multiplier
+						// that can indicate that more work than the required minimum has been performed. Right now this is never done
+						// but it could have some use in the future. There is no harm in doing it, and we'll accept any round count
+						// that is at least ZT_V1_IDENTITY_MIMC52_VDF_ROUNDS_BASE.
+						unsigned long rounds = (((unsigned long)_pub.t1mimc52[0] & 15U) + 1U); // max: 16 * ZT_V1_IDENTITY_MIMC52_VDF_ROUNDS_BASE
+						rounds *= ZT_V1_IDENTITY_MIMC52_VDF_ROUNDS_BASE;
+						return mimc52Verify(&_pub,sizeof(_pub) - sizeof(_pub.t1mimc52),rounds,Utils::loadBigEndian<uint64_t>(_pub.t1mimc52));
+					} else {
+						return false;
+					}
 
-		case P384:
-			if (_address == Address(_fp.data())) {
-				// The most significant 8 bits of the MIMC proof included with v1 identities can be used to store a multiplier
-				// that can indicate that more work than the required minimum has been performed. Right now this is never done
-				// but it could have some use in the future. There is no harm in doing it, and we'll accept any round count
-				// that is at least ZT_V1_IDENTITY_MIMC52_VDF_ROUNDS_BASE.
-				const unsigned long rounds = ZT_V1_IDENTITY_MIMC52_VDF_ROUNDS_BASE * ((unsigned long)_pub.t1mimc52[0] + 1U);
-				if (mimc52Verify(&_pub,sizeof(_pub) - sizeof(_pub.t1mimc52),rounds,Utils::loadBigEndian<uint64_t>(_pub.t1mimc52)))
-					return true;
 			}
-			break;
-
-	}
+		}
+	} catch ( ... ) {}
 	return false;
 }
 

+ 1 - 1
node/Identity.hpp

@@ -105,7 +105,7 @@ public:
 	 *
 	 * @return True if validation check passes
 	 */
-	bool locallyValidate() const;
+	bool locallyValidate() const noexcept;
 
 	/**
 	 * @return True if this identity contains a private key

Разлика између датотеке није приказан због своје велике величине
+ 1 - 2
node/MIMC52.cpp


+ 3 - 3
node/Tests.cpp

@@ -180,8 +180,8 @@ static const C25519TestVector C25519_TEST_VECTORS[ZT_NUM_C25519_TEST_VECTORS] =
 #define IDENTITY_V0_KNOWN_GOOD_0 "8e4df28b72:0:ac3d46abe0c21f3cfe7a6c8d6a85cfcffcb82fbd55af6a4d6350657c68200843fa2e16f9418bbd9702cae365f2af5fb4c420908b803a681d4daef6114d78a2d7:bd8dd6e4ce7022d2f812797a80c6ee8ad180dc4ebf301dec8b06d1be08832bddd63a2f1cfa7b2c504474c75bdc8898ba476ef92e8e2d0509f8441985171ff16e"
 #define IDENTITY_V0_KNOWN_BAD_0 "9e4df28b72:0:ac3d46abe0c21f3cfe7a6c8d6a85cfcffcb82fbd55af6a4d6350657c68200843fa2e16f9418bbd9702cae365f2af5fb4c420908b803a681d4daef6114d78a2d7:bd8dd6e4ce7022d2f812797a80c6ee8ad180dc4ebf301dec8b06d1be08832bddd63a2f1cfa7b2c504474c75bdc8898ba476ef92e8e2d0509f8441985171ff16e"
 
-#define IDENTITY_V1_KNOWN_GOOD_0 "237ce8d8e2:1:5w3rj6am3sa7f5vtwm535iswob6ngmkpdidijz5ormqrfwkj55lhwyyszruu4rkbjycmlxzzoiuwtyw5s2mybknqx5j2cwxnaflqbwycoio2hqzcro5afrpcncnxlemzs6bt5linlib5flsej3f3r3bbzclxk733ei7tdrtm5uruiwpmyi4vgaafze42sx6hpe:mwjavgvhxz75ow2fhgq3zu4qfou5kce4wzegpjjd6545fpjnhjxb26e5unuutv7k3c6sm6umpyvatgpufwehi4wqmyudvq724h2klbiem6txs2h5iit5crgg3e6se5xeomuqhircv7zhkylrtnlgh57il742pwkrdgt4lz5fstetmiw7y3rq"
-#define IDENTITY_V1_KNOWN_BAD_0 "238ce8d8e2:1:5w3rj6am3sa7f5vtwm535iswob6ngmkpdidijz5ormqrfwkj55lhwyyszruu4rkbjycmlxzzoiuwtyw5s2mybknqx5j2cwxnaflqbwycoio2hqzcro5afrpcncnxlemzs6bt5linlib5flsej3f3r3bbzclxk733ei7tdrtm5uruiwpmyi4vgaafze42sx6hpe:mwjavgvhxz75ow2fhgq3zu4qfou5kce4wzegpjjd6545fpjnhjxb26e5unuutv7k3c6sm6umpyvatgpufwehi4wqmyudvq724h2klbiem6txs2h5iit5crgg3e6se5xeomuqhircv7zhkylrtnlgh57il742pwkrdgt4lz5fstetmiw7y3rq"
+#define IDENTITY_V1_KNOWN_GOOD_0 "12a4e65422:1:norcnqlkhl2ly6aljrguqntd7bfwdpfpgse32gy2nonhrninfyfxbz4qyj4i7jm2jn6c5hnr6fe3j7a556w5irhtmz77ajdkw6ge2nadlwczld5yak4mhdj46bcwvgzpu3evsfbx44psgughwwgp7rl5ju2gcw4mil5csvd3dp6itwqksyzf6aake3fpn5seo4:ds3mdnqdnbveqlyqq446if3tdilsva4fpsaqahqysavvbv23j655yfahihupezaic56uqrk2dbaamdj2fzmyzulhraux2daj3p6hnxyrhbwugu2ukuqi4eucdck4eczjqcgmv33w65nyxkm3gvhahmoc3zwt2nqmexcdsxlqccexfcpvinuq"
+#define IDENTITY_V1_KNOWN_BAD_0 "22a4e65422:1:norcnqlkhl2ly6aljrguqntd7bfwdpfpgse32gy2nonhrninfyfxbz4qyj4i7jm2jn6c5hnr6fe3j7a556w5irhtmz77ajdkw6ge2nadlwczld5yak4mhdj46bcwvgzpu3evsfbx44psgughwwgp7rl5ju2gcw4mil5csvd3dp6itwqksyzf6aake3fpn5seo4:ds3mdnqdnbveqlyqq446if3tdilsva4fpsaqahqysavvbv23j655yfahihupezaic56uqrk2dbaamdj2fzmyzulhraux2daj3p6hnxyrhbwugu2ukuqi4eucdck4eczjqcgmv33w65nyxkm3gvhahmoc3zwt2nqmexcdsxlqccexfcpvinuq"
 
 // --------------------------------------------------------------------------------------------------------------------
 
@@ -639,7 +639,7 @@ extern "C" const char *ZTT_crypto()
 		{
 			ZT_T_PRINTF("[crypto] Testing MIMC52 VDF... ");
 			const uint64_t proof = mimc52Delay("testing",7,1000);
-			if ((!mimc52Verify("testing",7,1000,proof))||(proof != 0x0007a1a0a1b0fe32)) {
+			if ((!mimc52Verify("testing",7,1000,proof))||(proof != 0x000b501115c73369)) {
 				ZT_T_PRINTF("FAILED (%.16llx)" ZT_EOL_S,proof);
 				return "MIMC52 failed simple delay/verify test";
 			}

+ 100 - 54
node/Utils.hpp

@@ -423,14 +423,14 @@ static ZT_ALWAYS_INLINE uint64_t swapBytes(uint64_t n) noexcept
 #endif
 #else
 	return (
-		((n & 0x00000000000000FFULL) << 56) |
-		((n & 0x000000000000FF00ULL) << 40) |
-		((n & 0x0000000000FF0000ULL) << 24) |
-		((n & 0x00000000FF000000ULL) <<  8) |
-		((n & 0x000000FF00000000ULL) >>  8) |
-		((n & 0x0000FF0000000000ULL) >> 24) |
-		((n & 0x00FF000000000000ULL) >> 40) |
-		((n & 0xFF00000000000000ULL) >> 56)
+		((n & 0x00000000000000ffULL) << 56) |
+		((n & 0x000000000000ff00ULL) << 40) |
+		((n & 0x0000000000ff0000ULL) << 24) |
+		((n & 0x00000000ff000000ULL) <<  8) |
+		((n & 0x000000ff00000000ULL) >>  8) |
+		((n & 0x0000ff0000000000ULL) >> 24) |
+		((n & 0x00ff000000000000ULL) >> 40) |
+		((n & 0xff00000000000000ULL) >> 56)
 	);
 #endif
 }
@@ -446,15 +446,32 @@ template<typename I>
 static ZT_ALWAYS_INLINE I loadBigEndian(const void *const p) noexcept
 {
 #ifdef ZT_NO_UNALIGNED_ACCESS
-	I x = (I)0;
-	for(unsigned int k=0;k<sizeof(I);++k) {
-#if __BYTE_ORDER == __LITTLE_ENDIAN
-		reinterpret_cast<uint8_t *>(&x)[k] = reinterpret_cast<const uint8_t *>(p)[(sizeof(I)-1)-k];
-#else
-		reinterpret_cast<uint8_t *>(&x)[k] = reinterpret_cast<const uint8_t *>(p)[k];
-#endif
+	if (sizeof(I) == 8) {
+		return (I)(
+			((uint64_t)reinterpret_cast<const uint8_t *>(p)[0] << 56U) |
+			((uint64_t)reinterpret_cast<const uint8_t *>(p)[1] << 48U) |
+			((uint64_t)reinterpret_cast<const uint8_t *>(p)[2] << 40U) |
+			((uint64_t)reinterpret_cast<const uint8_t *>(p)[3] << 32U) |
+			((uint64_t)reinterpret_cast<const uint8_t *>(p)[4] << 24U) |
+			((uint64_t)reinterpret_cast<const uint8_t *>(p)[5] << 16U) |
+			((uint64_t)reinterpret_cast<const uint8_t *>(p)[6] << 8U) |
+			(uint64_t)reinterpret_cast<const uint8_t *>(p)[7]
+		);
+	} else if (sizeof(I) == 4) {
+		return (I)(
+			((uint32_t)reinterpret_cast<const uint8_t *>(p)[0] << 24U) |
+			((uint32_t)reinterpret_cast<const uint8_t *>(p)[1] << 16U) |
+			((uint32_t)reinterpret_cast<const uint8_t *>(p)[2] << 8U) |
+			(uint32_t)reinterpret_cast<const uint8_t *>(p)[3]
+		);
+	} else if (sizeof(I) == 2) {
+		return (I)(
+			((unsigned int)reinterpret_cast<const uint8_t *>(p)[0] << 8U) |
+			(unsigned int)reinterpret_cast<const uint8_t *>(p)[1]
+		);
+	} else {
+		return (I)reinterpret_cast<const uint8_t *>(p)[0];
 	}
-	return x;
 #else
 	return ntoh(*reinterpret_cast<const I *>(p));
 #endif
@@ -468,15 +485,28 @@ static ZT_ALWAYS_INLINE I loadBigEndian(const void *const p) noexcept
  * #param i Integer to write
  */
 template<typename I>
-static ZT_ALWAYS_INLINE void storeBigEndian(void *const p,const I i) noexcept
+static ZT_ALWAYS_INLINE void storeBigEndian(void *const p,I i) noexcept
 {
 #ifdef ZT_NO_UNALIGNED_ACCESS
-	for(unsigned int k=0;k<sizeof(I);++k) {
-#if __BYTE_ORDER == __LITTLE_ENDIAN
-		reinterpret_cast<uint8_t *>(p)[k] = reinterpret_cast<const uint8_t *>(&i)[(sizeof(I)-1)-k];
-#else
-		reinterpret_cast<uint8_t *>(p)[k] = reinterpret_cast<const uint8_t *>(&i)[k];
-#endif
+	if (sizeof(I) == 8) {
+		reinterpret_cast<uint8_t *>(p)[0] = (uint8_t)(reinterpret_cast<uint64_t>(i) >> 56U);
+		reinterpret_cast<uint8_t *>(p)[1] = (uint8_t)(reinterpret_cast<uint64_t>(i) >> 48U);
+		reinterpret_cast<uint8_t *>(p)[2] = (uint8_t)(reinterpret_cast<uint64_t>(i) >> 40U);
+		reinterpret_cast<uint8_t *>(p)[3] = (uint8_t)(reinterpret_cast<uint64_t>(i) >> 32U);
+		reinterpret_cast<uint8_t *>(p)[4] = (uint8_t)(reinterpret_cast<uint64_t>(i) >> 24U);
+		reinterpret_cast<uint8_t *>(p)[5] = (uint8_t)(reinterpret_cast<uint64_t>(i) >> 16U);
+		reinterpret_cast<uint8_t *>(p)[6] = (uint8_t)(reinterpret_cast<uint64_t>(i) >> 8U);
+		reinterpret_cast<uint8_t *>(p)[7] = (uint8_t)reinterpret_cast<uint64_t>(i);
+	} else if (sizeof(I) == 4) {
+		reinterpret_cast<uint8_t *>(p)[0] = (uint8_t)(reinterpret_cast<uint32_t>(i) >> 24U);
+		reinterpret_cast<uint8_t *>(p)[1] = (uint8_t)(reinterpret_cast<uint32_t>(i) >> 16U);
+		reinterpret_cast<uint8_t *>(p)[2] = (uint8_t)(reinterpret_cast<uint32_t>(i) >> 8U);
+		reinterpret_cast<uint8_t *>(p)[3] = (uint8_t)reinterpret_cast<uint32_t>(i);
+	} else if (sizeof(I) == 2) {
+		reinterpret_cast<uint8_t *>(p)[0] = (uint8_t)(reinterpret_cast<uint16_t>(i) >> 8U);
+		reinterpret_cast<uint8_t *>(p)[1] = (uint8_t)reinterpret_cast<uint16_t>(i);
+	} else {
+		reinterpret_cast<uint8_t *>(p)[0] = (uint8_t)i;
 	}
 #else
 	*reinterpret_cast<I *>(p) = hton(i);
@@ -486,33 +516,42 @@ static ZT_ALWAYS_INLINE void storeBigEndian(void *const p,const I i) noexcept
 /**
  * Decode a little-endian value from a byte stream
  *
- * @tparam I Type to decode (should be unsigned e.g. uint32_t or uint64_t)
+ * @tparam I Type to decode
  * @param p Byte stream, must be at least sizeof(I) in size
  * @return Decoded integer
  */
 template<typename I>
 static ZT_ALWAYS_INLINE I loadLittleEndian(const void *const p) noexcept
 {
-#ifdef ZT_NO_UNALIGNED_ACCESS
-	I x = (I)0;
-	for(unsigned int k=0;k<sizeof(I);++k) {
-#if __BYTE_ORDER == __LITTLE_ENDIAN
-		reinterpret_cast<uint8_t *>(&x)[k] = reinterpret_cast<const uint8_t *>(p)[k];
-#else
-		reinterpret_cast<uint8_t *>(&x)[k] = reinterpret_cast<const uint8_t *>(p)[(sizeof(I)-1)-k];
-#endif
+#if __BYTE_ORDER == __BIG_ENDIAN || defined(ZT_NO_UNALIGNED_ACCESS)
+	if (sizeof(I) == 8) {
+		return (I)(
+			(uint64_t)reinterpret_cast<const uint8_t *>(p)[0] |
+			((uint64_t)reinterpret_cast<const uint8_t *>(p)[1] << 8U) |
+			((uint64_t)reinterpret_cast<const uint8_t *>(p)[2] << 16U) |
+			((uint64_t)reinterpret_cast<const uint8_t *>(p)[3] << 24U) |
+			((uint64_t)reinterpret_cast<const uint8_t *>(p)[4] << 32U) |
+			((uint64_t)reinterpret_cast<const uint8_t *>(p)[5] << 40U) |
+			((uint64_t)reinterpret_cast<const uint8_t *>(p)[6] << 48U) |
+			((uint64_t)reinterpret_cast<const uint8_t *>(p)[7] << 56U)
+		);
+	} else if (sizeof(I) == 4) {
+		return (I)(
+			(uint32_t)reinterpret_cast<const uint8_t *>(p)[0] |
+			((uint32_t)reinterpret_cast<const uint8_t *>(p)[1] << 8U) |
+			((uint32_t)reinterpret_cast<const uint8_t *>(p)[2] << 16U) |
+			((uint32_t)reinterpret_cast<const uint8_t *>(p)[3] << 24U)
+		);
+	} else if (sizeof(I) == 2) {
+		return (I)(
+			(unsigned int)reinterpret_cast<const uint8_t *>(p)[0] |
+			((unsigned int)reinterpret_cast<const uint8_t *>(p)[1] << 8U)
+		);
+	} else {
+		return (I)reinterpret_cast<const uint8_t *>(p)[0];
 	}
-	return x;
 #else
-#if __BYTE_ORDER == __LITTLE_ENDIAN
 	return *reinterpret_cast<const I *>(p);
-#else
-	I x = (I)0;
-	for(unsigned int k=0;k<sizeof(I);++k) {
-		reinterpret_cast<uint8_t *>(&x)[k] = reinterpret_cast<const uint8_t *>(p)[(sizeof(I)-1)-k];
-	}
-	return x;
-#endif
 #endif
 }
 
@@ -526,22 +565,29 @@ static ZT_ALWAYS_INLINE I loadLittleEndian(const void *const p) noexcept
 template<typename I>
 static ZT_ALWAYS_INLINE void storeLittleEndian(void *const p,const I i) noexcept
 {
-#ifdef ZT_NO_UNALIGNED_ACCESS
-	for(unsigned int k=0;k<sizeof(I);++k) {
-#if __BYTE_ORDER == __LITTLE_ENDIAN
-		reinterpret_cast<uint8_t *>(p)[k] = reinterpret_cast<const uint8_t *>(&i)[k];
-#else
-		reinterpret_cast<uint8_t *>(p)[k] = reinterpret_cast<const uint8_t *>(&i)[(sizeof(I)-1)-k];
-#endif
+#if __BYTE_ORDER == __BIG_ENDIAN || defined(ZT_NO_UNALIGNED_ACCESS)
+	if (sizeof(I) == 8) {
+		reinterpret_cast<uint8_t *>(p)[0] = (uint8_t)reinterpret_cast<uint64_t>(i);
+		reinterpret_cast<uint8_t *>(p)[1] = (uint8_t)(reinterpret_cast<uint64_t>(i) >> 8U);
+		reinterpret_cast<uint8_t *>(p)[2] = (uint8_t)(reinterpret_cast<uint64_t>(i) >> 16U);
+		reinterpret_cast<uint8_t *>(p)[3] = (uint8_t)(reinterpret_cast<uint64_t>(i) >> 24U);
+		reinterpret_cast<uint8_t *>(p)[4] = (uint8_t)(reinterpret_cast<uint64_t>(i) >> 32U);
+		reinterpret_cast<uint8_t *>(p)[5] = (uint8_t)(reinterpret_cast<uint64_t>(i) >> 40U);
+		reinterpret_cast<uint8_t *>(p)[6] = (uint8_t)(reinterpret_cast<uint64_t>(i) >> 48U);
+		reinterpret_cast<uint8_t *>(p)[7] = (uint8_t)(reinterpret_cast<uint64_t>(i) >> 56U);
+	} else if (sizeof(I) == 4) {
+		reinterpret_cast<uint8_t *>(p)[0] = (uint8_t)reinterpret_cast<uint32_t>(i);
+		reinterpret_cast<uint8_t *>(p)[1] = (uint8_t)(reinterpret_cast<uint32_t>(i) >> 8U);
+		reinterpret_cast<uint8_t *>(p)[2] = (uint8_t)(reinterpret_cast<uint32_t>(i) >> 16U);
+		reinterpret_cast<uint8_t *>(p)[3] = (uint8_t)(reinterpret_cast<uint32_t>(i) >> 24U);
+	} else if (sizeof(I) == 2) {
+		reinterpret_cast<uint8_t *>(p)[0] = (uint8_t)reinterpret_cast<uint16_t>(i);
+		reinterpret_cast<uint8_t *>(p)[1] = (uint8_t)(reinterpret_cast<uint16_t>(i) >> 8U);
+	} else {
+		reinterpret_cast<uint8_t *>(p)[0] = (uint8_t)i;
 	}
 #else
-#if __BYTE_ORDER == __LITTLE_ENDIAN
 	*reinterpret_cast<I *>(p) = i;
-#else
-	for(unsigned int k=0;k<sizeof(I);++k) {
-		reinterpret_cast<uint8_t *>(p)[k] = reinterpret_cast<const uint8_t *>(&i)[(sizeof(I)-1)-k];
-	}
-#endif
 #endif
 }
 

Неке датотеке нису приказане због велике количине промена