You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
|`0xEC00000000000000000000000000000000000001`|`usigverifier`| Ed25519 signature verification (Solana signatures over `bytes32` digests), registered at the reserved Push range |
152
152
153
-
Gas cost: `4000` per `verifyEd25519` call. See [`precompiles/usigverifier/README.md`](../precompiles/usigverifier/README.md).
153
+
Gas cost: `4000` per `verifyEd25519` call (fixed 32-byte digest), and `4000` plus `12` per 32-byte
154
+
word of `message` for `verifyEd25519RawMessage`, whose message is hard-capped at 128 KiB. See
The baseline EVM precompiles (`bech32`, `p256`, `staking`, `distribution`, `ics20`, `bank`, `gov`, `slashing`, `evidence`) are wired in via `app/precompiles.go:NewAvailableStaticPrecompiles`.
Copy file name to clipboardExpand all lines: precompiles/usigverifier/README.md
+33-6Lines changed: 33 additions & 6 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -40,11 +40,36 @@ interface IUSigVerifier {
40
40
41
41
| Method | Signed bytes | Gas | Use when |
42
42
|---|---|---|---|
43
-
|`verifyEd25519(bytes,bytes32,bytes)`|`"0x" + hex(msgDigest)` (66 ASCII bytes) | 4000 | UEA_SVM / Solana-wallet flows where the user signs a hex string in Phantom/Solflare |
44
-
|`verifyEd25519RawMessage(bytes,bytes,bytes)`| Raw `message` bytes | 4000 | New integrations / relayers using standard `ed25519.Sign(privKey, rawBytes)`|
43
+
|`verifyEd25519(bytes,bytes32,bytes)`|`"0x" + hex(msgDigest)` (66 ASCII bytes) | 4000 (flat) | UEA_SVM / Solana-wallet flows where the user signs a hex string in Phantom/Solflare |
44
+
|`verifyEd25519RawMessage(bytes,bytes,bytes)`| Raw `message` bytes |`4000 + 12` per 32-byte word of `message`| New integrations / relayers using standard `ed25519.Sign(privKey, rawBytes)`|
45
45
46
46
Both methods are `view` and touch no chain state.
47
47
48
+
### Why only the raw method scales with size
49
+
50
+
`ed25519.Verify` hashes the whole message, so its CPU cost grows with the message
51
+
(~58 µs at 32 B, ~146 µs at 128 KiB, ~922 µs at 1 MB). `verifyEd25519` always verifies
52
+
the same 66-byte ASCII string no matter what the caller sends, so its cost is constant
53
+
and its price stays flat. `verifyEd25519RawMessage` verifies caller-supplied bytes, so
54
+
it is priced per 32-byte word — the same per-word rate the EVM `SHA-256` precompile
55
+
charges for comparable hashing work.
56
+
57
+
Because both methods are `view`, a contract can park one large message in memory and
58
+
loop `STATICCALL`s over it, paying the calldata only once. Pricing alone is therefore
59
+
not the whole defence: `message` is also **hard-capped at 128 KiB**
60
+
(`MaxEd25519MessageBytes`), and anything larger reverts with `message too large`
61
+
instead of being verified.
62
+
63
+
|`len(message)`| Gas |
64
+
|---|---|
65
+
| 0 | 4,000 |
66
+
| 32 B | 4,012 |
67
+
| 1 KiB | 4,384 |
68
+
| 8 KiB | 7,072 |
69
+
| 64 KiB | 28,576 |
70
+
| 128 KiB (cap) | 53,152 |
71
+
| > 128 KiB | reverts |
72
+
48
73
## Verification Semantics
49
74
50
75
Two methods, two distinct signing conventions. **A signature produced for one method will not verify under the other** — the test vectors in `query_test.go` lock this in.
@@ -69,13 +94,14 @@ Standard Ed25519 verification — signature is checked against the raw `message`
69
94
ok = ed25519.Verify(pubKeyBytes, message, signature)
70
95
```
71
96
72
-
Use this when your signer uses `ed25519.Sign(privKey, rawBytes)` (default in every Solana SDK / nacl library). `message` may be any length, not just 32 bytes.
97
+
Use this when your signer uses `ed25519.Sign(privKey, rawBytes)` (default in every Solana SDK / nacl library). `message` may be any length up to `MaxEd25519MessageBytes` (128 KiB), not just 32 bytes.
73
98
74
99
### Common rules
75
100
76
101
-`pubKey` must be exactly 32 bytes; `signature` must be exactly 64 bytes — otherwise the precompile reverts with `invalid params`.
102
+
-`verifyEd25519RawMessage` reverts with `message too large` past `MaxEd25519MessageBytes` (128 KiB).
77
103
- Unknown method IDs revert with the standard `unknown method` error.
78
-
-Both methods cost `4000` gas.
104
+
-`verifyEd25519` costs a flat `4000` gas; `verifyEd25519RawMessage` costs `4000` plus `12` per 32-byte word of `message`.
79
105
80
106
## Generating the ABI
81
107
@@ -120,7 +146,8 @@ If the call returns `0x` (empty), the precompile is not in `active_static_precom
120
146
precompiles/usigverifier/
121
147
|-- USigVerifier.sol Solidity interface (the source of truth for the ABI)
122
148
|-- abi.json Embedded into the binary via go:embed
123
-
|-- usigverifier.go Precompile struct, NewPrecompile / NewPrecompileV2, RequiredGas, Run
0 commit comments