github.com/ethereum/go-ethereum@v1.16.1/crypto/kzg4844/kzg4844.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 // Package kzg4844 implements the KZG crypto for EIP-4844. 18 package kzg4844 19 20 import ( 21 "embed" 22 "errors" 23 "hash" 24 "reflect" 25 "sync/atomic" 26 27 "github.com/ethereum/go-ethereum/common/hexutil" 28 ) 29 30 //go:embed trusted_setup.json 31 var content embed.FS 32 33 var ( 34 blobT = reflect.TypeOf(Blob{}) 35 commitmentT = reflect.TypeOf(Commitment{}) 36 proofT = reflect.TypeOf(Proof{}) 37 38 CellProofsPerBlob = 128 39 ) 40 41 // Blob represents a 4844 data blob. 42 type Blob [131072]byte 43 44 // UnmarshalJSON parses a blob in hex syntax. 45 func (b *Blob) UnmarshalJSON(input []byte) error { 46 return hexutil.UnmarshalFixedJSON(blobT, input, b[:]) 47 } 48 49 // MarshalText returns the hex representation of b. 50 func (b *Blob) MarshalText() ([]byte, error) { 51 return hexutil.Bytes(b[:]).MarshalText() 52 } 53 54 // Commitment is a serialized commitment to a polynomial. 55 type Commitment [48]byte 56 57 // UnmarshalJSON parses a commitment in hex syntax. 58 func (c *Commitment) UnmarshalJSON(input []byte) error { 59 return hexutil.UnmarshalFixedJSON(commitmentT, input, c[:]) 60 } 61 62 // MarshalText returns the hex representation of c. 63 func (c Commitment) MarshalText() ([]byte, error) { 64 return hexutil.Bytes(c[:]).MarshalText() 65 } 66 67 // Proof is a serialized commitment to the quotient polynomial. 68 type Proof [48]byte 69 70 // UnmarshalJSON parses a proof in hex syntax. 71 func (p *Proof) UnmarshalJSON(input []byte) error { 72 return hexutil.UnmarshalFixedJSON(proofT, input, p[:]) 73 } 74 75 // MarshalText returns the hex representation of p. 76 func (p Proof) MarshalText() ([]byte, error) { 77 return hexutil.Bytes(p[:]).MarshalText() 78 } 79 80 // Point is a BLS field element. 81 type Point [32]byte 82 83 // Claim is a claimed evaluation value in a specific point. 84 type Claim [32]byte 85 86 // useCKZG controls whether the cryptography should use the Go or C backend. 87 var useCKZG atomic.Bool 88 89 // UseCKZG can be called to switch the default Go implementation of KZG to the C 90 // library if for some reason the user wishes to do so (e.g. consensus bug in one 91 // or the other). 92 func UseCKZG(use bool) error { 93 if use && !ckzgAvailable { 94 return errors.New("CKZG unavailable on your platform") 95 } 96 useCKZG.Store(use) 97 98 // Initializing the library can take 2-4 seconds - and can potentially crash 99 // on CKZG and non-ADX CPUs - so might as well do it now and don't wait until 100 // a crypto operation is actually needed live. 101 if use { 102 ckzgIniter.Do(ckzgInit) 103 } else { 104 gokzgIniter.Do(gokzgInit) 105 } 106 return nil 107 } 108 109 // BlobToCommitment creates a small commitment out of a data blob. 110 func BlobToCommitment(blob *Blob) (Commitment, error) { 111 if useCKZG.Load() { 112 return ckzgBlobToCommitment(blob) 113 } 114 return gokzgBlobToCommitment(blob) 115 } 116 117 // ComputeProof computes the KZG proof at the given point for the polynomial 118 // represented by the blob. 119 func ComputeProof(blob *Blob, point Point) (Proof, Claim, error) { 120 if useCKZG.Load() { 121 return ckzgComputeProof(blob, point) 122 } 123 return gokzgComputeProof(blob, point) 124 } 125 126 // VerifyProof verifies the KZG proof that the polynomial represented by the blob 127 // evaluated at the given point is the claimed value. 128 func VerifyProof(commitment Commitment, point Point, claim Claim, proof Proof) error { 129 if useCKZG.Load() { 130 return ckzgVerifyProof(commitment, point, claim, proof) 131 } 132 return gokzgVerifyProof(commitment, point, claim, proof) 133 } 134 135 // ComputeBlobProof returns the KZG proof that is 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 ComputeBlobProof(blob *Blob, commitment Commitment) (Proof, error) { 140 if useCKZG.Load() { 141 return ckzgComputeBlobProof(blob, commitment) 142 } 143 return gokzgComputeBlobProof(blob, commitment) 144 } 145 146 // VerifyBlobProof verifies that the blob data corresponds to the provided commitment. 147 func VerifyBlobProof(blob *Blob, commitment Commitment, proof Proof) error { 148 if useCKZG.Load() { 149 return ckzgVerifyBlobProof(blob, commitment, proof) 150 } 151 return gokzgVerifyBlobProof(blob, commitment, proof) 152 } 153 154 // VerifyCellProofs verifies a batch of proofs corresponding to the blobs and commitments. 155 // Expects length of blobs and commitments to be equal. 156 // Expects length of proofs be 128 * length of blobs. 157 func VerifyCellProofs(blobs []Blob, commitments []Commitment, proofs []Proof) error { 158 if useCKZG.Load() { 159 return ckzgVerifyCellProofBatch(blobs, commitments, proofs) 160 } 161 return gokzgVerifyCellProofBatch(blobs, commitments, proofs) 162 } 163 164 // ComputeCellProofs returns the KZG cell proofs that are used to verify the blob against 165 // the commitment. 166 // 167 // This method does not verify that the commitment is correct with respect to blob. 168 func ComputeCellProofs(blob *Blob) ([]Proof, error) { 169 if useCKZG.Load() { 170 return ckzgComputeCellProofs(blob) 171 } 172 return gokzgComputeCellProofs(blob) 173 } 174 175 // CalcBlobHashV1 calculates the 'versioned blob hash' of a commitment. 176 // The given hasher must be a sha256 hash instance, otherwise the result will be invalid! 177 func CalcBlobHashV1(hasher hash.Hash, commit *Commitment) (vh [32]byte) { 178 if hasher.Size() != 32 { 179 panic("wrong hash size") 180 } 181 hasher.Reset() 182 hasher.Write(commit[:]) 183 hasher.Sum(vh[:0]) 184 vh[0] = 0x01 // version 185 return vh 186 } 187 188 // IsValidVersionedHash checks that h is a structurally-valid versioned blob hash. 189 func IsValidVersionedHash(h []byte) bool { 190 return len(h) == 32 && h[0] == 0x01 191 }