@@ -3,14 +3,19 @@ use std::io::{Read, Write};
3
3
use std:: path:: Path ;
4
4
5
5
use anyhow:: { ensure, Result } ;
6
+ use bellperson:: groth16:: aggregate:: AggregateVersion ;
7
+ use blstrs:: Scalar as Fr ;
6
8
7
9
use filecoin_proofs_v1:: types:: {
8
10
EmptySectorUpdateEncoded , EmptySectorUpdateProof , MerkleTreeTrait , PartitionProof ,
9
- SectorUpdateConfig ,
11
+ SectorUpdateConfig , SectorUpdateProofInputs , TreeRHasher ,
10
12
} ;
11
- use filecoin_proofs_v1:: { with_shape, TreeRHasher } ;
13
+ use filecoin_proofs_v1:: with_shape;
12
14
13
- use crate :: { types:: PartitionProofBytes , Commitment , PieceInfo , RegisteredUpdateProof } ;
15
+ use crate :: {
16
+ types:: PartitionProofBytes , AggregateSnarkProof , Commitment , PieceInfo ,
17
+ RegisteredAggregationProof , RegisteredUpdateProof ,
18
+ } ;
14
19
15
20
fn empty_sector_update_encode_into_inner < Tree : ' static + MerkleTreeTrait < Hasher = TreeRHasher > > (
16
21
registered_proof : RegisteredUpdateProof ,
@@ -620,3 +625,173 @@ pub fn verify_empty_sector_update_proof(
620
625
comm_d_new,
621
626
)
622
627
}
628
+
629
+ /// Given a `registered_proof` type and a list of sector update proofs, this method aggregates
630
+ /// those proofs (naively padding the count if necessary up to a power of 2) and
631
+ /// returns the aggregate proof bytes.
632
+ ///
633
+ /// # Arguments
634
+ ///
635
+ /// * `registered_proof` - Selected sector update operation.
636
+ /// * `registered_aggregation` - Aggregation proof types; note that this method only supports SnarkPackV2+.
637
+ /// * `sector_update_inputs` - Ordered list of input commitments used to generate the individual sector update proofs.
638
+ /// * `sector_update_proofs` - Ordered list of sector update proofs.
639
+ ///
640
+ /// Returns aggregate of zk-SNARK proofs in [`AggregateSnarkProof`].
641
+ pub fn aggregate_empty_sector_update_proofs (
642
+ registered_proof : RegisteredUpdateProof ,
643
+ registered_aggregation : RegisteredAggregationProof ,
644
+ sector_update_inputs : & [ SectorUpdateProofInputs ] ,
645
+ sector_update_proofs : & [ filecoin_proofs_v1:: types:: EmptySectorUpdateProof ] ,
646
+ ) -> Result < AggregateSnarkProof > {
647
+ ensure ! (
648
+ registered_proof. major_version( ) == 1 ,
649
+ "unusupported version"
650
+ ) ;
651
+
652
+ ensure ! (
653
+ registered_aggregation == RegisteredAggregationProof :: SnarkPackV2 ,
654
+ "unsupported aggregation or registered proof version"
655
+ ) ;
656
+
657
+ let aggregate_version = AggregateVersion :: V2 ;
658
+
659
+ with_shape ! (
660
+ u64 :: from( registered_proof. sector_size( ) ) ,
661
+ aggregate_empty_sector_update_proofs_inner,
662
+ registered_proof,
663
+ sector_update_inputs,
664
+ sector_update_proofs,
665
+ aggregate_version,
666
+ )
667
+ }
668
+
669
+ fn aggregate_empty_sector_update_proofs_inner <
670
+ Tree : ' static + MerkleTreeTrait < Hasher = TreeRHasher > ,
671
+ > (
672
+ registered_proof : RegisteredUpdateProof ,
673
+ sector_update_inputs : & [ SectorUpdateProofInputs ] ,
674
+ sector_update_proofs : & [ EmptySectorUpdateProof ] ,
675
+ aggregate_version : AggregateVersion ,
676
+ ) -> Result < AggregateSnarkProof > {
677
+ let config = registered_proof. as_v1_config ( ) ;
678
+
679
+ filecoin_proofs_v1:: aggregate_empty_sector_update_proofs :: < Tree > (
680
+ & config,
681
+ sector_update_proofs,
682
+ sector_update_inputs,
683
+ aggregate_version,
684
+ )
685
+ }
686
+
687
+ /// Given the specified arguments, this method returns the inputs that were used to
688
+ /// generate the sector update proof. This can be useful for proof aggregation, as verification
689
+ /// requires these inputs.
690
+ ///
691
+ /// This method allows them to be retrieved when needed, rather than storing them for
692
+ /// some amount of time.
693
+ ///
694
+ /// # Arguments
695
+ ///
696
+ /// * `registered_proof` - Selected sector update proof operation.
697
+ /// * `comm_r_old` - A commitment to a sector's previous replica.
698
+ /// * `comm_r_new` - A commitment to a sector's current replica.
699
+ /// * `comm_d_new` - A commitment to a sector's current data.
700
+ ///
701
+ /// Returns the inputs that were used to generate seal proof.
702
+ pub fn get_sector_update_inputs (
703
+ registered_proof : RegisteredUpdateProof ,
704
+ comm_r_old : Commitment ,
705
+ comm_r_new : Commitment ,
706
+ comm_d_new : Commitment ,
707
+ ) -> Result < Vec < Vec < Fr > > > {
708
+ ensure ! (
709
+ registered_proof. major_version( ) == 1 ,
710
+ "unusupported version"
711
+ ) ;
712
+
713
+ with_shape ! (
714
+ u64 :: from( registered_proof. sector_size( ) ) ,
715
+ get_sector_update_inputs_inner,
716
+ registered_proof,
717
+ comm_r_old,
718
+ comm_r_new,
719
+ comm_d_new,
720
+ )
721
+ }
722
+
723
+ fn get_sector_update_inputs_inner < Tree : ' static + MerkleTreeTrait < Hasher = TreeRHasher > > (
724
+ registered_proof : RegisteredUpdateProof ,
725
+ comm_r_old : Commitment ,
726
+ comm_r_new : Commitment ,
727
+ comm_d_new : Commitment ,
728
+ ) -> Result < Vec < Vec < Fr > > > {
729
+ let config = registered_proof. as_v1_config ( ) ;
730
+
731
+ filecoin_proofs_v1:: get_sector_update_inputs :: < Tree > (
732
+ & config, comm_r_old, comm_r_new, comm_d_new,
733
+ )
734
+ }
735
+
736
+ /// Given a `registered_proof`, an aggregate proof, a list of proofs and a combined and flattened
737
+ /// list of sector update public inputs, this method verifies the aggregate empty sector update proof.
738
+ ///
739
+ /// # Arguments
740
+ ///
741
+ /// * `registered_proof` - Selected seal operation.
742
+ /// * `registered_aggregation` - Aggregation proof types.
743
+ /// * `aggregate_proof_bytes` - The returned aggregate proof from [`aggregate_empty_sector_update_proofs`].
744
+ /// * `inputs` - Ordered list of sector update input commitments.
745
+ /// * `sector_update_inputs` - A flattened/combined and ordered list of all public inputs, which must match
746
+ /// the ordering of the sector update proofs when aggregated.
747
+ ///
748
+ /// Returns true if proof is validated.
749
+ pub fn verify_aggregate_empty_sector_update_proofs (
750
+ registered_proof : RegisteredUpdateProof ,
751
+ registered_aggregation : RegisteredAggregationProof ,
752
+ aggregate_proof_bytes : AggregateSnarkProof ,
753
+ inputs : & [ SectorUpdateProofInputs ] ,
754
+ sector_update_inputs : Vec < Vec < Fr > > ,
755
+ ) -> Result < bool > {
756
+ ensure ! (
757
+ registered_proof. major_version( ) == 1 ,
758
+ "unusupported version"
759
+ ) ;
760
+
761
+ ensure ! (
762
+ registered_aggregation == RegisteredAggregationProof :: SnarkPackV2 ,
763
+ "unsupported aggregation or registered proof version"
764
+ ) ;
765
+
766
+ let aggregate_version = AggregateVersion :: V2 ;
767
+
768
+ with_shape ! (
769
+ u64 :: from( registered_proof. sector_size( ) ) ,
770
+ verify_aggregate_empty_sector_update_proofs_inner,
771
+ registered_proof,
772
+ aggregate_proof_bytes,
773
+ inputs,
774
+ sector_update_inputs,
775
+ aggregate_version,
776
+ )
777
+ }
778
+
779
+ fn verify_aggregate_empty_sector_update_proofs_inner <
780
+ Tree : ' static + MerkleTreeTrait < Hasher = TreeRHasher > ,
781
+ > (
782
+ registered_proof : RegisteredUpdateProof ,
783
+ aggregate_proof_bytes : AggregateSnarkProof ,
784
+ inputs : & [ SectorUpdateProofInputs ] ,
785
+ sector_update_inputs : Vec < Vec < Fr > > ,
786
+ aggregate_version : AggregateVersion ,
787
+ ) -> Result < bool > {
788
+ let config = registered_proof. as_v1_config ( ) ;
789
+
790
+ filecoin_proofs_v1:: verify_aggregate_sector_update_proofs :: < Tree > (
791
+ & config,
792
+ aggregate_proof_bytes,
793
+ inputs,
794
+ sector_update_inputs,
795
+ aggregate_version,
796
+ )
797
+ }
0 commit comments