зеркало из https://github.com/microsoft/eEVM.git
Checksum addresses (#30)
* 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:
Родитель
d39457e705
Коммит
659f23547f
|
@ -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"))
|
||||
|
|
Загрузка…
Ссылка в новой задаче