1use std::borrow::Cow;
2
3use crate::{
4 default_zkapp_hash,
5 proofs::{public_input::plonk_checks::ShiftingValue, util::four_u64_to_field},
6};
7use ark_ff::{Field, One, Zero};
8use kimchi::proof::{PointEvaluations, ProofEvaluations, ProverCommitments, ProverProof};
9use mina_curves::pasta::{Fp, Fq};
10use mina_p2p_messages::{string::ByteString, v2};
11use mina_signer::CompressedPubKey;
12use poly_commitment::evaluation_proof::OpeningProof;
13
14use crate::{
15 proofs::{
16 public_input::prepared_statement::{DeferredValues, Plonk, ProofState},
17 step::OptFlag,
18 util::two_u64_to_field,
19 },
20 scan_state::{
21 currency::{self, Sgn},
22 fee_excess::FeeExcess,
23 pending_coinbase,
24 scan_state::transaction_snark::{Registers, SokDigest, Statement},
25 transaction_logic::{
26 protocol_state::{EpochData, EpochLedger},
27 transaction_union_payload,
28 zkapp_statement::ZkappStatement,
29 },
30 },
31 staged_ledger::hash::StagedLedgerHash,
32 Account, MyCow, ReceiptChainHash, TimingAsRecord, TokenId, TokenSymbol, VotingFor,
33};
34
35use super::{
36 field::{Boolean, CircuitVar, FieldWitness, GroupAffine},
37 step::PerProofWitness,
38 transaction::{
39 field_to_bits, InnerCurve, PlonkVerificationKeyEvals, StepMainProofState, StepMainStatement,
40 },
41 unfinalized::{AllEvals, EvalsWithPublicInput},
42};
43
44pub trait ToFieldElementsDebug: ToFieldElements<Fp> + std::fmt::Debug {}
45
46impl<T: ToFieldElements<Fp> + std::fmt::Debug> ToFieldElementsDebug for T {}
47
48pub trait ToFieldElements<F: Field> {
49 fn to_field_elements(&self, fields: &mut Vec<F>);
50
51 fn to_field_elements_owned(&self) -> Vec<F> {
52 let mut fields = Vec::with_capacity(1024);
53 self.to_field_elements(&mut fields);
54 fields
55 }
56}
57
58impl ToFieldElements<Fp> for ZkappStatement {
59 fn to_field_elements(&self, fields: &mut Vec<Fp>) {
60 fields.extend(self.to_field_elements())
61 }
62}
63
64impl<F: Field> ToFieldElements<F> for () {
74 fn to_field_elements(&self, _fields: &mut Vec<F>) {}
75}
76
77impl ToFieldElements<Fp> for SokDigest {
78 fn to_field_elements(&self, fields: &mut Vec<Fp>) {
79 const BITS: [u8; 8] = [1, 2, 4, 8, 16, 32, 64, 128];
80 for byte in &self.0 {
81 fields.extend(BITS.iter().map(|bit| Fp::from((byte & bit != 0) as u64)));
82 }
83 }
84}
85
86impl<T: ToFieldElements<Fp>> ToFieldElements<Fp> for Statement<T> {
99 fn to_field_elements(&self, fields: &mut Vec<Fp>) {
100 let Self {
101 source,
102 target,
103 connecting_ledger_left,
104 connecting_ledger_right,
105 supply_increase,
106 fee_excess,
107 sok_digest,
108 } = self;
109
110 let sign_to_field = |sgn| -> Fp {
111 use crate::scan_state::currency::Sgn::*;
112 match sgn {
113 Pos => 1i64,
114 Neg => -1,
115 }
116 .into()
117 };
118
119 let mut add_register = |registers: &Registers| {
120 let Registers {
121 first_pass_ledger,
122 second_pass_ledger,
123 pending_coinbase_stack,
124 local_state,
125 } = registers;
126
127 first_pass_ledger.to_field_elements(fields);
128 second_pass_ledger.to_field_elements(fields);
129 pending_coinbase_stack.to_field_elements(fields);
130 local_state.stack_frame.to_field_elements(fields);
131 local_state.call_stack.to_field_elements(fields);
132 local_state.transaction_commitment.to_field_elements(fields);
133 local_state
134 .full_transaction_commitment
135 .to_field_elements(fields);
136 local_state.excess.magnitude.to_field_elements(fields);
137 sign_to_field(local_state.excess.sgn).to_field_elements(fields);
138 local_state
139 .supply_increase
140 .magnitude
141 .to_field_elements(fields);
142 sign_to_field(local_state.supply_increase.sgn).to_field_elements(fields);
143 local_state.ledger.to_field_elements(fields);
144 local_state.success.to_field_elements(fields);
145 local_state.account_update_index.to_field_elements(fields);
146 local_state.will_succeed.to_field_elements(fields);
147 };
148
149 add_register(source);
150 add_register(target);
151 connecting_ledger_left.to_field_elements(fields);
152 connecting_ledger_right.to_field_elements(fields);
153 supply_increase.magnitude.to_field_elements(fields);
154 sign_to_field(supply_increase.sgn).to_field_elements(fields);
155
156 let FeeExcess {
157 fee_token_l,
158 fee_excess_l,
159 fee_token_r,
160 fee_excess_r,
161 } = fee_excess;
162
163 fee_token_l.to_field_elements(fields);
164 fee_excess_l.magnitude.to_field_elements(fields);
165 sign_to_field(fee_excess_l.sgn).to_field_elements(fields);
166
167 fee_token_r.to_field_elements(fields);
168 fee_excess_r.magnitude.to_field_elements(fields);
169 sign_to_field(fee_excess_r.sgn).to_field_elements(fields);
170
171 sok_digest.to_field_elements(fields)
172 }
173}
174
175impl<F: FieldWitness, T: ToFieldElements<F>> ToFieldElements<F> for Vec<T> {
176 fn to_field_elements(&self, fields: &mut Vec<F>) {
177 self.iter().for_each(|v| v.to_field_elements(fields));
178 }
179}
180
181impl<F: FieldWitness, T: ToFieldElements<F>> ToFieldElements<F> for Box<[T]> {
182 fn to_field_elements(&self, fields: &mut Vec<F>) {
183 self.iter().for_each(|v| v.to_field_elements(fields));
184 }
185}
186
187impl<F: FieldWitness> ToFieldElements<F> for Fp {
188 fn to_field_elements(&self, fields: &mut Vec<F>) {
189 use crate::proofs::field::IntoGeneric;
190 fields.push(self.into_gen());
191 }
192}
193
194impl<F: FieldWitness, T: ToFieldElements<F> + Clone> ToFieldElements<F> for Cow<'_, T> {
195 fn to_field_elements(&self, fields: &mut Vec<F>) {
196 let this: &T = self.as_ref();
197 this.to_field_elements(fields)
198 }
199}
200
201pub fn field_of_bits<F: FieldWitness, const N: usize>(bs: &[bool; N]) -> F {
203 bs.iter().rev().fold(F::zero(), |acc, b| {
204 let acc = acc + acc;
205 if *b {
206 acc + F::one()
207 } else {
208 acc
209 }
210 })
211}
212
213impl<F: FieldWitness> ToFieldElements<F> for Fq {
214 fn to_field_elements(&self, fields: &mut Vec<F>) {
215 use crate::proofs::field::IntoGeneric;
216 use std::any::TypeId;
217
218 if TypeId::of::<F>() == TypeId::of::<Fq>() {
220 fields.push(self.into_gen());
221 } else {
222 let to_high_low = |fq: Fq| {
227 let [low, high @ ..] = field_to_bits::<Fq, 255>(fq);
228 [field_of_bits(&high), F::from(low)]
229 };
230 fields.extend(to_high_low(*self));
231 }
232 }
233}
234
235impl<F: FieldWitness, T: ToFieldElements<F>, const N: usize> ToFieldElements<F> for [T; N] {
236 fn to_field_elements(&self, fields: &mut Vec<F>) {
237 self.iter().for_each(|v| v.to_field_elements(fields));
238 }
239}
240
241impl<F: FieldWitness> ToFieldElements<F> for StagedLedgerHash<F> {
242 fn to_field_elements(&self, fields: &mut Vec<F>) {
243 let Self {
244 non_snark,
245 pending_coinbase_hash,
246 } = self;
247
248 let non_snark_digest = non_snark.digest();
249
250 const BITS: [u8; 8] = [1, 2, 4, 8, 16, 32, 64, 128];
251 fields.extend(
252 non_snark_digest
253 .iter()
254 .flat_map(|byte| BITS.iter().map(|bit| F::from((*byte & bit != 0) as u64))),
255 );
256
257 pending_coinbase_hash.to_field_elements(fields);
258 }
259}
260
261impl<F: FieldWitness> ToFieldElements<F> for ByteString {
262 fn to_field_elements(&self, fields: &mut Vec<F>) {
263 let slice: &[u8] = self;
264 slice.to_field_elements(fields);
265 }
266}
267
268impl<F: FieldWitness> ToFieldElements<F> for GroupAffine<F> {
269 fn to_field_elements(&self, fields: &mut Vec<F>) {
270 let Self {
271 x, y, infinity: _, ..
272 } = self;
273 y.to_field_elements(fields);
274 x.to_field_elements(fields);
275 }
276}
277
278impl<F: FieldWitness> ToFieldElements<F> for &'_ [u8] {
279 fn to_field_elements(&self, fields: &mut Vec<F>) {
280 const BITS: [u8; 8] = [1, 2, 4, 8, 16, 32, 64, 128];
281 fields.extend(
282 self.iter()
283 .flat_map(|byte| BITS.iter().map(|bit| F::from((*byte & bit != 0) as u64))),
284 );
285 }
286}
287
288impl<F: FieldWitness> ToFieldElements<F> for &'_ [bool] {
289 fn to_field_elements(&self, fields: &mut Vec<F>) {
290 fields.reserve(self.len());
291 fields.extend(self.iter().copied().map(F::from))
292 }
293}
294
295impl<F: FieldWitness> ToFieldElements<F> for bool {
296 fn to_field_elements(&self, fields: &mut Vec<F>) {
297 F::from(*self).to_field_elements(fields)
298 }
299}
300
301impl<F: FieldWitness> ToFieldElements<F> for u64 {
302 fn to_field_elements(&self, fields: &mut Vec<F>) {
303 F::from(*self).to_field_elements(fields)
304 }
305}
306
307impl<F: FieldWitness> ToFieldElements<F> for u32 {
308 fn to_field_elements(&self, fields: &mut Vec<F>) {
309 F::from(*self).to_field_elements(fields)
310 }
311}
312
313impl<F: FieldWitness, T: ToFieldElements<F>> ToFieldElements<F> for PointEvaluations<T> {
314 fn to_field_elements(&self, fields: &mut Vec<F>) {
315 let Self { zeta, zeta_omega } = self;
316 zeta.to_field_elements(fields);
317 zeta_omega.to_field_elements(fields);
318 }
319}
320
321impl<F: FieldWitness, T: ToFieldElements<F>> ToFieldElements<F> for ProofEvaluations<T> {
322 fn to_field_elements(&self, fields: &mut Vec<F>) {
323 let Self {
324 public: _,
325 w,
326 z,
327 s,
328 coefficients,
329 generic_selector,
330 poseidon_selector,
331 complete_add_selector,
332 mul_selector,
333 emul_selector,
334 endomul_scalar_selector,
335 range_check0_selector,
336 range_check1_selector,
337 foreign_field_add_selector,
338 foreign_field_mul_selector,
339 xor_selector,
340 rot_selector,
341 lookup_aggregation,
342 lookup_table,
343 lookup_sorted,
344 runtime_lookup_table,
345 runtime_lookup_table_selector,
346 xor_lookup_selector,
347 lookup_gate_lookup_selector,
348 range_check_lookup_selector,
349 foreign_field_mul_lookup_selector,
350 } = self;
351
352 let mut push = |value: &T| {
353 value.to_field_elements(fields);
354 };
355
356 w.iter().for_each(&mut push);
357 coefficients.iter().for_each(&mut push);
358 push(z);
359 s.iter().for_each(&mut push);
360 push(generic_selector);
361 push(poseidon_selector);
362 push(complete_add_selector);
363 push(mul_selector);
364 push(emul_selector);
365 push(endomul_scalar_selector);
366 range_check0_selector.as_ref().map(&mut push);
367 range_check1_selector.as_ref().map(&mut push);
368 foreign_field_add_selector.as_ref().map(&mut push);
369 foreign_field_mul_selector.as_ref().map(&mut push);
370 xor_selector.as_ref().map(&mut push);
371 rot_selector.as_ref().map(&mut push);
372 lookup_aggregation.as_ref().map(&mut push);
373 lookup_table.as_ref().map(&mut push);
374 lookup_sorted.iter().for_each(|v| {
375 v.as_ref().map(&mut push);
376 });
377 runtime_lookup_table.as_ref().map(&mut push);
378 runtime_lookup_table_selector.as_ref().map(&mut push);
379 xor_lookup_selector.as_ref().map(&mut push);
380 lookup_gate_lookup_selector.as_ref().map(&mut push);
381 range_check_lookup_selector.as_ref().map(&mut push);
382 foreign_field_mul_lookup_selector.as_ref().map(&mut push);
383 }
384}
385
386impl<F: FieldWitness> ToFieldElements<F> for AllEvals<F> {
387 fn to_field_elements(&self, fields: &mut Vec<F>) {
388 let Self {
389 ft_eval1,
390 evals:
391 EvalsWithPublicInput {
392 evals,
393 public_input,
394 },
395 } = self;
396
397 public_input.to_field_elements(fields);
398 evals.to_field_elements(fields);
399 ft_eval1.to_field_elements(fields);
400 }
401}
402
403impl<F: FieldWitness> ToFieldElements<F> for &[AllEvals<F>] {
404 fn to_field_elements(&self, fields: &mut Vec<F>) {
405 self.iter().for_each(|e| e.to_field_elements(fields))
406 }
407}
408
409impl<F: FieldWitness> ToFieldElements<F> for EpochData<F> {
410 fn to_field_elements(&self, fields: &mut Vec<F>) {
411 let Self {
412 ledger:
413 EpochLedger {
414 hash,
415 total_currency,
416 },
417 seed,
418 start_checkpoint,
419 lock_checkpoint,
420 epoch_length,
421 } = self;
422
423 hash.to_field_elements(fields);
424 total_currency.to_field_elements(fields);
425 seed.to_field_elements(fields);
426 start_checkpoint.to_field_elements(fields);
427 lock_checkpoint.to_field_elements(fields);
428 epoch_length.to_field_elements(fields);
429 }
430}
431
432impl<F: FieldWitness> ToFieldElements<F> for v2::MinaBaseProtocolConstantsCheckedValueStableV1 {
433 fn to_field_elements(&self, fields: &mut Vec<F>) {
434 let Self {
435 k,
436 slots_per_epoch,
437 slots_per_sub_window,
438 grace_period_slots,
439 delta,
440 genesis_state_timestamp,
441 } = self;
442
443 k.as_u32().to_field_elements(fields);
444 slots_per_epoch.as_u32().to_field_elements(fields);
445 slots_per_sub_window.as_u32().to_field_elements(fields);
446 grace_period_slots.as_u32().to_field_elements(fields);
447 delta.as_u32().to_field_elements(fields);
448 genesis_state_timestamp.as_u64().to_field_elements(fields);
449 }
450}
451
452impl ToFieldElements<Fp> for super::block::BlockchainState {
453 fn to_field_elements(&self, fields: &mut Vec<Fp>) {
454 let Self {
455 staged_ledger_hash,
456 genesis_ledger_hash,
457 ledger_proof_statement,
458 timestamp,
459 body_reference,
460 } = self;
461
462 staged_ledger_hash.to_field_elements(fields);
463 genesis_ledger_hash.to_field_elements(fields);
464 ledger_proof_statement.to_field_elements(fields);
465 timestamp.as_u64().to_field_elements(fields);
466 body_reference.to_field_elements(fields);
467 }
468}
469
470impl ToFieldElements<Fp> for super::block::consensus::ConsensusState {
471 fn to_field_elements(&self, fields: &mut Vec<Fp>) {
472 let super::block::consensus::ConsensusState {
473 blockchain_length,
474 epoch_count,
475 min_window_density,
476 sub_window_densities,
477 last_vrf_output,
478 total_currency,
479 curr_global_slot_since_hard_fork:
480 super::block::consensus::GlobalSlot {
481 slot_number,
482 slots_per_epoch,
483 },
484 global_slot_since_genesis,
485 staking_epoch_data,
486 next_epoch_data,
487 has_ancestor_in_same_checkpoint_window,
488 block_stake_winner,
489 block_creator,
490 coinbase_receiver,
491 supercharge_coinbase,
492 } = self;
493
494 blockchain_length.as_u32().to_field_elements(fields);
495 epoch_count.as_u32().to_field_elements(fields);
496 min_window_density.as_u32().to_field_elements(fields);
497 fields.extend(sub_window_densities.iter().map(|w| Fp::from(w.as_u32())));
498 last_vrf_output.to_field_elements(fields);
499 total_currency.as_u64().to_field_elements(fields);
500 slot_number.to_field_elements(fields);
501 slots_per_epoch.to_field_elements(fields);
502 global_slot_since_genesis.as_u32().to_field_elements(fields);
503 staking_epoch_data.to_field_elements(fields);
504 next_epoch_data.to_field_elements(fields);
505 has_ancestor_in_same_checkpoint_window.to_field_elements(fields);
506 block_stake_winner.to_field_elements(fields);
507 block_creator.to_field_elements(fields);
508 coinbase_receiver.to_field_elements(fields);
509 supercharge_coinbase.to_field_elements(fields);
510 }
511}
512
513impl ToFieldElements<Fp> for super::block::ProtocolStateBody {
514 fn to_field_elements(&self, fields: &mut Vec<Fp>) {
515 let Self {
516 genesis_state_hash,
517 blockchain_state,
518 consensus_state,
519 constants,
520 } = self;
521
522 genesis_state_hash.to_field_elements(fields);
523 blockchain_state.to_field_elements(fields);
524 consensus_state.to_field_elements(fields);
525 constants.to_field_elements(fields);
526 }
527}
528
529impl ToFieldElements<Fp> for TokenId {
530 fn to_field_elements(&self, fields: &mut Vec<Fp>) {
531 let Self(token_id) = self;
532 token_id.to_field_elements(fields);
533 }
534}
535
536impl ToFieldElements<Fp> for CompressedPubKey {
537 fn to_field_elements(&self, fields: &mut Vec<Fp>) {
538 let Self { x, is_odd } = self;
539 x.to_field_elements(fields);
540 is_odd.to_field_elements(fields);
541 }
542}
543
544impl ToFieldElements<Fp> for mina_signer::Signature {
545 fn to_field_elements(&self, fields: &mut Vec<Fp>) {
546 let Self { rx, s } = self;
547
548 rx.to_field_elements(fields);
549 let s_bits = field_to_bits::<_, 255>(*s);
550 s_bits.to_field_elements(fields);
551 }
552}
553
554impl ToFieldElements<Fp> for mina_signer::PubKey {
555 fn to_field_elements(&self, fields: &mut Vec<Fp>) {
556 let GroupAffine::<Fp> { x, y, .. } = self.point();
557 x.to_field_elements(fields);
558 y.to_field_elements(fields);
559 }
560}
561
562impl ToFieldElements<Fp> for transaction_union_payload::TransactionUnion {
563 fn to_field_elements(&self, fields: &mut Vec<Fp>) {
564 use transaction_union_payload::{Body, Common, TransactionUnionPayload};
565
566 let Self {
567 payload:
568 TransactionUnionPayload {
569 common:
570 Common {
571 fee,
572 fee_token,
573 fee_payer_pk,
574 nonce,
575 valid_until,
576 memo,
577 },
578 body:
579 Body {
580 tag,
581 source_pk,
582 receiver_pk,
583 token_id,
584 amount,
585 },
586 },
587 signer,
588 signature,
589 } = self;
590
591 fee.to_field_elements(fields);
592 fee_token.to_field_elements(fields);
593 fee_payer_pk.to_field_elements(fields);
594 nonce.to_field_elements(fields);
595 valid_until.to_field_elements(fields);
596 memo.as_slice().to_field_elements(fields);
597 tag.to_untagged_bits().to_field_elements(fields);
598 source_pk.to_field_elements(fields);
599 receiver_pk.to_field_elements(fields);
600 token_id.to_field_elements(fields);
601 amount.to_field_elements(fields);
602 signer.to_field_elements(fields);
603 signature.to_field_elements(fields);
604 }
605}
606
607impl ToFieldElements<Fp> for pending_coinbase::StateStack {
608 fn to_field_elements(&self, fields: &mut Vec<Fp>) {
609 let Self { init, curr } = self;
610 init.to_field_elements(fields);
611 curr.to_field_elements(fields);
612 }
613}
614
615impl ToFieldElements<Fp> for pending_coinbase::Stack {
616 fn to_field_elements(&self, fields: &mut Vec<Fp>) {
617 let Self {
618 data: pending_coinbase::CoinbaseStack(data),
619 state,
620 } = self;
621
622 data.to_field_elements(fields);
623 state.to_field_elements(fields);
624 }
625}
626
627impl ToFieldElements<Fp> for TokenSymbol {
628 fn to_field_elements(&self, fields: &mut Vec<Fp>) {
629 let field: Fp = self.to_field();
630 field.to_field_elements(fields);
631 }
632}
633
634impl<F: FieldWitness> ToFieldElements<F> for crate::Timing {
636 fn to_field_elements(&self, fields: &mut Vec<F>) {
637 let TimingAsRecord {
638 is_timed,
639 initial_minimum_balance,
640 cliff_time,
641 cliff_amount,
642 vesting_period,
643 vesting_increment,
644 } = self.to_record();
645
646 F::from(is_timed).to_field_elements(fields);
647 F::from(initial_minimum_balance.as_u64()).to_field_elements(fields);
648 F::from(cliff_time.as_u32()).to_field_elements(fields);
649 F::from(cliff_amount.as_u64()).to_field_elements(fields);
650 F::from(vesting_period.as_u32()).to_field_elements(fields);
651 F::from(vesting_increment.as_u64()).to_field_elements(fields);
652 }
653}
654
655impl<F: FieldWitness> ToFieldElements<F> for crate::Permissions<crate::AuthRequired> {
656 fn to_field_elements(&self, fields: &mut Vec<F>) {
657 use crate::AuthOrVersion;
658
659 self.iter_as_bits(|bit| match bit {
660 AuthOrVersion::Auth(bit) => bit.to_field_elements(fields),
661 AuthOrVersion::Version(version) => version.to_field_elements(fields),
662 });
663 }
664}
665
666impl<F: FieldWitness> ToFieldElements<F> for crate::AuthRequired {
667 fn to_field_elements(&self, fields: &mut Vec<F>) {
668 let crate::AuthRequiredEncoded {
672 constant,
673 signature_necessary,
674 signature_sufficient,
675 } = self.encode();
676
677 [signature_sufficient, signature_necessary, constant].to_field_elements(fields);
678 }
679}
680
681impl ToFieldElements<Fp> for Box<Account> {
682 fn to_field_elements(&self, fields: &mut Vec<Fp>) {
683 let Account {
684 public_key,
685 token_id: TokenId(token_id),
686 token_symbol,
687 balance,
688 nonce,
689 receipt_chain_hash: ReceiptChainHash(receipt_chain_hash),
690 delegate,
691 voting_for: VotingFor(voting_for),
692 timing,
693 permissions,
694 zkapp,
695 } = &**self;
696
697 public_key.to_field_elements(fields);
699 token_id.to_field_elements(fields);
700 token_symbol.to_field_elements(fields);
701 balance.to_field_elements(fields);
702 nonce.to_field_elements(fields);
703 receipt_chain_hash.to_field_elements(fields);
704 let delegate = MyCow::borrow_or_else(delegate, CompressedPubKey::empty);
705 delegate.to_field_elements(fields);
706 voting_for.to_field_elements(fields);
707 timing.to_field_elements(fields);
708 permissions.to_field_elements(fields);
709 match zkapp.as_ref() {
710 Some(zkapp) => zkapp.hash(),
711 None => default_zkapp_hash(),
712 }
713 .to_field_elements(fields);
714 }
715}
716
717impl<F: FieldWitness> ToFieldElements<F> for crate::MerklePath {
718 fn to_field_elements(&self, fields: &mut Vec<F>) {
719 self.hash().to_field_elements(fields);
720 }
721}
722
723impl<F: FieldWitness, A: ToFieldElements<F>, B: ToFieldElements<F>> ToFieldElements<F> for (A, B) {
724 fn to_field_elements(&self, fields: &mut Vec<F>) {
725 let (a, b) = self;
726 a.to_field_elements(fields);
727 b.to_field_elements(fields);
728 }
729}
730
731impl<F: FieldWitness> ToFieldElements<F> for ReceiptChainHash {
732 fn to_field_elements(&self, fields: &mut Vec<F>) {
733 let Self(receipt_chain_hash) = self;
734 receipt_chain_hash.to_field_elements(fields);
735 }
736}
737
738impl<F: FieldWitness> ToFieldElements<F> for Sgn {
739 fn to_field_elements(&self, fields: &mut Vec<F>) {
740 let field: F = self.to_field();
741 field.to_field_elements(fields)
742 }
743}
744
745impl<F: FieldWitness, T: currency::Magnitude + ToFieldElements<F>> ToFieldElements<F>
746 for currency::Signed<T>
747{
748 fn to_field_elements(&self, fields: &mut Vec<F>) {
749 let Self { magnitude, sgn } = self;
750
751 magnitude.to_field_elements(fields);
752 sgn.to_field_elements(fields);
753 }
754}
755
756impl<F: FieldWitness> ToFieldElements<F> for PlonkVerificationKeyEvals<F> {
757 fn to_field_elements(&self, fields: &mut Vec<F>) {
758 let Self {
759 sigma,
760 coefficients,
761 generic,
762 psm,
763 complete_add,
764 mul,
765 emul,
766 endomul_scalar,
767 } = self;
768
769 sigma.iter().for_each(|s| s.to_field_elements(fields));
770 coefficients
771 .iter()
772 .for_each(|c| c.to_field_elements(fields));
773 generic.to_field_elements(fields);
774 psm.to_field_elements(fields);
775 complete_add.to_field_elements(fields);
776 mul.to_field_elements(fields);
777 emul.to_field_elements(fields);
778 endomul_scalar.to_field_elements(fields);
779 }
780}
781
782impl<F: FieldWitness, const N: usize> ToFieldElements<F> for crate::address::raw::Address<N> {
783 fn to_field_elements(&self, fields: &mut Vec<F>) {
784 let zero = F::zero();
785 let one = F::one();
786
787 fields.extend(
788 self.iter()
789 .map(|b| match b {
790 crate::Direction::Left => zero,
791 crate::Direction::Right => one,
792 })
793 .rev(),
794 );
795 }
796}
797
798impl<F: FieldWitness, T: ToFieldElements<F>> ToFieldElements<F> for &T {
800 fn to_field_elements(&self, fields: &mut Vec<F>) {
801 (*self).to_field_elements(fields);
802 }
803}
804
805impl<F: FieldWitness> ToFieldElements<F> for InnerCurve<F> {
806 fn to_field_elements(&self, fields: &mut Vec<F>) {
807 let GroupAffine::<F> { x, y, .. } = self.to_affine();
808 x.to_field_elements(fields);
809 y.to_field_elements(fields);
810 }
811}
812
813impl<F: FieldWitness> ToFieldElements<F> for Boolean {
814 fn to_field_elements(&self, fields: &mut Vec<F>) {
815 self.to_field::<F>().to_field_elements(fields);
816 }
817}
818
819impl<F: FieldWitness> ToFieldElements<F> for CircuitVar<Boolean> {
820 fn to_field_elements(&self, fields: &mut Vec<F>) {
821 self.as_boolean().to_field_elements(fields);
822 }
823}
824
825impl<F: FieldWitness> ToFieldElements<F> for CircuitVar<Sgn> {
826 fn to_field_elements(&self, fields: &mut Vec<F>) {
827 match self {
828 CircuitVar::Constant(_) => (),
829 CircuitVar::Var(var) => var.to_field_elements(fields),
830 }
831 }
832}
833
834impl ToFieldElements<Fp> for StepMainStatement {
835 fn to_field_elements(&self, fields: &mut Vec<Fp>) {
836 let Self {
837 proof_state:
838 StepMainProofState {
839 unfinalized_proofs,
840 messages_for_next_step_proof,
841 },
842 messages_for_next_wrap_proof,
843 } = self;
844
845 unfinalized_proofs.to_field_elements(fields);
846 messages_for_next_step_proof.to_field_elements(fields);
847 messages_for_next_wrap_proof.to_field_elements(fields);
848 }
849}
850
851impl ToFieldElements<Fp> for PerProofWitness {
852 fn to_field_elements(&self, fields: &mut Vec<Fp>) {
853 let Self {
854 app_state,
855 wrap_proof,
856 proof_state,
857 prev_proof_evals,
858 prev_challenges,
859 prev_challenge_polynomial_commitments,
860 hack_feature_flags,
861 } = self;
862
863 assert!(app_state.is_none());
864
865 let push_affine = |g: GroupAffine<Fp>, fields: &mut Vec<Fp>| {
866 let GroupAffine::<Fp> { x, y, .. } = g;
867 x.to_field_elements(fields);
868 y.to_field_elements(fields);
869 };
870
871 let push_affines = |slice: &[GroupAffine<Fp>], fields: &mut Vec<Fp>| {
872 slice.iter().copied().for_each(|g| push_affine(g, fields))
873 };
874
875 let ProverProof {
876 commitments:
877 ProverCommitments {
878 w_comm,
879 z_comm,
880 t_comm,
881 lookup: _,
882 },
883 proof:
884 OpeningProof {
885 lr,
886 delta,
887 z1,
888 z2,
889 sg,
890 },
891 evals: _,
892 ft_eval1: _,
893 prev_challenges: _,
894 } = wrap_proof;
895
896 for w in w_comm {
897 push_affines(&w.elems, fields);
898 }
899
900 push_affines(&z_comm.elems, fields);
901 push_affines(&t_comm.elems, fields);
902
903 for (a, b) in lr {
904 push_affine(*a, fields);
905 push_affine(*b, fields);
906 }
907
908 let shift = |f: Fq| <Fq as FieldWitness>::Shifting::of_field(f);
909
910 shift(*z1).to_field_elements(fields);
911 shift(*z2).to_field_elements(fields);
912
913 push_affines(&[*delta, *sg], fields);
914
915 let ProofState {
916 deferred_values:
917 DeferredValues {
918 plonk:
919 Plonk {
920 alpha,
921 beta,
922 gamma,
923 zeta,
924 zeta_to_srs_length,
925 zeta_to_domain_size,
926 perm,
927 lookup: _,
928 feature_flags: _,
929 },
930 combined_inner_product,
931 b,
932 xi,
933 bulletproof_challenges,
934 branch_data,
935 },
936 sponge_digest_before_evaluations,
937 messages_for_next_wrap_proof: _,
938 } = proof_state;
939
940 two_u64_to_field::<Fp>(alpha).to_field_elements(fields);
941 two_u64_to_field::<Fp>(beta).to_field_elements(fields);
942 two_u64_to_field::<Fp>(gamma).to_field_elements(fields);
943 two_u64_to_field::<Fp>(zeta).to_field_elements(fields);
944
945 zeta_to_srs_length.to_field_elements(fields);
946 zeta_to_domain_size.to_field_elements(fields);
947 perm.to_field_elements(fields);
948 match hack_feature_flags {
949 OptFlag::Maybe => {
950 let zeros: [u64; 10] = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
961 zeros.to_field_elements(fields);
962 }
963 OptFlag::Yes => unimplemented!(), OptFlag::No => {}
965 }
966
967 combined_inner_product.to_field_elements(fields);
968 b.to_field_elements(fields);
969 two_u64_to_field::<Fp>(xi).to_field_elements(fields);
970 bulletproof_challenges.to_field_elements(fields);
971
972 {
974 let v2::CompositionTypesBranchDataStableV1 {
975 proofs_verified,
976 domain_log2,
977 } = branch_data;
978 let proofs_verified = match proofs_verified {
980 v2::PicklesBaseProofsVerifiedStableV1::N0 => [Fp::zero(), Fp::zero()],
981 v2::PicklesBaseProofsVerifiedStableV1::N1 => [Fp::zero(), Fp::one()],
982 v2::PicklesBaseProofsVerifiedStableV1::N2 => [Fp::one(), Fp::one()],
983 };
984 let domain_log2: u64 = domain_log2.0.as_u8() as u64;
985
986 proofs_verified.to_field_elements(fields);
987 Fp::from(domain_log2).to_field_elements(fields);
988 }
989
990 four_u64_to_field::<Fp>(sponge_digest_before_evaluations)
991 .unwrap() .to_field_elements(fields);
993
994 let AllEvals {
995 ft_eval1,
996 evals:
997 EvalsWithPublicInput {
998 evals,
999 public_input,
1000 },
1001 } = prev_proof_evals;
1002
1003 public_input.to_field_elements(fields);
1004 evals.to_field_elements(fields);
1005 match hack_feature_flags {
1006 OptFlag::Maybe => {
1007 let zeros: [u64; 57] = [0; 57];
1010 zeros.to_field_elements(fields);
1011 }
1012 OptFlag::Yes => unimplemented!(), OptFlag::No => {}
1014 }
1015 ft_eval1.to_field_elements(fields);
1016 prev_challenges.to_field_elements(fields);
1017 push_affines(prev_challenge_polynomial_commitments, fields);
1018 }
1019}