Как я могу проверить, действителен ли адрес Ethereum?

Я много раз читал, что вы никогда не должны вводить адрес вручную, если только вы не хотите случайно отправить эфир в ничейную зону. Я хотел бы знать, что это могут быть за контрольные суммы. Есть ли способ сказать, что произошла опечатка? как и какие правила форматирования к нему? Я спрашиваю, чтобы я мог потенциально создать функцию-оболочку, которая проверяет эти вещи перед отправкой в ​​​​сеть.

Связанная среда.com/@piyopiyo/…

Ответы (9)

Использование библиотеки

Такие библиотеки, как web3.js и эфиры , имеют файлы isAddress().

Примеры:

  • ethers.utils.isAddress('0x8ba1f109551bd432803012645ac136ddd64dba72');// истинный

  • web3.utils.isAddress('blah');// ЛОЖЬ

Ниже приведен ответ от 2016 года.

Обычный адрес

В EIP 55 добавлена ​​«контрольная сумма на основе заглавных букв», которая была реализована Geth к маю 2016 года. Вот код Javascript от Geth:

/**
 * Checks if the given string is an address
 *
 * @method isAddress
 * @param {String} address the given HEX adress
 * @return {Boolean}
*/
var isAddress = function (address) {
    if (!/^(0x)?[0-9a-f]{40}$/i.test(address)) {
        // check if it has the basic requirements of an address
        return false;
    } else if (/^(0x)?[0-9a-f]{40}$/.test(address) || /^(0x)?[0-9A-F]{40}$/.test(address)) {
        // If it's all small caps or all all caps, return true
        return true;
    } else {
        // Otherwise check each case
        return isChecksumAddress(address);
    }
};

/**
 * Checks if the given string is a checksummed address
 *
 * @method isChecksumAddress
 * @param {String} address the given HEX adress
 * @return {Boolean}
*/
var isChecksumAddress = function (address) {
    // Check each case
    address = address.replace('0x','');
    var addressHash = sha3(address.toLowerCase());
    for (var i = 0; i < 40; i++ ) {
        // the nth letter should be uppercase if the nth digit of casemap is 1
        if ((parseInt(addressHash[i], 16) > 7 && address[i].toUpperCase() !== address[i]) || (parseInt(addressHash[i], 16) <= 7 && address[i].toLowerCase() !== address[i])) {
            return false;
        }
    }
    return true;
};

ICAP-адрес

ICAP имеет контрольную сумму, которую можно проверить. Вы можете просмотреть icap.go Geth и вот фрагмент из него:

// https://en.wikipedia.org/wiki/International_Bank_Account_Number#Validating_the_IBAN
func validCheckSum(s string) error {
    s = join(s[4:], s[:4])
    expanded, err := iso13616Expand(s)
    if err != nil {
        return err
    }
    checkSumNum, _ := new(big.Int).SetString(expanded, 10)
    if checkSumNum.Mod(checkSumNum, Big97).Cmp(Big1) != 0 {
        return ICAPChecksumError
    }
    return nil
}
Отличный ответ! Из любопытства, есть идеи, насколько хороша контрольная сумма? то есть с несколькими неправильными цифрами, каковы шансы, что он все равно случайно пройдет контрольную сумму?
EIP 55 сравнивает обычную контрольную сумму адреса с ICAP: «В среднем будет 15 контрольных битов на адрес, и чистая вероятность того, что случайно сгенерированный адрес, если он будет введен с ошибкой, случайно пройдет проверку, составляет 0,0247%. Это улучшение в ~ 50 раз по сравнению с ICAP. , но не так хорошо, как 4-байтовый контрольный код».
Было бы неплохо иметь возможность проверить валидность и в Solidity. Один из способов сделать это — перевести небольшое количество эфира на любой новый адрес, который вы создадите, и проверить ненулевой баланс в Solidity. (Это должен быть отдельный вопрос?)
@eth При использовании обычной адресной функции я получаю сообщение ReferenceError: sha3 is not definedоб ошибке, есть идеи, почему?
@PedroLobito Для sha3 вы можете использовать keccak256библиотеку, например github.com/emn178/js-sha3 . Мне не удалось найти последний код, который Geth использует для улучшения этого ответа.
Я сделаю это, ткс!
sha3функция не определена. Используется в функции checkSumAddress в ответе.var addressHash = sha3(address.toLowerCase());
@DenisMatafonov Вы спрашиваете то же, что и Пабло... ethereum.stackexchange.com/questions/1374/…
@eth это был не вопрос, это было замечание о том, что код, указанный в ответе, недействителен. И хуже всего то, что он работает большую часть времени, за исключением случаев, когда адрес не попадает в первый, второй ifи else if. Ссылка на sha3 lib должна быть включена в ответ.
@eth Я пытаюсь использовать эту библиотеку github.com/Caligatio/jsSHA для sha3, но похоже, что она не работает с вашим кодом. Не могли бы вы помочь мне с этим?
Это также работает для адреса смарт-контракта? @эт
@Alper Да, адрес смарт-контракта может быть написан с заглавной буквы в соответствии с EIP 55, например .
плохой ответ, этот код не проходит проверку даже действительных адресов! следующий ответ с web3.utils.isAddress намного лучше и проще
@OleksandrGrin Спасибо за ваш комментарий. Я бы также использовал библиотеку; Я изменил этот ответ, чтобы показать 2 примера.

