Skip to content

Commit e0e42d2

Browse files
authored
Merge pull request #16 from lambdaclass/state_size_in_pub_input
State size in protocol state public input
2 parents cdb2438 + 49e60b1 commit e0e42d2

7 files changed

Lines changed: 102 additions & 40 deletions

File tree

Makefile

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -401,6 +401,14 @@ batcher_send_mina_task_bad_hash:
401401
--public_input test_files/mina/protocol_state_bad_hash.pub \
402402
--proof_generator_addr 0x66f9664f97F2b50F62D13eA064982f936dE76657
403403

404+
batcher_send_mina_task_bad_consensus:
405+
@echo "Sending Mina state task to Batcher..."
406+
@cd batcher/aligned/ && cargo run --release -- submit \
407+
--proving_system Mina \
408+
--proof test_files/mina/protocol_state.proof \
409+
--public_input test_files/mina/protocol_state_bad_consensus.pub \
410+
--proof_generator_addr 0x66f9664f97F2b50F62D13eA064982f936dE76657
411+
404412
batcher_send_mina_burst:
405413
@echo "Sending Mina state task to Batcher..."
406414
@cd batcher/aligned/ && cargo run --release -- submit \

batcher/aligned-batcher/src/mina/mod.rs

Lines changed: 27 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,11 @@
1+
use std::array;
2+
13
use base64::prelude::*;
24
use log::{debug, warn};
35

46
const STATE_HASH_SIZE: usize = 32;
5-
// TODO(gabrielbosio): check that this length is always the same for every block
6-
const PROTOCOL_STATE_SIZE: usize = 2056;
77

