* Add to_lower_hex_str

* Add to_checksum_address, and is_checksum_address

* Add tests, fix case of Keccak_256
This commit is contained in:
Eddy Ashton 2019-04-18 17:11:46 +01:00 коммит произвёл GitHub
Родитель d39457e705
Коммит 659f23547f
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
7 изменённых файлов: 115 добавлений и 18 удалений

Просмотреть файл

@ -1150,7 +1150,7 @@ namespace evm
prepare_mem_access(offset, size);
uint8_t h[32];
Keccak_256(ctxt->mem.data() + offset, static_cast<unsigned int>(size), h);
keccak_256(ctxt->mem.data() + offset, static_cast<unsigned int>(size), h);
ctxt->s.push(from_big_endian(h, h + sizeof(h)));
}

Просмотреть файл

@ -50,7 +50,7 @@ namespace evm
const auto rlp_encoding = rlp::encode(sender, nonce);
uint8_t buffer[32u];
Keccak_256(
keccak_256(
rlp_encoding.data(),
static_cast<unsigned int>(rlp_encoding.size()),
buffer);

Просмотреть файл

@ -39,6 +39,13 @@ inline auto to_hex_str(const uint256_t& v)
return ss.str();
}
inline auto to_lower_hex_str(const uint256_t& v)
{
auto s = to_hex_str(v);
std::transform(s.begin(), s.end(), s.begin(), ::tolower);
return s;
}
template <typename Iterator>
auto from_big_endian(const Iterator begin, const Iterator end)
{

Просмотреть файл

@ -38,7 +38,7 @@ namespace evm
assign_const(x, std::move(t));
}
inline void Keccak_256(
inline void keccak_256(
const unsigned char* input,
unsigned int inputByteLen,
unsigned char* output)
@ -55,6 +55,21 @@ namespace evm
Keccak_HashFinal(&hi, output);
}
inline std::array<uint8_t, 32u> keccak_256(
const unsigned char* begin, size_t byte_len)
{
std::array<uint8_t, 32u> h;
keccak_256(begin, byte_len, h.data());
return h;
}
inline std::array<uint8_t, 32u> keccak_256(
const std::string& s, size_t skip = 0)
{
skip = std::min(skip, s.size());
return keccak_256((const unsigned char*)s.data() + skip, s.size() - skip);
}
std::string strip(const std::string& s);
std::vector<uint8_t> to_bytes(const std::string& s);
@ -79,6 +94,37 @@ namespace evm
return to_hex_string(bytes.begin(), bytes.end());
}
inline std::string to_checksum_address(const Address& a)
{
auto s = to_lower_hex_str(a);
// Start at index 2 to skip the "0x" prefix
const auto h = keccak_256(s, 2);
std::cout << s << std::endl;
std::cout << to_hex_string(h) << std::endl;
for (size_t i = 0; i < s.size() - 2; ++i)
{
auto& c = s[i + 2];
if (c >= 'a' && c <= 'f')
{
if (h[i / 2] & (i % 2 == 0 ? 0x80 : 0x08))
{
c = std::toupper(c);
}
}
}
return s;
}
inline bool is_checksum_address(const std::string& s)
{
const auto cs = to_checksum_address(from_hex_str(s));
return cs == s;
}
Address generate_address(const Address& sender, uint64_t nonce);
uint64_t to_uint64(const nlohmann::json& j);

Просмотреть файл

