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