pallet_evm_precompile_ed25519/
lib.rs1#![cfg_attr(not(feature = "std"), no_std)]
19#![warn(unused_crate_dependencies)]
20
21extern crate alloc;
22
23use alloc::vec::Vec;
24
25use ed25519_dalek::{Signature, Verifier, VerifyingKey};
26use fp_evm::{ExitError, ExitSucceed, LinearCostPrecompile, PrecompileFailure};
27
28pub struct Ed25519Verify;
29
30impl LinearCostPrecompile for Ed25519Verify {
31 const BASE: u64 = 15;
32 const WORD: u64 = 3;
33
34 fn execute(input: &[u8], _: u64) -> Result<(ExitSucceed, Vec<u8>), PrecompileFailure> {
35 if input.len() < 128 {
36 return Err(PrecompileFailure::Error {
37 exit_status: ExitError::Other("input must contain 128 bytes".into()),
38 });
39 };
40
41 let mut i = [0u8; 128];
42 i[..128].copy_from_slice(&input[..128]);
43
44 let mut buf = [0u8; 4];
45
46 let msg = &i[0..32];
47 let pk = VerifyingKey::try_from(&i[32..64]).map_err(|_| PrecompileFailure::Error {
48 exit_status: ExitError::Other("Public key recover failed".into()),
49 })?;
50 let sig = Signature::try_from(&i[64..128]).map_err(|_| PrecompileFailure::Error {
51 exit_status: ExitError::Other("Signature recover failed".into()),
52 })?;
53
54 if pk.verify(msg, &sig).is_ok() {
56 buf[3] = 0u8;
57 } else {
58 buf[3] = 1u8;
59 };
60
61 Ok((ExitSucceed::Returned, buf.to_vec()))
62 }
63}
64
65#[cfg(test)]
66mod tests {
67 use super::*;
68 use ed25519_dalek::{Signer, SigningKey};
69
70 #[test]
71 fn test_empty_input() -> Result<(), PrecompileFailure> {
72 let input: [u8; 0] = [];
73 let cost: u64 = 1;
74
75 match Ed25519Verify::execute(&input, cost) {
76 Ok((_, _)) => {
77 panic!("Test not expected to pass");
78 }
79 Err(e) => {
80 assert_eq!(
81 e,
82 PrecompileFailure::Error {
83 exit_status: ExitError::Other("input must contain 128 bytes".into())
84 }
85 );
86 Ok(())
87 }
88 }
89 }
90
91 #[test]
92 fn test_verify() -> Result<(), PrecompileFailure> {
93 #[allow(clippy::zero_prefixed_literal)]
94 let secret_key_bytes: [u8; ed25519_dalek::SECRET_KEY_LENGTH] = [
95 157, 097, 177, 157, 239, 253, 090, 096, 186, 132, 074, 244, 146, 236, 044, 196, 068,
96 073, 197, 105, 123, 050, 105, 025, 112, 059, 172, 003, 028, 174, 127, 096,
97 ];
98
99 let keypair = SigningKey::from_bytes(&secret_key_bytes);
100 let public_key = keypair.verifying_key();
101
102 let msg: &[u8] = b"abcdefghijklmnopqrstuvwxyz123456";
103 assert_eq!(msg.len(), 32);
104 let signature = keypair.sign(msg);
105
106 let mut input: Vec<u8> = Vec::with_capacity(128);
111 input.extend_from_slice(msg);
112 input.extend_from_slice(&public_key.to_bytes());
113 input.extend_from_slice(&signature.to_bytes());
114 assert_eq!(input.len(), 128);
115
116 let cost: u64 = 1;
117
118 match Ed25519Verify::execute(&input, cost) {
119 Ok((_, output)) => {
120 assert_eq!(output.len(), 4);
121 assert_eq!(output[0], 0u8);
122 assert_eq!(output[1], 0u8);
123 assert_eq!(output[2], 0u8);
124 assert_eq!(output[3], 0u8);
125 }
126 Err(e) => {
127 return Err(e);
128 }
129 };
130
131 let msg: &[u8] = b"BAD_MESSAGE_mnopqrstuvwxyz123456";
133
134 let mut input: Vec<u8> = Vec::with_capacity(128);
135 input.extend_from_slice(msg);
136 input.extend_from_slice(&public_key.to_bytes());
137 input.extend_from_slice(&signature.to_bytes());
138 assert_eq!(input.len(), 128);
139
140 match Ed25519Verify::execute(&input, cost) {
141 Ok((_, output)) => {
142 assert_eq!(output.len(), 4);
143 assert_eq!(output[0], 0u8);
144 assert_eq!(output[1], 0u8);
145 assert_eq!(output[2], 0u8);
146 assert_eq!(output[3], 1u8); }
148 Err(e) => {
149 return Err(e);
150 }
151 };
152
153 Ok(())
154 }
155}