@ -48,15 +48,6 @@ evm::Address get_random_address()
}
///////////////////////////////////////////////////////////////////////////////
// Truncate 160-bit addresses to a more human-friendly length, retaining the
// start and end for identification
std::string short_name(const evm::Address& address)
{
const auto full_hex = to_hex_str(address);
return full_hex.substr(0, 5) + std::string("...") +
full_hex.substr(full_hex.size() - 3);
}
// Run input as an EVM transaction, check the result and return the output
std::vector<uint8_t> run_and_check_result(
Environment& env,
@ -189,8 +180,8 @@ bool transfer(
append_argument(function_call, amount);
std::cout << "Transferring " << amount << " from "
<< short_name(source_address) << " to "
<< short_name(target_address);
<< evm::to_checksum_address(source_address) << " to "
<< evm::to_checksum_address(target_address);
const auto output =
run_and_check_result(env, source_address, contract_address, function_call);
@ -258,7 +249,7 @@ void print_erc20_state(
std::cout << "User balances: " << std::endl;
for (const auto& pair : balances)
{
std::cout << " " << pair.second << " owned by " << short_name(pair.first);
std::cout << " " << pair.second << " owned by " << evm::to_checksum_address(pair.first);
if (pair.first == env.owner_address)
{
std::cout << " (original contract creator)";

Просмотреть файл

@ -155,11 +155,11 @@ int main(int argc, char** argv)
const uint256_t result = from_big_endian(e.output.begin(), e.output.end());
std::cout << to_hex_str(arg_a);
std::cout << to_lower_hex_str(arg_a);
std::cout << " + ";
std::cout << to_hex_str(arg_b);
std::cout << to_lower_hex_str(arg_b);
std::cout << " = ";
std::cout << to_hex_str(result);
std::cout << to_lower_hex_str(result);
std::cout << std::endl;
if (verbose)

Просмотреть файл

@ -29,6 +29,59 @@ TEST_CASE("util" * doctest::test_suite("util"))
REQUIRE(to_bytes("0xabc") == vector<uint8_t>{0xa, 0xbc});
REQUIRE(to_bytes("0xabcd") == vector<uint8_t>{0xab, 0xcd});
}
SUBCASE("keccak_256")
{
const std::string empty;
REQUIRE(
to_hex_string(keccak_256(empty)) ==
"0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470");
REQUIRE(
to_hex_string(keccak_256(empty, 5)) ==
"0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470");
const std::string s = "Hello world";
REQUIRE(
to_hex_string(keccak_256(s)) ==
"0xed6c11b0b5b808960df26f5bfc471d04c1995b0ffd2055925ad1be28d6baadfd");
REQUIRE(
to_hex_string(keccak_256(s, 1)) ==
"0x06f5a9ffe20e0fda47399119d5f89e6ea5aa7442fdbc973c365ef4ad993cde12");
REQUIRE(
to_hex_string(keccak_256(s, 6)) ==
"0x8452c9b9140222b08593a26daa782707297be9f7b3e8281d7b4974769f19afd0");
}
SUBCASE("to_checksum_address")
{
const Address t0 =
from_hex_str("0x5aaeb6053f3e94c9b9a09f33669435e7ef1beaed");
REQUIRE(
to_checksum_address(t0) == "0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed");
const Address t1 =
from_hex_str("0xfb6916095ca1df60bb79ce92ce3ea74c37c5d359");
REQUIRE(
to_checksum_address(t1) == "0xfB6916095ca1df60bB79Ce92cE3Ea74c37c5d359");
const Address t2 =
from_hex_str("0xDBF03B407C01E7CD3CBEA99509D93F8DDDC8C6FB");
REQUIRE(
to_checksum_address(t2) == "0xdbF03B407c01E7cD3CBea99509d93f8DDDC8C6FB");
const Address t3 =
from_hex_str("0xD1220A0cf47c7B9Be7A2E6BA89F429762e7b9aDb");
REQUIRE(
to_checksum_address(t3) == "0xD1220A0cf47c7B9Be7A2E6BA89F429762e7b9aDb");
REQUIRE(is_checksum_address("0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed"));
REQUIRE(is_checksum_address("0xfB6916095ca1df60bB79Ce92cE3Ea74c37c5d359"));
REQUIRE(is_checksum_address("0xdbF03B407c01E7cD3CBea99509d93f8DDDC8C6FB"));
REQUIRE(is_checksum_address("0xD1220A0cf47c7B9Be7A2E6BA89F429762e7b9aDb"));
}
}
TEST_CASE("byteExport" * doctest::test_suite("primitive"))