如何通过PHP/Laravel验证以太坊地址?

4
我该如何检查Laravel输入的以太坊地址格式是否有效?
3个回答

3
这是一个 Laravel 自定义验证规则,用于根据EIP 55规范验证以太坊地址。有关其工作原理的详细信息,请阅读注释。
<?php

namespace App\Rules;

use kornrunner\Keccak; // composer require greensea/keccak
use Illuminate\Contracts\Validation\Rule;

class ValidEthereumAddress implements Rule
{
    /**
     * @var Keccak
     */
    protected $hasher;

    public function __construct(Keccak $hasher)
    {
        $this->keccak = $hasher;
    }

    public function passes($attribute, $value)
    {
        // See: https://github.com/ethereum/web3.js/blob/7935e5f/lib/utils/utils.js#L415
        if ($this->matchesPattern($value)) {
            return $this->isAllSameCaps($value) ?: $this->isValidChecksum($value);
        }

        return false;
    }

    public function message()
    {
        return 'The :attribute must be a valid Ethereum address.';
    }

    protected function matchesPattern(string $address): int
    {
        return preg_match('/^(0x)?[0-9a-f]{40}$/i', $address);
    }

    protected function isAllSameCaps(string $address): bool
    {
        return preg_match('/^(0x)?[0-9a-f]{40}$/', $address) || preg_match('/^(0x)?[0-9A-F]{40}$/', $address);
    }

    protected function isValidChecksum($address)
    {
        $address = str_replace('0x', '', $address);
        $hash = $this->keccak->hash(strtolower($address), 256);

        // See: https://github.com/web3j/web3j/pull/134/files#diff-db8702981afff54d3de6a913f13b7be4R42
        for ($i = 0; $i < 40; $i++ ) {
            if (ctype_alpha($address{$i})) {
                // Each uppercase letter should correlate with a first bit of 1 in the hash char with the same index,
                // and each lowercase letter with a 0 bit.
                $charInt = intval($hash{$i}, 16);

                if ((ctype_upper($address{$i}) && $charInt <= 7) || (ctype_lower($address{$i}) && $charInt > 7)) {
                    return false;
                }
            }
        }

        return true;
    }
}

依赖项

为了验证校验和地址,我们需要一个Keccac实现,而内置的hash()函数不支持该实现。您需要引入这个纯PHP实现以使上述规则生效。


它没有正常工作。如果您检查此有效地址,则仍将显示无效,即0x7614e80bE7E0C1e5aFce4E8e35627dEEc461d2bD - Dhaval Bharadva
这里的哈希算法出了问题。以太坊使用一种名为Keccak的具有不同填充常数的SHA3变体。我已更新答案。感谢@WebSpanner指出。 - sepehr
@DhavalBharadva,你确定这是有效的以太坊地址吗? - Syamsoul Azrien

0

任何以0x开头,后跟0-9、A-F、a-f(有效的十六进制字符)的42个字符字符串都代表一个有效的以太坊地址。

您可以在这里找到有关小写和部分大写(用于添加校验和)以太坊地址格式的更多信息。


谢谢回复,我正在使用go-ethereum JSON RPC API概念,但没有任何函数来验证地址。 - Hitesh Patel
是的,它比需要一个新的api调用更简单。你只需要一行代码就可以做到。例如使用Python的re模块: True if re.match("^(0x)?[0-9a-f]{40}$", address) else False - I. Helmot

0

从 Laravel 9 开始,如果您正在使用请求类进行验证,请将此内容添加到验证规则中:

/**
 * Get the validation rules that apply to the request.
 * 
 * @return array
 */
public function rules()
{
    return [
        'address' => 'regex:/^(0x)?(?i:[0-9a-f]){40}$/'
    ];
}

注释:

  • 这里,输入字段名称为address
  • 我使用格式(?i: ... )对正则表达式的部分内容进行了大小写不敏感处理

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接