github.com/consensys/gnark@v0.11.0/internal/generator/backend/template/zkpschemes/groth16/groth16.marshal.go.tmpl (about)

     1  import (
     2  	{{ template "import_curve" . }}
     3  	{{ template "import_pedersen" . }}
     4  	"github.com/consensys/gnark/internal/utils"
     5  	"github.com/consensys/gnark-crypto/utils/unsafe"
     6  	"io"
     7  )
     8  
     9  // WriteTo writes binary encoding of the Proof elements to writer
    10  // points are stored in compressed form Ar | Krs | Bs
    11  // use WriteRawTo(...) to encode the proof without point compression 
    12  func (proof *Proof) WriteTo(w io.Writer) (n int64, err error) {
    13  	return proof.writeTo(w, false)
    14  }
    15  
    16  // WriteRawTo writes binary encoding of the Proof elements to writer
    17  // points are stored in uncompressed form Ar | Krs | Bs
    18  // use WriteTo(...) to encode the proof with point compression 
    19  func (proof *Proof) WriteRawTo(w io.Writer) (n int64, err error) {
    20  	return proof.writeTo(w, true)
    21  }
    22  
    23  func (proof *Proof) writeTo(w io.Writer, raw bool) (int64, error) {
    24  	var enc *curve.Encoder
    25  	if raw {
    26  		enc = curve.NewEncoder(w, curve.RawEncoding())
    27  	} else {
    28  		enc = curve.NewEncoder(w)
    29  	}
    30  
    31  	if err := enc.Encode(&proof.Ar); err != nil {
    32  		return enc.BytesWritten(), err
    33  	}
    34  	if err := enc.Encode(&proof.Bs); err != nil {
    35  		return enc.BytesWritten(), err
    36  	}
    37  	if err := enc.Encode(&proof.Krs); err != nil {
    38  		return enc.BytesWritten(), err
    39  	}
    40  	if err := enc.Encode(proof.Commitments); err != nil {
    41  		return enc.BytesWritten(), err
    42  	}
    43  	if err := enc.Encode(&proof.CommitmentPok); err != nil {
    44  		return enc.BytesWritten(), err
    45  	}
    46  
    47  	return enc.BytesWritten(), nil
    48  } 
    49  
    50  
    51  // ReadFrom attempts to decode a Proof from reader
    52  // Proof must be encoded through WriteTo (compressed) or WriteRawTo (uncompressed) 
    53  func (proof *Proof) ReadFrom(r io.Reader) (n int64, err error) {
    54  
    55  	dec := curve.NewDecoder(r)
    56  
    57  	if err := dec.Decode(&proof.Ar); err != nil {
    58  		return dec.BytesRead(), err
    59  	}
    60  	if err := dec.Decode(&proof.Bs); err != nil {
    61  		return dec.BytesRead(), err
    62  	}
    63  	if err := dec.Decode(&proof.Krs); err != nil {
    64  		return dec.BytesRead(), err
    65  	}
    66  	if err := dec.Decode(&proof.Commitments); err != nil {
    67  		return dec.BytesRead(), err
    68  	}
    69  	if err := dec.Decode(&proof.CommitmentPok); err != nil {
    70  		return dec.BytesRead(), err
    71  	}
    72  
    73  	return dec.BytesRead(), nil
    74  }
    75  
    76  // WriteTo writes binary encoding of the key elements to writer
    77  // points are compressed
    78  // use WriteRawTo(...) to encode the key without point compression 
    79  func (vk *VerifyingKey) WriteTo(w io.Writer) (n int64, err error) {
    80  	return vk.writeTo(w, false)
    81  }
    82  
    83  // WriteRawTo writes binary encoding of the key elements to writer
    84  // points are not compressed
    85  // use WriteTo(...) to encode the key with point compression 
    86  func (vk *VerifyingKey) WriteRawTo(w io.Writer) (n int64, err error) {
    87  	return vk.writeTo(w, true)
    88  }
    89  
    90  // writeTo serialization format: 
    91  // follows bellman format: 
    92  // https://github.com/zkcrypto/bellman/blob/fa9be45588227a8c6ec34957de3f68705f07bd92/src/groth16/mod.rs#L143
    93  // [α]1,[β]1,[β]2,[γ]2,[δ]1,[δ]2,uint32(len(Kvk)),[Kvk]1
    94  func (vk *VerifyingKey) writeTo(w io.Writer, raw bool) (int64, error) {
    95  	var enc *curve.Encoder
    96  	if raw {
    97  		enc = curve.NewEncoder(w, curve.RawEncoding())
    98  	} else {
    99  		enc = curve.NewEncoder(w)
   100  	}
   101  	if vk.PublicAndCommitmentCommitted == nil {
   102  		vk.PublicAndCommitmentCommitted = [][]int{} // only matters in tests
   103  	}
   104  	toEncode := []interface{}{
   105  		// [α]1,[β]1,[β]2,[γ]2,[δ]1,[δ]2
   106  		&vk.G1.Alpha,
   107  		&vk.G1.Beta,
   108  		&vk.G2.Beta,
   109  		&vk.G2.Gamma,
   110  		&vk.G1.Delta,
   111  		&vk.G2.Delta,
   112  		// uint32(len(Kvk)),[Kvk]1
   113  		vk.G1.K,
   114  		utils.IntSliceSliceToUint64SliceSlice(vk.PublicAndCommitmentCommitted),
   115  		uint32(len(vk.CommitmentKeys)),
   116  	}
   117  	for _, v := range toEncode {
   118  		if err := enc.Encode(v); err != nil {
   119  			return enc.BytesWritten(), err
   120  		}
   121  	}
   122  	var n int64
   123  	for i := range vk.CommitmentKeys {
   124  		var (
   125  			m   int64
   126  			err error
   127  		)
   128  		if raw {
   129  			m, err = vk.CommitmentKeys[i].WriteRawTo(w)
   130  		} else {
   131  			m, err = vk.CommitmentKeys[i].WriteTo(w)
   132  		}
   133  		n += m
   134  		if err != nil {
   135  			return n + enc.BytesWritten(), err
   136  		}
   137  	}
   138  	return n + enc.BytesWritten(), nil
   139  }
   140  
   141  // ReadFrom attempts to decode a VerifyingKey from reader
   142  // VerifyingKey must be encoded through WriteTo (compressed) or WriteRawTo (uncompressed) 
   143  // serialization format:
   144  // https://github.com/zkcrypto/bellman/blob/fa9be45588227a8c6ec34957de3f68705f07bd92/src/groth16/mod.rs#L143
   145  // [α]1,[β]1,[β]2,[γ]2,[δ]1,[δ]2,uint32(len(Kvk)),[Kvk]1
   146  func (vk *VerifyingKey) ReadFrom(r io.Reader) (int64, error) {
   147  	return vk.readFrom(r, false)
   148  }
   149  
   150  // UnsafeReadFrom has the same behavior as ReadFrom, except that it will not check that decode points
   151  // are on the curve and in the correct subgroup. 
   152  func (vk *VerifyingKey) UnsafeReadFrom(r io.Reader) (int64, error) {
   153  	return vk.readFrom(r, true)
   154  }
   155  
   156  func (vk *VerifyingKey) readFrom(r io.Reader, raw bool) (int64, error) {
   157  	var dec *curve.Decoder
   158  	if raw {
   159  		dec = curve.NewDecoder(r, curve.NoSubgroupChecks())
   160  	} else {
   161  		dec = curve.NewDecoder(r)
   162  	}
   163  
   164  	var publicCommitted [][]uint64
   165  	var nbCommitments uint32
   166  
   167  	toDecode := []interface{}{
   168  		// [α]1,[β]1,[β]2,[γ]2,[δ]1,[δ]2
   169  		&vk.G1.Alpha,
   170  		&vk.G1.Beta,
   171  		&vk.G2.Beta,
   172  		&vk.G2.Gamma,
   173  		&vk.G1.Delta,
   174  		&vk.G2.Delta,
   175  		// uint32(len(Kvk)),[Kvk]1
   176  		&vk.G1.K,
   177  		&publicCommitted,
   178  		&nbCommitments,
   179  	}
   180  
   181  	for _, v := range toDecode {
   182  		if err := dec.Decode(v); err != nil {
   183  			return dec.BytesRead(), err
   184  		}
   185  	}
   186  
   187  	vk.PublicAndCommitmentCommitted = utils.Uint64SliceSliceToIntSliceSlice(publicCommitted)
   188  	
   189  	vk.CommitmentKeys = make([]pedersen.VerifyingKey, nbCommitments)
   190  	var n int64
   191  	for i := range vk.CommitmentKeys {
   192  		var (
   193  			m   int64
   194  			err error
   195  		)
   196  		if raw {
   197  			m, err = vk.CommitmentKeys[i].UnsafeReadFrom(r)
   198  		} else {
   199  			m, err = vk.CommitmentKeys[i].ReadFrom(r)
   200  		}
   201  		n += m
   202  		if err != nil {
   203  			return n + dec.BytesRead(), err
   204  		}
   205  	}
   206  
   207  	// recompute vk.e (e(α, β)) and  -[δ]2, -[γ]2
   208  	if err := vk.Precompute(); err != nil {
   209  		return n + dec.BytesRead(), err
   210  	}
   211  
   212  	return n + dec.BytesRead(), nil
   213  }
   214  
   215  
   216  
   217  // WriteTo writes binary encoding of the key elements to writer
   218  // points are compressed
   219  // use WriteRawTo(...) to encode the key without point compression 
   220  func (pk *ProvingKey) WriteTo(w io.Writer) (n int64, err error) {
   221  	return pk.writeTo(w, false)
   222  }
   223  
   224  
   225  // WriteRawTo writes binary encoding of the key elements to writer
   226  // points are not compressed
   227  // use WriteTo(...) to encode the key with point compression 
   228  func (pk *ProvingKey) WriteRawTo(w io.Writer) (n int64, err error) {
   229  	return pk.writeTo(w, true)
   230  }
   231  
   232  func (pk *ProvingKey) writeTo(w io.Writer, raw bool) (int64, error) {
   233  	n, err := pk.Domain.WriteTo(w)
   234  	if err != nil {
   235  		return n, err 
   236  	}
   237  
   238  	var enc *curve.Encoder
   239  	if raw {
   240  		enc = curve.NewEncoder(w, curve.RawEncoding())
   241  	} else {
   242  		enc = curve.NewEncoder(w)
   243  	}
   244  	nbWires := uint64(len(pk.InfinityA))
   245  	
   246  	toEncode := []interface{}{
   247  		&pk.G1.Alpha,
   248  		&pk.G1.Beta,
   249  		&pk.G1.Delta,
   250  		pk.G1.A,
   251  		pk.G1.B,
   252  		pk.G1.Z,
   253  		pk.G1.K,
   254  		&pk.G2.Beta,
   255  		&pk.G2.Delta,
   256  		pk.G2.B,
   257  		nbWires,
   258  		pk.NbInfinityA,
   259  		pk.NbInfinityB,
   260  		pk.InfinityA,
   261  		pk.InfinityB,
   262  		uint32(len(pk.CommitmentKeys)),
   263  	}
   264  
   265  	for _, v := range toEncode {
   266  		if err := enc.Encode(v); err != nil {
   267  			return n + enc.BytesWritten(), err
   268  		}
   269  	}
   270  
   271  	for i := range pk.CommitmentKeys {
   272  		var (
   273  			n2  int64
   274  			err error
   275  		)
   276  		if raw {
   277  			n2, err = pk.CommitmentKeys[i].WriteRawTo(w)
   278  		} else {
   279  			n2, err = pk.CommitmentKeys[i].WriteTo(w)
   280  		}
   281  
   282  		n += n2
   283  		if err != nil {
   284  			return n + enc.BytesWritten(), err
   285  		}
   286  	}	
   287  
   288  	return n + enc.BytesWritten(), nil
   289  
   290  }
   291  
   292  // ReadFrom attempts to decode a ProvingKey from reader
   293  // ProvingKey must be encoded through WriteTo (compressed) or WriteRawTo (uncompressed) 
   294  // note that we don't check that the points are on the curve or in the correct subgroup at this point
   295  func (pk *ProvingKey) ReadFrom(r io.Reader) (int64, error) {
   296  	return pk.readFrom(r)
   297  }
   298  
   299  
   300  // UnsafeReadFrom behaves like ReadFrom excepts it doesn't check if the decoded points are on the curve
   301  // or in the correct subgroup
   302  func (pk *ProvingKey) UnsafeReadFrom(r io.Reader) (int64, error) {
   303  	return pk.readFrom(r, curve.NoSubgroupChecks())
   304  }
   305  
   306  func (pk *ProvingKey) readFrom(r io.Reader, decOptions ...func(*curve.Decoder)) (int64, error) {
   307  	n, err := pk.Domain.ReadFrom(r)
   308  	if err != nil {
   309  		return n, err
   310  	}
   311  
   312  	dec := curve.NewDecoder(r, decOptions...)
   313  
   314  	var nbWires uint64 
   315  	var nbCommitments uint32
   316  
   317  	toDecode := []interface{}{
   318  		&pk.G1.Alpha,
   319  		&pk.G1.Beta,
   320  		&pk.G1.Delta,
   321  		&pk.G1.A,
   322  		&pk.G1.B,
   323  		&pk.G1.Z,
   324  		&pk.G1.K,
   325  		&pk.G2.Beta,
   326  		&pk.G2.Delta,
   327  		&pk.G2.B,
   328  		&nbWires, 
   329  		&pk.NbInfinityA,
   330  		&pk.NbInfinityB,
   331  	}
   332  
   333  	for _, v := range toDecode {
   334  		if err := dec.Decode(v); err != nil {
   335  			return n + dec.BytesRead(), err
   336  		}
   337  	}
   338  	pk.InfinityA = make([]bool, nbWires)
   339  	pk.InfinityB = make([]bool, nbWires)
   340  
   341  	if err := dec.Decode(&pk.InfinityA); err != nil {
   342  		return n + dec.BytesRead(), err
   343  	}
   344  	if err := dec.Decode(&pk.InfinityB); err != nil {
   345  		return n + dec.BytesRead(), err
   346  	}
   347  	if err := dec.Decode(&nbCommitments); err != nil {
   348  		return n + dec.BytesRead(), err
   349  	}
   350  
   351  	pk.CommitmentKeys = make([]pedersen.ProvingKey, nbCommitments)
   352  	for i := range pk.CommitmentKeys {
   353  		n2, err := pk.CommitmentKeys[i].ReadFrom(r)
   354  		n += n2
   355  		if err != nil {
   356  			return n, err
   357  		}
   358  	}
   359  
   360  	return n + dec.BytesRead(), nil
   361  }
   362  
   363  
   364  // WriteDump behaves like WriteRawTo, excepts, the slices of points are "dumped" using gnark-crypto/utils/unsafe
   365  // Output is compatible with ReadDump, with the caveat that, not only the points are not checked for 
   366  // correctness, but the raw bytes are platform dependent (endianness, etc.)
   367  func (pk *ProvingKey) WriteDump(w io.Writer) error {
   368  	// it behaves like WriteRawTo, excepts, the slices of points are "dumped" using gnark-crypto/utils/unsafe
   369  
   370  	// start by writing an unsafe marker to fail early.
   371  	if err := unsafe.WriteMarker(w); err != nil {
   372  		return err
   373  	}
   374  	
   375  	if _, err := pk.Domain.WriteTo(w); err != nil {
   376  		return err 
   377  	}
   378  
   379  	enc := curve.NewEncoder(w, curve.RawEncoding())
   380  	nbWires := uint64(len(pk.InfinityA))
   381  	
   382  	toEncode := []interface{}{
   383  		&pk.G1.Alpha,
   384  		&pk.G1.Beta,
   385  		&pk.G1.Delta,
   386  		// pk.G1.A,
   387  		// pk.G1.B,
   388  		// pk.G1.Z,
   389  		// pk.G1.K,
   390  		&pk.G2.Beta,
   391  		&pk.G2.Delta,
   392  		// pk.G2.B,
   393  		nbWires,
   394  		pk.NbInfinityA,
   395  		pk.NbInfinityB,
   396  		pk.InfinityA,
   397  		pk.InfinityB,
   398  		uint32(len(pk.CommitmentKeys)),
   399  	}
   400  
   401  	for _, v := range toEncode {
   402  		if err := enc.Encode(v); err != nil {
   403  			return err
   404  		}
   405  	}
   406  
   407  	// dump slices of points
   408  	if err := unsafe.WriteSlice(w, pk.G1.A); err != nil {
   409  		return err
   410  	}
   411  	if err := unsafe.WriteSlice(w, pk.G1.B); err != nil {
   412  		return err
   413  	}
   414  	if err := unsafe.WriteSlice(w, pk.G1.Z); err != nil {
   415  		return err
   416  	}
   417  	if err := unsafe.WriteSlice(w, pk.G1.K); err != nil {
   418  		return err
   419  	}
   420  	if err := unsafe.WriteSlice(w, pk.G2.B); err != nil {
   421  		return err
   422  	}
   423  
   424  	for i := range pk.CommitmentKeys {
   425  		if err := unsafe.WriteSlice(w, pk.CommitmentKeys[i].Basis); err != nil {
   426  			return err
   427  		}
   428  		if err := unsafe.WriteSlice(w, pk.CommitmentKeys[i].BasisExpSigma); err != nil {
   429  			return err
   430  		}
   431  	}	
   432  
   433  	return  nil
   434  }
   435  
   436  // ReadDump reads a ProvingKey from a dump written by WriteDump.
   437  // This is platform dependent and very unsafe (no checks, no endianness translation, etc.)
   438  func (pk *ProvingKey) ReadDump(r io.Reader) error {
   439  	// read the marker to fail early in case of malformed input
   440  	if err := unsafe.ReadMarker(r); err != nil {
   441  		return err
   442  	}
   443  
   444  	if _, err := pk.Domain.ReadFrom(r); err != nil {
   445  		return err 
   446  	}
   447  
   448  	dec := curve.NewDecoder(r, curve.NoSubgroupChecks())
   449  
   450  	var nbWires uint64 
   451  	var nbCommitments uint32
   452  
   453  	toDecode := []interface{}{
   454  		&pk.G1.Alpha,
   455  		&pk.G1.Beta,
   456  		&pk.G1.Delta,
   457  		// &pk.G1.A,
   458  		// &pk.G1.B,
   459  		// &pk.G1.Z,
   460  		// &pk.G1.K,
   461  		&pk.G2.Beta,
   462  		&pk.G2.Delta,
   463  		// &pk.G2.B,
   464  		&nbWires, 
   465  		&pk.NbInfinityA,
   466  		&pk.NbInfinityB,
   467  	}
   468  
   469  	for _, v := range toDecode {
   470  		if err := dec.Decode(v); err != nil {
   471  			return err
   472  		}
   473  	}
   474  	pk.InfinityA = make([]bool, nbWires)
   475  	pk.InfinityB = make([]bool, nbWires)
   476  
   477  	if err := dec.Decode(&pk.InfinityA); err != nil {
   478  		return err
   479  	}
   480  	if err := dec.Decode(&pk.InfinityB); err != nil {
   481  		return err
   482  	}
   483  	if err := dec.Decode(&nbCommitments); err != nil {
   484  		return err
   485  	}
   486  
   487  	// read slices of points
   488  	var err error
   489  	pk.G1.A, _, err = unsafe.ReadSlice[[]curve.G1Affine](r)
   490  	if err != nil {
   491  		return err
   492  	}
   493  	pk.G1.B, _, err = unsafe.ReadSlice[[]curve.G1Affine](r)
   494  	if err != nil {
   495  		return err
   496  	}
   497  	pk.G1.Z, _, err = unsafe.ReadSlice[[]curve.G1Affine](r)
   498  	if err != nil {
   499  		return err
   500  	}
   501  	pk.G1.K, _, err = unsafe.ReadSlice[[]curve.G1Affine](r)
   502  	if err != nil {
   503  		return err
   504  	}
   505  	pk.G2.B, _, err = unsafe.ReadSlice[[]curve.G2Affine](r)
   506  	if err != nil {
   507  		return err
   508  	}
   509  
   510  	pk.CommitmentKeys = make([]pedersen.ProvingKey, nbCommitments)
   511  	for i := range pk.CommitmentKeys {
   512  		pk.CommitmentKeys[i].Basis, _, err = unsafe.ReadSlice[[]curve.G1Affine](r)
   513  		if err != nil {
   514  			return err
   515  		}
   516  		pk.CommitmentKeys[i].BasisExpSigma, _, err = unsafe.ReadSlice[[]curve.G1Affine](r)
   517  		if err != nil {
   518  			return err
   519  		}
   520  	}
   521  
   522  	return nil
   523  
   524  }