Skip to content

Commit 159a45d

Browse files
authored
fix: pad Poseidon hashv inputs to 32 bytes for syscall compatibility (#2373)
Solana mainnet now enforces all Poseidon syscall inputs to be exactly 32 bytes. Left-pad sub-32-byte inputs inside Poseidon::hashv() right before the syscall/library call. This preserves field element values (leading BE zeros are a no-op) and keeps AsByteVec and #[truncate] backwards compatible. Bumps light-hasher 1.1.0 -> 1.1.1, light-sdk 0.11.0 -> 0.11.1.
1 parent 2fc6f6d commit 159a45d

5 files changed

Lines changed: 24 additions & 5 deletions

File tree

Cargo.lock

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

merkle-tree/hasher/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "light-hasher"
3-
version = "1.1.0"
3+
version = "1.1.1"
44
description = "Trait for generic usage of hash functions on Solana"
55
repository = "https://github.com/Lightprotocol/light-protocol"
66
license = "Apache-2.0"

merkle-tree/hasher/src/errors.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ pub enum HasherError {
1212
PoseidonSyscall(#[from] PoseidonSyscallError),
1313
#[error("Unknown Solana syscall error: {0}")]
1414
UnknownSolanaSyscall(u64),
15+
#[error("Input length {0} exceeds maximum of {1} bytes")]
16+
InputTooLarge(usize, usize),
1517
}
1618

1719
// NOTE(vadorovsky): Unfortunately, we need to do it by hand. `num_derive::ToPrimitive`
@@ -23,6 +25,7 @@ impl From<HasherError> for u32 {
2325
HasherError::Poseidon(_) => 7002,
2426
HasherError::PoseidonSyscall(e) => (u64::from(e)).try_into().unwrap_or(7003),
2527
HasherError::UnknownSolanaSyscall(e) => e.try_into().unwrap_or(7004),
28+
HasherError::InputTooLarge(_, _) => 7005,
2629
}
2730
}
2831
}

merkle-tree/hasher/src/poseidon.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,22 @@ impl Hasher for Poseidon {
1414
}
1515

1616
fn hashv(vals: &[&[u8]]) -> Result<Hash, HasherError> {
17+
// Poseidon syscall requires exactly 32-byte inputs.
18+
// Leading zeros preserve big-endian field element values.
19+
let padded_bufs: Vec<[u8; 32]> = vals
20+
.iter()
21+
.map(|v| {
22+
if v.len() > 32 {
23+
return Err(HasherError::InputTooLarge(v.len(), 32));
24+
}
25+
let mut buf = [0u8; 32];
26+
buf[32 - v.len()..].copy_from_slice(v);
27+
Ok(buf)
28+
})
29+
.collect::<Result<Vec<_>, _>>()?;
30+
let vals: Vec<&[u8]> = padded_bufs.iter().map(|b| b.as_slice()).collect();
31+
let vals: &[&[u8]] = vals.as_slice();
32+
1733
// Perform the calculation inline, calling this from within a program is
1834
// not supported.
1935
#[cfg(not(target_os = "solana"))]

sdk/Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "light-sdk"
3-
version = "0.11.0"
3+
version = "0.11.1"
44
description = "Rust SDK for ZK Compression on Solana"
55
repository = "https://github.com/Lightprotocol/light-protocol"
66
license = "Apache-2.0"
@@ -37,7 +37,7 @@ aligned-sized = { version = "1.1.0", path = "../macros/aligned-sized" }
3737
light-macros = { version = "1.1.0", path = "../macros/light" }
3838
light-sdk-macros = { version = "0.4.0", path = "../macros/light-sdk-macros" }
3939
bytemuck = "1.17"
40-
light-hasher = { version = "1.1.0", path = "../merkle-tree/hasher", features=["solana"] }
40+
light-hasher = { version = "1.1.1", path = "../merkle-tree/hasher", features=["solana"] }
4141
light-heap = { version = "1.1.0", path = "../heap", optional = true }
4242
light-indexed-merkle-tree = { workspace = true }
4343
account-compression = { workspace = true , optional = true }

0 commit comments

Comments
 (0)