From 4153e662b60a0d83c1be15150f18483a37e9092c Mon Sep 17 00:00:00 2001 From: Ilan Date: Tue, 19 Jun 2018 14:52:39 -0300 Subject: [PATCH] Implement RSKIP-60 checksum address encoding --- address.c | 18 ++++++++++++++++-- address.h | 2 +- tests/test_check.c | 44 +++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 60 insertions(+), 4 deletions(-) diff --git a/address.c b/address.c index 4d63f8ee3a..3fa9f8927a 100644 --- a/address.c +++ b/address.c @@ -22,6 +22,9 @@ */ #include "address.h" +#include +#include +#include "bignum.h" size_t address_prefix_bytes_len(uint32_t address_type) { @@ -56,7 +59,7 @@ bool address_check_prefix(const uint8_t *addr, uint32_t address_type) #if USE_ETHEREUM #include "sha3.h" -void ethereum_address_checksum(const uint8_t *addr, char *address) +void ethereum_address_checksum(const uint8_t *addr, char *address, bool rskip60, uint8_t chain_id) { const char *hex = "0123456789abcdef"; for (int i = 0; i < 20; i++) { @@ -64,8 +67,19 @@ void ethereum_address_checksum(const uint8_t *addr, char *address) address[i * 2 + 1] = hex[addr[i] & 0xF]; } address[40] = 0; + + SHA3_CTX ctx; uint8_t hash[32]; - keccak_256((const uint8_t *)address, 40, hash); + keccak_256_Init(&ctx); + if(rskip60) + { + char prefix[16]; + int prefix_size = bn_format_uint64(chain_id, NULL, "0x", 0, 0, false, prefix, sizeof(prefix)); + keccak_Update(&ctx, (const uint8_t *)prefix, prefix_size); + } + keccak_Update(&ctx, (const uint8_t *)address, 40); + keccak_Final(&ctx, hash); + for (int i = 0; i < 20; i++) { if (hash[i] & 0x80 && address[i * 2 ] >= 'a' && address[i * 2 ] <= 'f') { address[i * 2] -= 0x20; diff --git a/address.h b/address.h index 307cf8dc8a..c70a1f28a3 100644 --- a/address.h +++ b/address.h @@ -33,7 +33,7 @@ size_t address_prefix_bytes_len(uint32_t address_type); void address_write_prefix_bytes(uint32_t address_type, uint8_t *out); bool address_check_prefix(const uint8_t *addr, uint32_t address_type); #if USE_ETHEREUM -void ethereum_address_checksum(const uint8_t *addr, char *address); +void ethereum_address_checksum(const uint8_t *addr, char *address, bool rskip60, uint8_t chain_id); #endif #endif diff --git a/tests/test_check.c b/tests/test_check.c index 388aec3379..7af2136f17 100644 --- a/tests/test_check.c +++ b/tests/test_check.c @@ -3802,7 +3802,45 @@ START_TEST(test_ethereum_address) const char **vec = vectors; while (*vec) { memcpy(addr, fromhex(*vec), 20); - ethereum_address_checksum(addr, address); + ethereum_address_checksum(addr, address, false, 1); + ck_assert_str_eq(address, *vec); + vec++; + } +} +END_TEST + +// test vectors from https://github.com/rsksmart/RSKIPs/blob/master/IPs/RSKIP60.md +START_TEST(test_rsk_address) +{ + uint8_t addr[20]; + char address[41]; + + static const char *rskip60_chain30[] = { + "5aaEB6053f3e94c9b9a09f33669435E7ef1bEAeD", + "Fb6916095cA1Df60bb79ce92cE3EA74c37c5d359", + "DBF03B407c01E7CD3cBea99509D93F8Dddc8C6FB", + "D1220A0Cf47c7B9BE7a2e6ba89F429762E7B9adB", + 0 + }; + const char **vec = rskip60_chain30; + while (*vec) { + memcpy(addr, fromhex(*vec), 20); + ethereum_address_checksum(addr, address, true, 30); + ck_assert_str_eq(address, *vec); + vec++; + } + + static const char *rskip60_chain31[] = { + "5aAeb6053F3e94c9b9A09F33669435E7EF1BEaEd", + "Fb6916095CA1dF60bb79CE92ce3Ea74C37c5D359", + "dbF03B407C01E7cd3cbEa99509D93f8dDDc8C6fB", + "d1220a0CF47c7B9Be7A2E6Ba89f429762E7b9adB", + 0 + }; + vec = rskip60_chain31; + while (*vec) { + memcpy(addr, fromhex(*vec), 20); + ethereum_address_checksum(addr, address, true, 31); ck_assert_str_eq(address, *vec); vec++; } @@ -4744,6 +4782,10 @@ Suite *test_suite(void) tcase_add_test(tc, test_ethereum_address); suite_add_tcase(s, tc); + tc = tcase_create("rsk_address"); + tcase_add_test(tc, test_rsk_address); + suite_add_tcase(s, tc); + tc = tcase_create("wif"); tcase_add_test(tc, test_wif); suite_add_tcase(s, tc);