88
pub fn verify_protocol_state_proof_integrity(proof: &[u8], public_input: &[u8]) -> bool {
9-
if public_input.len() != (STATE_HASH_SIZE + PROTOCOL_STATE_SIZE) * 2 {
10-
return false;
11-
}
12-
139
debug!("Checking Mina protocol state proof");
1410
if let Err(err) = check_protocol_state_proof(proof) {
1511
warn!("Protocol state proof check failed: {}", err);
@@ -38,24 +34,35 @@ pub fn check_protocol_state_proof(protocol_state_proof_bytes: &[u8]) -> Result<(
3834

3935
pub fn check_protocol_state_pub(protocol_state_pub: &[u8]) -> Result<(), String> {
4036
// TODO(xqft): check hash and binprot deserialization
41-
let candidate_protocol_state_base64 = std::str::from_utf8(
42-
&protocol_state_pub[STATE_HASH_SIZE..(STATE_HASH_SIZE + PROTOCOL_STATE_SIZE)],
43-
)
44-
.map_err(|err| err.to_string())?;
45-
BASE64_STANDARD
46-
.decode(candidate_protocol_state_base64)
47-
.map_err(|err| err.to_string())?;
37+
let candidate_protocol_state_len =
38+
check_protocol_state_and_hash(protocol_state_pub, STATE_HASH_SIZE)?;
4839

49-
let tip_protocol_state_base64 = std::str::from_utf8(
50-
&protocol_state_pub[(STATE_HASH_SIZE + PROTOCOL_STATE_SIZE) + STATE_HASH_SIZE
51-
..((STATE_HASH_SIZE + PROTOCOL_STATE_SIZE) * 2)],
52-
)
53-
.map_err(|err| err.to_string())?;
40+
let _tip_protocol_state_len = check_protocol_state_and_hash(
41+
protocol_state_pub,
42+
STATE_HASH_SIZE + 4 + candidate_protocol_state_len + STATE_HASH_SIZE,
43+
)?;
44+
45+
Ok(())
46+
}
47+
48+
fn check_protocol_state_and_hash(protocol_state_pub: &[u8], start: usize) -> Result<usize, String> {
49+
let protocol_state_len_vec: Vec<_> = protocol_state_pub.iter().skip(start).take(4).collect();
50+
let protocol_state_len_bytes: [u8; 4] = array::from_fn(|i| protocol_state_len_vec[i].clone());
51+
let protocol_state_len = u32::from_be_bytes(protocol_state_len_bytes) as usize;
52+
53+
let protocol_state_bytes: Vec<_> = protocol_state_pub
54+
.iter()
55+
.skip(start + 4)
56+
.take(protocol_state_len)
57+
.map(|byte| byte.clone())
58+
.collect();
59+
let protocol_state_base64 =
60+
std::str::from_utf8(protocol_state_bytes.as_slice()).map_err(|err| err.to_string())?;
5461
BASE64_STANDARD
55-
.decode(tip_protocol_state_base64)
62+
.decode(protocol_state_base64)
5663
.map_err(|err| err.to_string())?;
5764

58-
Ok(())
65+
Ok(protocol_state_len)
5966
}
6067

6168
#[cfg(test)]

batcher/aligned/test_files/mina/protocol_state.proof

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.
8 Bytes
Binary file not shown.
0 Bytes
Binary file not shown.
8 Bytes
Binary file not shown.

operator/mina/lib/src/lib.rs

Lines changed: 66 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
mod consensus_state;
22

3+
use std::array;
4+
35
use ark_ec::short_weierstrass_jacobian::GroupAffine;
46
use base64::prelude::*;
57
use consensus_state::{select_longer_chain, LongerChainResult};
@@ -24,9 +26,7 @@ lazy_static! {
2426
// TODO(xqft): check proof size
2527
const MAX_PROOF_SIZE: usize = 16 * 1024;
2628
const MAX_PUB_INPUT_SIZE: usize = 6 * 1024;
27-
const PROTOCOL_STATE_HASH_SIZE: usize = 32;
28-
// TODO(gabrielbosio): check that this length is always the same for every block
29-
const PROTOCOL_STATE_SIZE: usize = 2056;
29+
const STATE_HASH_SIZE: usize = 32;
3030

3131
#[no_mangle]
3232
pub extern "C" fn verify_protocol_state_proof_ffi(
@@ -110,14 +110,11 @@ pub fn parse_protocol_state_pub(
110110
),
111111
String,
112112
> {
113-
let (tip_protocol_state_hash, tip_protocol_state) = parse_protocol_state_with_hash(
114-
&protocol_state_pub[..(PROTOCOL_STATE_HASH_SIZE + PROTOCOL_STATE_SIZE)],
115-
)?;
113+
let (tip_protocol_state_hash, tip_protocol_state, candidate_start) =
114+
parse_protocol_state_with_hash(&protocol_state_pub, 0)?;
116115

117-
let (candidate_protocol_state_hash, candidate_protocol_state) = parse_protocol_state_with_hash(
118-
&protocol_state_pub[(PROTOCOL_STATE_HASH_SIZE + PROTOCOL_STATE_SIZE)
119-
..((PROTOCOL_STATE_HASH_SIZE + PROTOCOL_STATE_SIZE) * 2)],
120-
)?;
116+
let (candidate_protocol_state_hash, candidate_protocol_state, _) =
117+
parse_protocol_state_with_hash(&protocol_state_pub, candidate_start)?;
121118

122119
Ok((
123120
tip_protocol_state_hash,
@@ -129,25 +126,52 @@ pub fn parse_protocol_state_pub(
129126

130127
fn parse_protocol_state_with_hash(
131128
protocol_state_pub: &[u8],
129+
start: usize,
132130
) -> Result<
133131
(
134132
ark_ff::Fp256<mina_curves::pasta::fields::FpParameters>,
135133
MinaStateProtocolStateValueStableV2,
134+
usize,
136135
),
137136
String,
138137
> {
138+
let protocol_state_hash_bytes: Vec<_> = protocol_state_pub
139+
.iter()
140+
.skip(start)
141+
.take(STATE_HASH_SIZE)
142+
.map(|byte| byte.clone())
143+
.collect();
139144
let protocol_state_hash =
140-
Fp::from_bytes(&protocol_state_pub[..32]).map_err(|err| err.to_string())?;
145+
Fp::from_bytes(&protocol_state_hash_bytes).map_err(|err| err.to_string())?;
146+
147+
let protocol_state_len_vec: Vec<_> = protocol_state_pub
148+
.iter()
149+
.skip(start + STATE_HASH_SIZE)
150+
.take(8)
151+
.collect();
152+
let protocol_state_len_bytes: [u8; 4] = array::from_fn(|i| protocol_state_len_vec[i].clone());
153+
let protocol_state_len = u32::from_be_bytes(protocol_state_len_bytes) as usize;
154+
155+
let protocol_state_bytes: Vec<_> = protocol_state_pub
156+
.iter()
157+
.skip(start + STATE_HASH_SIZE + 4)
158+
.take(protocol_state_len)
159+
.map(|byte| byte.clone())
160+
.collect();
141161
let protocol_state_base64 =
142-
std::str::from_utf8(&protocol_state_pub[32..]).map_err(|err| err.to_string())?;
162+
std::str::from_utf8(&protocol_state_bytes).map_err(|err| err.to_string())?;
143163
let protocol_state_binprot = BASE64_STANDARD
144164
.decode(protocol_state_base64)
145165
.map_err(|err| err.to_string())?;
146166
let protocol_state =
147167
MinaStateProtocolStateValueStableV2::binprot_read(&mut protocol_state_binprot.as_slice())
148168
.map_err(|err| err.to_string())?;
149169

150-
Ok((protocol_state_hash, protocol_state))
170+
Ok((
171+
protocol_state_hash,
172+
protocol_state,
173+
start + STATE_HASH_SIZE + 4 + protocol_state_len,
174+
))
151175
}
152176

153177
#[cfg(test)]
@@ -158,9 +182,11 @@ mod test {
158182
include_bytes!("../../../../batcher/aligned/test_files/mina/protocol_state.proof");
159183
const PROTOCOL_STATE_PUB_BYTES: &[u8] =
160184
include_bytes!("../../../../batcher/aligned/test_files/mina/protocol_state.pub");
161-
const BAD_PROTOCOL_STATE_PUB_BYTES: &[u8] =
162-
include_bytes!("../../../../batcher/aligned/test_files/mina/bad_protocol_state.pub");
163-
// BAD_PROTOCOL_STATE_PUB_BYTES has an invalid hash.
185+
const PROTOCOL_STATE_BAD_HASH_PUB_BYTES: &[u8] =
186+
include_bytes!("../../../../batcher/aligned/test_files/mina/protocol_state_bad_hash.pub");
187+
const PROTOCOL_STATE_BAD_CONSENSUS_PUB_BYTES: &[u8] = include_bytes!(
188+
"../../../../batcher/aligned/test_files/mina/protocol_state_bad_consensus.pub"
189+
);
164190

165191
#[test]
166192
fn parse_protocol_state_proof_does_not_fail() {
@@ -194,16 +220,37 @@ mod test {
194220
}
195221

196222
#[test]
197-
fn bad_protocol_state_proof_does_not_verify() {
223+
fn proof_of_protocol_state_with_bad_hash_does_not_verify() {
224+
let mut proof_buffer = [0u8; super::MAX_PROOF_SIZE];
225+
let proof_size = PROTOCOL_STATE_PROOF_BYTES.len();
226+
assert!(proof_size <= proof_buffer.len());
227+
proof_buffer[..proof_size].clone_from_slice(PROTOCOL_STATE_PROOF_BYTES);
228+
229+
let mut pub_input_buffer = [0u8; super::MAX_PUB_INPUT_SIZE];
230+
let pub_input_size = PROTOCOL_STATE_BAD_HASH_PUB_BYTES.len();
231+
assert!(pub_input_size <= pub_input_buffer.len());
232+
pub_input_buffer[..pub_input_size].clone_from_slice(PROTOCOL_STATE_BAD_HASH_PUB_BYTES);
233+
234+
let result = verify_protocol_state_proof_ffi(
235+
&proof_buffer,
236+
proof_size,
237+
&pub_input_buffer,
238+
pub_input_size,
239+
);
240+
assert!(!result);
241+
}
242+
243+
#[test]
244+
fn proof_of_protocol_state_with_bad_consensus_does_not_verify() {
198245
let mut proof_buffer = [0u8; super::MAX_PROOF_SIZE];
199246
let proof_size = PROTOCOL_STATE_PROOF_BYTES.len();
200247
assert!(proof_size <= proof_buffer.len());
201248
proof_buffer[..proof_size].clone_from_slice(PROTOCOL_STATE_PROOF_BYTES);
202249

203250
let mut pub_input_buffer = [0u8; super::MAX_PUB_INPUT_SIZE];
204-
let pub_input_size = BAD_PROTOCOL_STATE_PUB_BYTES.len();
251+
let pub_input_size = PROTOCOL_STATE_BAD_CONSENSUS_PUB_BYTES.len();
205252
assert!(pub_input_size <= pub_input_buffer.len());
206-
pub_input_buffer[..pub_input_size].clone_from_slice(BAD_PROTOCOL_STATE_PUB_BYTES);
253+
pub_input_buffer[..pub_input_size].clone_from_slice(PROTOCOL_STATE_BAD_CONSENSUS_PUB_BYTES);
207254

208255
let result = verify_protocol_state_proof_ffi(
209256
&proof_buffer,

0 commit comments

Comments
 (0)