Skip to content

Commit 7160931

Browse files
authored
Merge pull request #609 from openmina/fix-poseidon
Fix poseidon hashing when absorbing empty slice
2 parents 23c8e29 + 3d33b6d commit 7160931

File tree

3 files changed

+76
-0
lines changed

3 files changed

+76
-0
lines changed

ledger/src/poseidon/mod.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1872,6 +1872,23 @@ impl<F: Field, SC: SpongeConstants> Sponge<F, F> for ArithmeticSponge<F, SC> {
18721872

18731873
#[inline(never)]
18741874
fn absorb(&mut self, x: &[F]) {
1875+
if x.is_empty() {
1876+
// Same as the loop below but doesn't add `x`
1877+
match self.sponge_state {
1878+
SpongeState::Absorbed(n) => {
1879+
if n == self.rate {
1880+
self.poseidon_block_cipher();
1881+
self.sponge_state = SpongeState::Absorbed(1);
1882+
} else {
1883+
self.sponge_state = SpongeState::Absorbed(n + 1);
1884+
}
1885+
}
1886+
SpongeState::Squeezed(_n) => {
1887+
self.sponge_state = SpongeState::Absorbed(1);
1888+
}
1889+
}
1890+
return;
1891+
}
18751892
for x in x.iter() {
18761893
match self.sponge_state {
18771894
SpongeState::Absorbed(n) => {

ledger/src/proofs/transaction.rs

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1687,7 +1687,28 @@ pub mod poseidon {
16871687
Self::new_with_state([F::zero(); 3], F::get_params2())
16881688
}
16891689

1690+
fn absorb_empty(&mut self, w: &mut Witness<F>) {
1691+
match self.sponge_state {
1692+
SpongeState::Absorbed(n) => {
1693+
if n == C::SPONGE_RATE {
1694+
self.poseidon_block_cipher(true, w);
1695+
self.sponge_state = SpongeState::Absorbed(1);
1696+
} else {
1697+
self.sponge_state = SpongeState::Absorbed(n + 1);
1698+
}
1699+
}
1700+
SpongeState::Squeezed(_n) => {
1701+
self.sponge_state = SpongeState::Absorbed(1);
1702+
}
1703+
}
1704+
}
1705+
16901706
pub fn absorb(&mut self, x: &[F], w: &mut Witness<F>) {
1707+
if x.is_empty() {
1708+
self.absorb_empty(w);
1709+
return;
1710+
}
1711+
16911712
// Hack to know when to ignore witness
16921713
// That should be removed once we use `cvar`
16931714
let mut first = true;
@@ -1719,6 +1740,11 @@ pub mod poseidon {
17191740
}
17201741

17211742
pub fn absorb2(&mut self, x: &[F], w: &mut Witness<F>) {
1743+
if x.is_empty() {
1744+
self.absorb_empty(w);
1745+
return;
1746+
}
1747+
17221748
// Hack to know when to ignore witness
17231749
// That should be removed once we use `cvar`
17241750
let mut first = true;
@@ -1754,6 +1780,11 @@ pub mod poseidon {
17541780
}
17551781

17561782
pub fn absorb3(&mut self, x: &[F], w: &mut Witness<F>) {
1783+
if x.is_empty() {
1784+
self.absorb_empty(w);
1785+
return;
1786+
}
1787+
17571788
// Hack to know when to ignore witness
17581789
// That should be removed once we use `cvar`
17591790
let mut first = true;
@@ -4429,6 +4460,21 @@ mod tests {
44294460
dbg!(sum);
44304461
}
44314462

4463+
#[test]
4464+
fn test_hash_empty_event_checked() {
4465+
// Same value than OCaml
4466+
const EXPECTED: &str =
4467+
"6963060754718463299978089777716994949151371320681588566338620419071140958308";
4468+
4469+
let mut w = Witness::empty();
4470+
let hash = transaction_snark::checked_hash("MinaZkappEvent", &[], &mut w);
4471+
assert_eq!(hash, Fp::from_str(EXPECTED).unwrap());
4472+
4473+
let mut w = Witness::empty();
4474+
let hash = transaction_snark::checked_hash3("MinaZkappEvent", &[], &mut w);
4475+
assert_eq!(hash, Fp::from_str(EXPECTED).unwrap());
4476+
}
4477+
44324478
/// Print requests types
44334479
#[allow(unused)]
44344480
#[test]

ledger/src/scan_state/transaction_logic.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -945,6 +945,9 @@ pub mod zkapp_command {
945945
pub struct Event(pub Vec<Fp>);
946946

947947
impl Event {
948+
pub fn empty() -> Self {
949+
Self(Vec::new())
950+
}
948951
pub fn hash(&self) -> Fp {
949952
hash_with_kimchi("MinaZkappEvent", &self.0[..])
950953
}
@@ -8395,6 +8398,16 @@ mod tests {
83958398
.into_compressed()
83968399
}
83978400

8401+
#[test]
8402+
fn test_hash_empty_event() {
8403+
// Same value than OCaml
8404+
const EXPECTED: &str =
8405+
"6963060754718463299978089777716994949151371320681588566338620419071140958308";
8406+
8407+
let event = zkapp_command::Event::empty();
8408+
assert_eq!(event.hash(), Fp::from_str(EXPECTED).unwrap());
8409+
}
8410+
83988411
/// Test using same values as here:
83998412
/// https://github.com/MinaProtocol/mina/blob/3a78f0e0c1343d14e2729c8b00205baa2ec70c93/src/lib/mina_base/receipt.ml#L136
84008413
#[test]

0 commit comments

Comments
 (0)