github.com/ethereum/go-ethereum@v1.16.1/crypto/kzg4844/kzg4844_ckzg_cgo.go (about)

     1  // Copyright 2023 The go-ethereum Authors
     2  // This file is part of the go-ethereum library.
     3  //
     4  // The go-ethereum library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The go-ethereum library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  //go:build ckzg && !nacl && !js && !wasip1 && cgo && !gofuzz
    18  
    19  package kzg4844
    20  
    21  import (
    22  	"encoding/json"
    23  	"errors"
    24  	"sync"
    25  
    26  	gokzg4844 "github.com/crate-crypto/go-eth-kzg"
    27  	ckzg4844 "github.com/ethereum/c-kzg-4844/v2/bindings/go"
    28  	"github.com/ethereum/go-ethereum/common/hexutil"
    29  )
    30  
    31  // ckzgAvailable signals whether the library was compiled into Geth.
    32  const ckzgAvailable = true
    33  
    34  // ckzgIniter ensures that we initialize the KZG library once before using it.
    35  var ckzgIniter sync.Once
    36  
    37  // ckzgInit initializes the KZG library with the provided trusted setup.
    38  func ckzgInit() {
    39  	config, err := content.ReadFile("trusted_setup.json")
    40  	if err != nil {
    41  		panic(err)
    42  	}
    43  	params := new(gokzg4844.JSONTrustedSetup)
    44  	if err = json.Unmarshal(config, params); err != nil {
    45  		panic(err)
    46  	}
    47  	if err = gokzg4844.CheckTrustedSetupIsWellFormed(params); err != nil {
    48  		panic(err)
    49  	}
    50  	g1Lag := make([]byte, len(params.SetupG1Lagrange)*(len(params.SetupG1Lagrange[0])-2)/2)
    51  	for i, g1 := range params.SetupG1Lagrange {
    52  		copy(g1Lag[i*(len(g1)-2)/2:], hexutil.MustDecode(g1))
    53  	}
    54  	g1s := make([]byte, len(params.SetupG1Monomial)*(len(params.SetupG1Monomial[0])-2)/2)
    55  	for i, g1 := range params.SetupG1Monomial {
    56  		copy(g1s[i*(len(g1)-2)/2:], hexutil.MustDecode(g1))
    57  	}
    58  	g2s := make([]byte, len(params.SetupG2)*(len(params.SetupG2[0])-2)/2)
    59  	for i, g2 := range params.SetupG2 {
    60  		copy(g2s[i*(len(g2)-2)/2:], hexutil.MustDecode(g2))
    61  	}
    62  	// The last parameter determines the multiplication table, see https://notes.ethereum.org/@jtraglia/windowed_multiplications
    63  	// I think 6 is an decent compromise between size and speed
    64  	if err = ckzg4844.LoadTrustedSetup(g1s, g1Lag, g2s, 6); err != nil {
    65  		panic(err)
    66  	}
    67  }
    68  
    69  // ckzgBlobToCommitment creates a small commitment out of a data blob.
    70  func ckzgBlobToCommitment(blob *Blob) (Commitment, error) {
    71  	ckzgIniter.Do(ckzgInit)
    72  
    73  	commitment, err := ckzg4844.BlobToKZGCommitment((*ckzg4844.Blob)(blob))
    74  	if err != nil {
    75  		return Commitment{}, err
    76  	}
    77  	return (Commitment)(commitment), nil
    78  }
    79  
    80  // ckzgComputeProof computes the KZG proof at the given point for the polynomial
    81  // represented by the blob.
    82  func ckzgComputeProof(blob *Blob, point Point) (Proof, Claim, error) {
    83  	ckzgIniter.Do(ckzgInit)
    84  
    85  	proof, claim, err := ckzg4844.ComputeKZGProof((*ckzg4844.Blob)(blob), (ckzg4844.Bytes32)(point))
    86  	if err != nil {
    87  		return Proof{}, Claim{}, err
    88  	}
    89  	return (Proof)(proof), (Claim)(claim), nil
    90  }
    91  
    92  // ckzgVerifyProof verifies the KZG proof that the polynomial represented by the blob
    93  // evaluated at the given point is the claimed value.
    94  func ckzgVerifyProof(commitment Commitment, point Point, claim Claim, proof Proof) error {
    95  	ckzgIniter.Do(ckzgInit)
    96  
    97  	valid, err := ckzg4844.VerifyKZGProof((ckzg4844.Bytes48)(commitment), (ckzg4844.Bytes32)(point), (ckzg4844.Bytes32)(claim), (ckzg4844.Bytes48)(proof))
    98  	if err != nil {
    99  		return err
   100  	}
   101  	if !valid {
   102  		return errors.New("invalid proof")
   103  	}
   104  	return nil
   105  }
   106  
   107  // ckzgComputeBlobProof returns the KZG proof that is used to verify the blob against
   108  // the commitment.
   109  //
   110  // This method does not verify that the commitment is correct with respect to blob.
   111  func ckzgComputeBlobProof(blob *Blob, commitment Commitment) (Proof, error) {
   112  	ckzgIniter.Do(ckzgInit)
   113  
   114  	proof, err := ckzg4844.ComputeBlobKZGProof((*ckzg4844.Blob)(blob), (ckzg4844.Bytes48)(commitment))
   115  	if err != nil {
   116  		return Proof{}, err
   117  	}
   118  	return (Proof)(proof), nil
   119  }
   120  
   121  // ckzgVerifyBlobProof verifies that the blob data corresponds to the provided commitment.
   122  func ckzgVerifyBlobProof(blob *Blob, commitment Commitment, proof Proof) error {
   123  	ckzgIniter.Do(ckzgInit)
   124  
   125  	valid, err := ckzg4844.VerifyBlobKZGProof((*ckzg4844.Blob)(blob), (ckzg4844.Bytes48)(commitment), (ckzg4844.Bytes48)(proof))
   126  	if err != nil {
   127  		return err
   128  	}
   129  	if !valid {
   130  		return errors.New("invalid proof")
   131  	}
   132  	return nil
   133  }
   134  
   135  // ckzgComputeCellProofs returns the KZG cell proofs that are used to verify the blob against
   136  // the commitment.
   137  //
   138  // This method does not verify that the commitment is correct with respect to blob.
   139  func ckzgComputeCellProofs(blob *Blob) ([]Proof, error) {
   140  	ckzgIniter.Do(ckzgInit)
   141  
   142  	_, proofs, err := ckzg4844.ComputeCellsAndKZGProofs((*ckzg4844.Blob)(blob))
   143  	if err != nil {
   144  		return []Proof{}, err
   145  	}
   146  	var p []Proof
   147  	for _, proof := range proofs {
   148  		p = append(p, (Proof)(proof))
   149  	}
   150  	return p, nil
   151  }
   152  
   153  // ckzgVerifyCellProofs verifies that the blob data corresponds to the provided commitment.
   154  func ckzgVerifyCellProofBatch(blobs []Blob, commitments []Commitment, cellProofs []Proof) error {
   155  	ckzgIniter.Do(ckzgInit)
   156  	var (
   157  		proofs      = make([]ckzg4844.Bytes48, len(cellProofs))
   158  		commits     = make([]ckzg4844.Bytes48, 0, len(cellProofs))
   159  		cellIndices = make([]uint64, 0, len(cellProofs))
   160  		cells       = make([]ckzg4844.Cell, 0, len(cellProofs))
   161  	)
   162  	// Copy over the cell proofs
   163  	for i, proof := range cellProofs {
   164  		proofs[i] = (ckzg4844.Bytes48)(proof)
   165  	}
   166  	// Blow up the commitments to be the same length as the proofs
   167  	for _, commitment := range commitments {
   168  		for range gokzg4844.CellsPerExtBlob {
   169  			commits = append(commits, (ckzg4844.Bytes48)(commitment))
   170  		}
   171  	}
   172  	// Compute the cells and cell indices
   173  	for i := range blobs {
   174  		cellsI, err := ckzg4844.ComputeCells((*ckzg4844.Blob)(&blobs[i]))
   175  		if err != nil {
   176  			return err
   177  		}
   178  		cells = append(cells, cellsI[:]...)
   179  		for idx := range len(cellsI) {
   180  			cellIndices = append(cellIndices, uint64(idx))
   181  		}
   182  	}
   183  
   184  	valid, err := ckzg4844.VerifyCellKZGProofBatch(commits, cellIndices, cells, proofs)
   185  	if err != nil {
   186  		return err
   187  	}
   188  	if !valid {
   189  		return errors.New("invalid proof")
   190  	}
   191  	return nil
   192  }