Теперь есть более простой способ web3:

Наивный:
https://web3js.readthedocs.io/en/v1.2.0/web3-utils.html#isaddress

web3.utils.isAddress('0xc1912fee45d61c87cc5ea59dae31190fffff232d');
> true

ИЛИ
Лучшая версия
https://web3js.readthedocs.io/en/v1.2.0/web3-utils.html#tochecksumaddress

try {
  const address = web3.utils.toChecksumAddress(rawInput)
} catch(e) { 
  console.error('invalid ethereum address', e.message) 
}

использование метода checkSum лучше, потому что вы всегда будете иметь дело с данными и никогда не будете использовать нижний регистр.

Метод isaddress() также проверяет контрольную сумму! зачем нам нужен метод checkSum?
isAddress: Checks if a given string is a valid Ethereum address. It will also check the checksum, if the address has upper and lowercase letters.Как заявил @atul

Стандартные 40-символьные шестнадцатеричные адреса теперь имеют контрольную сумму в виде заглавных букв. Если в адресе есть хотя бы одна заглавная буква, то он суммируется и, если он введен на сайте, который проверяет сумму, он вернет false, если это недействительный адрес.

Схема выглядит следующим образом:

преобразовать адрес в шестнадцатеричный, но если i-я цифра является буквой (т. е. это одна из abcdef), напечатайте ее в верхнем регистре, если i-й бит хеша адреса (в двоичной форме) равен 1, в противном случае напечатайте его в нижнем регистре

Вы можете прочитать полную рецензию VB здесь: https://github.com/ethereum/EIPs/issues/55

function validateInputAddresses(address) {
        return (/^(0x){1}[0-9a-fA-F]{40}$/i.test(address));
}
Это просто проверка правдоподобия, не проверяет контрольную сумму. По-прежнему кажется, что это лучший способ написать регулярное выражение проверки правдоподобия.

В пакете python ethereum есть функция check_checksum в модуле utils:

from ethereum.utils import check_checksum
check_checksum('0xc1912fee45d61c87cc5ea59dae31190fffff232d')
> True

Для этого я создаю небольшой проект, который программно использую в своих приложениях. Он имеет «микро» API:

https://balidator.io/api/ethereum/0xea0258D0E745620e77B0A389e3A656EFdb7Cf821

Он также имеет проверку адреса для биткойнов, монеро и пульсации.

Вы можете найти документацию здесь: balidator.io/api-documentation

В библиотеке python Web3 также есть методы проверки адресов. web3py.readthedocs.io/en/latest/…
balidator.io не найден

Пока эфирные адреса не имеют контрольной суммы и представляют собой просто HEX-кодирование байтов адреса. Однако есть предложение по кодированию и контрольной сумме, см.: ICAP: Inter exchange Client Address Protocol .

ICAP имеет предварительную поддержку, объединенную в некоторых клиентах Ethereum.

Контрольные суммы — это механизмы, предотвращающие отправку средств на неправильные адреса (установленные по ошибке или злоумышленником).

Программно

Вы можете использовать web3удивительные утилиты:

web3.utils.toChecksumAddress(значение)

Функция выше работает, только если у вас есть версия 1.0.0или выше.

Интернет

Я создал онлайн-инструмент, посмотрите его здесь: EthSum .

Еще один способ проверить, есть ли у вас открытый ключ адреса эфириума. Можно использовать официальную eth-keysбиблиотеку Python от Ethereum Foundation, которая теперь является частью их репозитория Github, ее можно увидеть здесь и содержит набор инструментов, которые включают способы проверки правильности адреса, например, с помощью PublicKey().checksum_address()метода (см. пример ниже).

Для следующего метода требуется несжатый открытый ключ в формате байтов, что означает, что он должен быть только для учетных записей, для которых у вас есть данные открытого ключа:

 >>>from eth_keys import keys
 
 >>>keys.PublicKey(b'\x98\xbb\xfa\xdd\xbc\xc7\xab\x14\xa3\x9c\xb4\x84\xbf\x94MO\xf5\x91^G\xc1\xc2\x0b\xe77t\xc3\xd0\x05\x12|Z\xf5\x17PZ\x97\xe2\\`IR\xc1\xbd\x10\xa3\xa3\xdf\xbf0\xaf;7\xc0z\xbc\xc7\x0b\x9c\xbd<FY\x98').to_checksum_address()
        
        '0x28f4961F8b06F7361A1efD5E700DE717b1db5292'
Это должно быть from eth_keys import keys. Я бы отредактировал, но правки должны быть не менее шести символов.
@JoshDavis, ты абсолютно прав! Спасибо за замечание, я только что исправил.

Или в Python (с Web3py )

from web3 import Web3

print(Web3.isAddress("0xBB9923E927F0bC33C901396F4C589B43DB991705"))