-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added eth address class and conversion from eckey to addr
- Loading branch information
1 parent
d4b0c56
commit c9a566e
Showing
5 changed files
with
352 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,134 @@ | ||
// Copyright (c) 2024 Haofan Zheng | ||
// Use of this source code is governed by an MIT-style | ||
// license that can be found in the LICENSE file or at | ||
// https://opensource.org/licenses/MIT. | ||
|
||
#pragma once | ||
|
||
|
||
#include <string> | ||
|
||
#include <SimpleObjects/Codec/Hex.hpp> | ||
|
||
#include "../Exceptions.hpp" | ||
#include "../Internal/SimpleObj.hpp" | ||
#include "DataTypes.hpp" | ||
#include "Keccak256.hpp" | ||
|
||
|
||
namespace EclipseMonitor | ||
{ | ||
namespace Eth | ||
{ | ||
|
||
|
||
class Address | ||
{ | ||
public: // static members: | ||
|
||
using value_type = ContractAddr; | ||
|
||
static constexpr size_t sk_sizeBytes = 20; | ||
|
||
public: | ||
|
||
Address(const value_type& addr) : | ||
m_addr(addr) | ||
{} | ||
|
||
explicit Address(const std::string& addr) : | ||
m_addr() | ||
{ | ||
size_t expLen = sk_sizeBytes * 2; | ||
auto begin = addr.begin(); | ||
|
||
// check if the string begins with "0x" | ||
if ( | ||
(addr.size() >= 2) && // at least 2 characters | ||
((addr[0] == '0') && (addr[1] == 'x')) // starts with "0x" | ||
) | ||
{ | ||
begin += 2; | ||
expLen += 2; | ||
} | ||
|
||
// check if the string is of the correct length | ||
if (addr.size() != expLen) | ||
{ | ||
throw Exception( | ||
"The given ETH address hex string is of incorrect length" | ||
); | ||
} | ||
|
||
Internal::Obj::Codec::Hex::Decode(m_addr.begin(), begin, addr.end()); | ||
} | ||
|
||
Address(const Address& addr) : | ||
m_addr(addr.m_addr) | ||
{} | ||
|
||
Address(Address&& addr) : | ||
m_addr(std::move(addr.m_addr)) | ||
{} | ||
|
||
~Address() = default; | ||
|
||
bool operator==(const Address& addr) const | ||
{ | ||
return m_addr == addr.m_addr; | ||
} | ||
|
||
bool operator!=(const Address& addr) const | ||
{ | ||
return m_addr != addr.m_addr; | ||
} | ||
|
||
std::string ToString(const std::string& prefix = "0x") const | ||
{ | ||
// std::array<uint8_t, 20> should generate a hex string of length 40 | ||
std::string hexLower = | ||
Internal::Obj::Codec::Hex::Encode<std::string>(m_addr, ""); | ||
// std::array<uint8_t, 20> should generate a hex string of length 40 | ||
std::string hexUpper = | ||
Internal::Obj::Codec::HEX::Encode<std::string>(m_addr, ""); | ||
|
||
// the checksummed address that is going to be generated | ||
std::string checksummed = prefix; | ||
|
||
// The result of a 256-bit hash should have 32 bytes | ||
auto addrHash = Keccak256(hexLower); | ||
|
||
for (size_t i = 0; i < hexLower.size(); ++i) | ||
{ | ||
// if `i` is even, the nibble is the higher 4-bit of the byte | ||
// e.g., (0 % 2) = 0, (2 % 2) = 0, (4 % 2) = 0, ... | ||
// 1 - (i % 2) = 1 - 0 = 1 | ||
// (1 - (i % 2)) * 4 = 1 * 4 = 4 | ||
// if `i` is odd, the nibble is the lower 4-bit of the byte | ||
// e.g., (1 % 2) = 1, (3 % 2) = 1, (5 % 2) = 1, ... | ||
// 1 - (i % 2) = 1 - 1 = 0 | ||
// (1 - (i % 2)) * 4 = 0 * 4 = 0 | ||
uint8_t rightShift = (1 - (i % 2)) * 4; | ||
uint8_t hashByte = addrHash[i / 2]; | ||
uint8_t hashNibble = (hashByte >> rightShift) & 0x0FU; | ||
|
||
// if the nibble is greater than 7, the hex should be upper case | ||
// otherwise, the hex should be lower case | ||
char hexCh = hashNibble > 7 ? hexUpper[i] : hexLower[i]; | ||
|
||
checksummed.push_back(hexCh); | ||
} | ||
|
||
return checksummed; | ||
} | ||
|
||
|
||
private: // members: | ||
|
||
value_type m_addr; | ||
}; // class Address | ||
|
||
|
||
} // namespace Eth | ||
} // namespace EclipseMonitor | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
// Copyright (c) 2024 Haofan Zheng | ||
// Use of this source code is governed by an MIT-style | ||
// license that can be found in the LICENSE file or at | ||
// https://opensource.org/licenses/MIT. | ||
|
||
|
||
#include <gtest/gtest.h> | ||
|
||
#include <EclipseMonitor/Eth/Address.hpp> | ||
|
||
#include "Common.hpp" | ||
|
||
|
||
namespace EclipseMonitor_Test | ||
{ | ||
extern size_t g_numOfTestFile; | ||
} | ||
|
||
using namespace EclipseMonitor_Test; | ||
using namespace EclipseMonitor::Eth; | ||
|
||
|
||
GTEST_TEST(TestEthAddress, CountTestFile) | ||
{ | ||
static auto tmp = ++EclipseMonitor_Test::g_numOfTestFile; | ||
(void)tmp; | ||
} | ||
|
||
|
||
/** | ||
* @brief | ||
* | ||
* @param addrHexStr this string should avoid the prefix "0x" | ||
* @param prefix | ||
*/ | ||
static void TestAddressParseAndString( | ||
const std::string& addrHexStr, | ||
const std::string& prefix = "0x" | ||
) | ||
{ | ||
// parse without the prefix | ||
Address addr(addrHexStr); | ||
auto generatedStr = addr.ToString(""); | ||
EXPECT_EQ(generatedStr, addrHexStr); | ||
|
||
// parse again with the prefix | ||
Address addr2(generatedStr); | ||
auto generatedStr2 = addr2.ToString(prefix); | ||
EXPECT_EQ(generatedStr2, prefix + addrHexStr); | ||
|
||
// two `Address` instances should be equal | ||
EXPECT_EQ(addr, addr2); | ||
EXPECT_FALSE(addr != addr2); | ||
|
||
// test the copy constructor | ||
Address copied(addr); | ||
EXPECT_EQ(copied, addr); | ||
|
||
// test the move constructor | ||
Address moved(std::move(copied)); | ||
EXPECT_EQ(moved, addr); | ||
} | ||
|
||
|
||
GTEST_TEST(TestEthAddress, ParseAndString) | ||
{ | ||
TestAddressParseAndString("010EEE07C4020148D96F80CEd0EE4D129a267D20"); | ||
TestAddressParseAndString("453272C49Dd5b2343Fef13EAdb746E083fB36411"); | ||
TestAddressParseAndString("653E2Bb1258edA29c2F348e88de7F936af8E32C3"); | ||
TestAddressParseAndString("359E745B64498408F11e2811c7376c745084C80f"); | ||
TestAddressParseAndString("9Baa87097A3C3Ff7Fb6428baa2930a031A1Ea4dF"); | ||
TestAddressParseAndString("Dbc12BE0FB8059040b275fe35D6C0c44e420436E"); | ||
TestAddressParseAndString("2bE4803127CD97Abb65F1bE319fA18b6A5567C77"); | ||
TestAddressParseAndString("B39c2ecB0BC4Fa3e75e4Adcb3A59B8cb46AEc16c"); | ||
TestAddressParseAndString("7Bc655F54f53c5ae0aac55d19CCe245368f518AB"); | ||
TestAddressParseAndString("786d53fCc2ac73F3ac8aC21a1E03c0c1bDC70Ad3"); | ||
|
||
// string with incorrect length | ||
EXPECT_THROW_MSG( | ||
TestAddressParseAndString(""), | ||
EclipseMonitor::Exception, | ||
"The given ETH address hex string is of incorrect length" | ||
); | ||
EXPECT_THROW_MSG( | ||
TestAddressParseAndString("0"), | ||
EclipseMonitor::Exception, | ||
"The given ETH address hex string is of incorrect length" | ||
); | ||
EXPECT_THROW_MSG( | ||
TestAddressParseAndString("0x"), | ||
EclipseMonitor::Exception, | ||
"The given ETH address hex string is of incorrect length" | ||
); | ||
EXPECT_THROW_MSG( | ||
TestAddressParseAndString("786d53fCc2"), | ||
EclipseMonitor::Exception, | ||
"The given ETH address hex string is of incorrect length" | ||
); | ||
EXPECT_THROW_MSG( | ||
TestAddressParseAndString("786d53fCc2ac73F3ac8aC21a1E03c0c1bDC70Ad3786d53fCc2"), | ||
EclipseMonitor::Exception, | ||
"The given ETH address hex string is of incorrect length" | ||
); | ||
|
||
// string containing invalid characters | ||
EXPECT_THROW_MSG( | ||
TestAddressParseAndString("786d53fCc2ac73F3ac8HC21a1E03c0c1bDC70Ad3"), | ||
std::invalid_argument, | ||
"Invalid hex character" | ||
); | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters