|
1 | | -https://hackmd.io/@046EkvuRTzieElv1kovjww/r1b1kD3Gge# |
| 1 | +# ED25519 Signature Verification Precompile |
| 2 | + |
| 3 | +## Overview |
| 4 | + |
| 5 | +The ED25519 precompile provides native support for verifying ED25519 digital signatures within the EVM. This precompile enables efficient cryptographic signature verification using the ED25519 elliptic curve, which is widely used in blockchain and cryptographic applications. |
| 6 | + |
| 7 | +## Contract Address |
| 8 | + |
| 9 | +The ED25519 precompile is deployed at a fixed address: |
| 10 | + |
| 11 | +``` |
| 12 | +0x00000000000000000000000000000000000008f3 |
| 13 | +``` |
| 14 | + |
| 15 | +## Interface |
| 16 | + |
| 17 | +### Methods |
| 18 | + |
| 19 | +#### `ed25519Verify` |
| 20 | + |
| 21 | +Verifies an ED25519 signature against a public key and message. |
| 22 | + |
| 23 | +```solidity |
| 24 | +function ed25519Verify( |
| 25 | + bytes32 publicKey, |
| 26 | + bytes32[2] signature, |
| 27 | + bytes message |
| 28 | +) returns (bool isValid) |
| 29 | +``` |
| 30 | + |
| 31 | +**Parameters:** |
| 32 | +- `publicKey` (bytes32): The ED25519 public key (32 bytes) |
| 33 | +- `signature` (bytes32[2]): The ED25519 signature split into two 32-byte parts: |
| 34 | + - `signature[0]`: R component (first 32 bytes) |
| 35 | + - `signature[1]`: S component (last 32 bytes) |
| 36 | +- `message` (bytes): The message that was signed (variable length) |
| 37 | + |
| 38 | +**Returns:** |
| 39 | +- `isValid` (bool): `true` if the signature is valid, `false` otherwise |
| 40 | + |
| 41 | +## Gas Costs |
| 42 | + |
| 43 | +The gas cost for the `ed25519Verify` function is calculated dynamically based on the message length: |
| 44 | + |
| 45 | +``` |
| 46 | +gas = ED25519_VERIFY_BASE_GAS + SHA512_BASE_GAS + SHA512_PER_WORD_GAS * ((msgLen + 31) / 32) |
| 47 | +``` |
| 48 | + |
| 49 | +Where: |
| 50 | +- `ED25519_VERIFY_BASE_GAS = 2000`: Base cost for ED25519 signature verification |
| 51 | +- `SHA512_BASE_GAS = 60`: Base cost for SHA512 hashing |
| 52 | +- `SHA512_PER_WORD_GAS = 12`: Cost per 32-byte word for SHA512 hashing |
| 53 | +- `msgLen`: Length of the message (excluding the 36 bytes for method selector and signature.S) |
| 54 | + |
| 55 | + |
| 56 | +## Usage Example |
| 57 | + |
| 58 | +### Solidity |
| 59 | + |
| 60 | +```solidity |
| 61 | +// SPDX-License-Identifier: MIT |
| 62 | +pragma solidity ^0.8.0; |
| 63 | +
|
| 64 | +interface IED25519 { |
| 65 | + function ed25519Verify( |
| 66 | + bytes32 publicKey, |
| 67 | + bytes32[2] calldata signature, |
| 68 | + bytes calldata message |
| 69 | + ) external returns (bool isValid); |
| 70 | +} |
| 71 | +
|
| 72 | +contract ED25519Example { |
| 73 | + IED25519 constant ED25519_PRECOMPILE = IED25519(0x00000000000000000000000000000000000008f3); |
| 74 | +
|
| 75 | + function verifySignature( |
| 76 | + bytes32 publicKey, |
| 77 | + bytes32[2] calldata signature, |
| 78 | + bytes calldata message |
| 79 | + ) public returns (bool) { |
| 80 | + return ED25519_PRECOMPILE.ed25519Verify(publicKey, signature, message); |
| 81 | + } |
| 82 | +} |
| 83 | +``` |
| 84 | + |
| 85 | +### JavaScript/TypeScript (ethers.js) |
| 86 | + |
| 87 | +```typescript |
| 88 | +import { ethers } from 'ethers'; |
| 89 | + |
| 90 | +const ED25519_ADDRESS = '0x00000000000000000000000000000000000008f3'; |
| 91 | + |
| 92 | +const ed25519ABI = [ |
| 93 | + { |
| 94 | + "inputs": [ |
| 95 | + { "internalType": "bytes32", "name": "publicKey", "type": "bytes32" }, |
| 96 | + { "internalType": "bytes32[2]", "name": "signature", "type": "bytes32[2]" }, |
| 97 | + { "internalType": "bytes", "name": "message", "type": "bytes" } |
| 98 | + ], |
| 99 | + "name": "ed25519Verify", |
| 100 | + "outputs": [ |
| 101 | + { "internalType": "bool", "name": "isValid", "type": "bool" } |
| 102 | + ], |
| 103 | + "stateMutability": "nonpayable", |
| 104 | + "type": "function" |
| 105 | + } |
| 106 | +]; |
| 107 | + |
| 108 | +async function verifyED25519Signature( |
| 109 | + provider: ethers.Provider, |
| 110 | + publicKey: string, |
| 111 | + signature: [string, string], |
| 112 | + message: string |
| 113 | +): Promise<boolean> { |
| 114 | + const ed25519Contract = new ethers.Contract(ED25519_ADDRESS, ed25519ABI, provider); |
| 115 | + const isValid = await ed25519Contract.ed25519Verify(publicKey, signature, message); |
| 116 | + return isValid; |
| 117 | +} |
| 118 | +``` |
| 119 | + |
| 120 | +## Technical Details |
| 121 | + |
| 122 | +### ED25519 Algorithm |
| 123 | + |
| 124 | +ED25519 is a public-key signature system that uses: |
| 125 | +- Curve25519 elliptic curve |
| 126 | +- SHA-512 hash function |
| 127 | +- Schnorr signature scheme |
| 128 | + |
| 129 | +### Signature Format |
| 130 | + |
| 131 | +The ED25519 signature is 64 bytes long and is split into two components: |
| 132 | +- **R component** (32 bytes): The first half of the signature |
| 133 | +- **S component** (32 bytes): The second half of the signature |
| 134 | + |
| 135 | +### Implementation |
| 136 | + |
| 137 | +The precompile uses Go's standard `crypto/ed25519` package for signature verification, ensuring compatibility with standard ED25519 implementations. |
| 138 | + |
| 139 | +## Security Considerations |
| 140 | + |
| 141 | +1. **Public Key Validation**: The precompile expects a valid 32-byte ED25519 public key. Invalid keys will result in verification failure. |
| 142 | + |
| 143 | +2. **Signature Validation**: The signature must be exactly 64 bytes (provided as two 32-byte arrays). Invalid signature lengths or formats will result in an error. |
| 144 | + |
| 145 | +3. **Message Integrity**: The message should be provided exactly as it was when the signature was created. Any modification will cause verification to fail. |
| 146 | + |
| 147 | +4. **Gas Limits**: When verifying large messages, ensure sufficient gas is provided based on the dynamic gas calculation formula. |
| 148 | + |
| 149 | +## Use Cases |
| 150 | + |
| 151 | +- **Cross-chain Communication**: Verify signatures from chains that use ED25519 (e.g., Cosmos SDK chains, Solana) |
| 152 | +- **Identity Verification**: Validate ED25519-based digital identities |
| 153 | +- **Secure Messaging**: Verify signed messages in decentralized applications |
| 154 | +- **Multi-signature Wallets**: Implement multi-sig wallets that support ED25519 |
| 155 | +- **Oracle Data Verification**: Verify signed data from oracles using ED25519 keys |
| 156 | + |
| 157 | +## Testing |
| 158 | + |
| 159 | +The precompile includes comprehensive test coverage. Run tests with: |
| 160 | + |
| 161 | +```bash |
| 162 | +go test ./precompiles/ed25519/... |
| 163 | +``` |
| 164 | + |
| 165 | +## References |
| 166 | + |
| 167 | +- [ED25519 Specification (RFC 8032)](https://datatracker.ietf.org/doc/html/rfc8032) |
| 168 | +- [Go crypto/ed25519 Package](https://pkg.go.dev/crypto/ed25519) |
| 169 | +- [Curve25519 and ED25519](https://ed25519.cr.yp.to/) |
| 170 | + |
| 171 | +## License |
| 172 | + |
| 173 | +This precompile is part of the Cosmos EVM project and is licensed under the project's license terms. |
0 commit comments