Skip to main content

fluentbase_runtime/syscall_handler/edwards/
edwards_add.rs

1use crate::{syscall_handler::syscall_process_exit_code, RuntimeContext};
2use fluentbase_types::{ExitCode, ED25519_POINT_DECOMPRESSED_SIZE};
3use rwasm::{StoreTr, TrapCode, Value};
4use sp1_curves::{edwards::ed25519::Ed25519, AffinePoint};
5
6pub fn syscall_edwards_add_handler(
7    ctx: &mut impl StoreTr<RuntimeContext>,
8    params: &[Value],
9    _result: &mut [Value],
10) -> Result<(), TrapCode> {
11    let p_ptr = params[0].i32().unwrap() as u32;
12    let mut p_bytes = [0u8; ED25519_POINT_DECOMPRESSED_SIZE];
13    ctx.memory_read(p_ptr as usize, &mut p_bytes)?;
14    let q_ptr = params[1].i32().unwrap() as u32;
15    let mut q_bytes = [0u8; ED25519_POINT_DECOMPRESSED_SIZE];
16    ctx.memory_read(q_ptr as usize, &mut q_bytes)?;
17    let res = syscall_edwards_add_impl(p_bytes, q_bytes)
18        .map_err(|e| syscall_process_exit_code(ctx, e))?;
19    ctx.memory_write(q_ptr as usize, &res)?;
20    Ok(())
21}
22
23#[cfg(target_endian = "big")]
24compile_error!("syscall_ed25519_add_impl is not implemented for big-endian targets");
25
26pub fn syscall_edwards_add_impl(
27    p_bytes: [u8; ED25519_POINT_DECOMPRESSED_SIZE],
28    q_bytes: [u8; ED25519_POINT_DECOMPRESSED_SIZE],
29) -> Result<[u8; ED25519_POINT_DECOMPRESSED_SIZE], ExitCode> {
30    let p_words: [u32; ED25519_POINT_DECOMPRESSED_SIZE / 4] = bytemuck::cast(p_bytes);
31    let q_words: [u32; ED25519_POINT_DECOMPRESSED_SIZE / 4] = bytemuck::cast(q_bytes);
32    let p_affine = AffinePoint::<Ed25519>::from_words_le(&p_words);
33    let q_affine = AffinePoint::<Ed25519>::from_words_le(&q_words);
34    let result_affine = p_affine + q_affine;
35    let r_words: [u32; ED25519_POINT_DECOMPRESSED_SIZE / 4] =
36        result_affine.to_words_le().try_into().unwrap();
37    let r_bytes: [u8; ED25519_POINT_DECOMPRESSED_SIZE] = bytemuck::cast(r_words);
38    Ok(r_bytes)
39}
40
41#[cfg(test)]
42mod tests {
43    use super::*;
44
45    /// SP1 tests are taken from: sp1/crates/test-artifacts/programs/ed-decompress/src/main.rs
46    #[test]
47    fn test_ed25519_add_sp1() {
48        // 90393249858788985237231628593243673548167146579814268721945474994541877372611
49        // 33321104029277118100578831462130550309254424135206412570121538923759338004303
50        let a: [u8; 64] = [
51            195, 166, 157, 207, 218, 220, 175, 197, 111, 177, 123, 23, 73, 72, 114, 103, 28, 246,
52            66, 207, 66, 146, 187, 234, 136, 238, 133, 145, 47, 196, 216, 199, 79, 31, 224, 30,
53            179, 122, 51, 84, 116, 12, 4, 189, 198, 198, 190, 22, 71, 201, 143, 249, 92, 56, 147,
54            133, 92, 187, 130, 33, 152, 19, 171, 73,
55        ];
56
57        // 61717728572175158701898635111983295176935961585742968051419350619945173564869
58        // 28137966556353620208933066709998005335145594788896528644015312259959272398451
59        let b: [u8; 64] = [
60            197, 189, 200, 77, 201, 212, 57, 105, 191, 133, 123, 170, 167, 50, 114, 38, 37, 102,
61            188, 29, 215, 227, 157, 142, 252, 31, 129, 67, 24, 255, 114, 136, 115, 94, 94, 55, 43,
62            200, 117, 224, 139, 251, 238, 45, 80, 154, 70, 213, 219, 78, 201, 108, 73, 203, 72, 45,
63            167, 131, 199, 47, 82, 134, 53, 62,
64        ];
65
66        let r = syscall_edwards_add_impl(a, b).unwrap();
67
68        // 36213413123116753589144482590359479011148956763279542162278577842046663495729
69        // 17093345531692682197799066694073110060588941459686871373458223451938707761683
70        let c: [u8; 64] = [
71            49, 144, 129, 197, 86, 163, 62, 48, 222, 208, 213, 200, 219, 90, 163, 54, 211, 248,
72            178, 224, 238, 167, 235, 219, 251, 247, 189, 239, 194, 16, 16, 80, 19, 106, 20, 198,
73            72, 56, 103, 111, 68, 201, 29, 107, 75, 208, 193, 232, 181, 186, 175, 22, 213, 187,
74            253, 125, 44, 80, 222, 209, 159, 125, 202, 37,
75        ];
76
77        assert_eq!(r, c);
78    }
79}