diff --git a/accounts/external/backend.go b/accounts/external/backend.go index fac55cdc94..e8b9dcf44f 100644 --- a/accounts/external/backend.go +++ b/accounts/external/backend.go @@ -218,14 +218,14 @@ func (api *ExternalSigner) SignTx(account accounts.Account, tx *types.Transactio args.MaxFeePerGas = (*hexutil.Big)(tx.GasFeeCap()) args.MaxPriorityFeePerGas = (*hexutil.Big)(tx.GasTipCap()) case types.BlobTxType: - hashes, _, blobs, aggProof := tx.BlobWrapData() + hashes, _, blobs, proofs := tx.BlobWrapData() if len(hashes) != len(blobs) { return nil, fmt.Errorf("missing blobs data, expected %d blobs", len(hashes)) } - var z types.KZGProof - if aggProof == z { - return nil, fmt.Errorf("missing aggregated proof in blobs") + if len(hashes) != len(proofs) { + return nil, fmt.Errorf("missing proofs data, expected %d proofs", len(proofs)) } + args.MaxFeePerGas = (*hexutil.Big)(tx.GasFeeCap()) args.MaxPriorityFeePerGas = (*hexutil.Big)(tx.GasTipCap()) args.Blobs = blobs diff --git a/beacon/engine/types.go b/beacon/engine/types.go index c9ab734ecb..9f70bf04a8 100644 --- a/beacon/engine/types.go +++ b/beacon/engine/types.go @@ -17,7 +17,6 @@ package engine import ( - "errors" "fmt" "math/big" @@ -257,15 +256,12 @@ func BlockToBlobData(block *types.Block) (*BlobsBundle, error) { } for i, tx := range block.Transactions() { if tx.Type() == types.BlobTxType { - versionedHashes, kzgs, blobs, aggProof := tx.BlobWrapData() - if len(versionedHashes) != len(kzgs) || len(versionedHashes) != len(blobs) { + versionedHashes, kzgs, blobs, proofs := tx.BlobWrapData() + if len(versionedHashes) != len(kzgs) || len(versionedHashes) != len(blobs) || len(blobs) != len(proofs) { return nil, fmt.Errorf("tx %d in block %s has inconsistent blobs (%d) / kzgs (%d)"+ - " / versioned hashes (%d)", i, blockHash, len(blobs), len(kzgs), len(versionedHashes)) - } - var zProof types.KZGProof - if zProof == aggProof { - return nil, errors.New("aggregated proof is not available in blobs") + " / versioned hashes (%d) / proofs (%d)", i, blockHash, len(blobs), len(kzgs), len(versionedHashes), len(proofs)) } + blobsBundle.Blobs = append(blobsBundle.Blobs, blobs...) blobsBundle.KZGs = append(blobsBundle.KZGs, kzgs...) } diff --git a/core/txpool/txpool_test.go b/core/txpool/txpool_test.go index 1cf8aa0446..a16ee86d36 100644 --- a/core/txpool/txpool_test.go +++ b/core/txpool/txpool_test.go @@ -128,11 +128,11 @@ func blobTx(nonce uint64, gaslimit uint64, gasFee uint64, tip uint64, dataGasFee for i := 0; i < len(blobData.BlobKzgs); i++ { hashes = append(hashes, blobData.BlobKzgs[i].ComputeVersionedHash()) } - _, _, aggregatedProof, err := blobData.Blobs.ComputeCommitmentsAndAggregatedProof() + _, _, proofs, err := blobData.Blobs.ComputeCommitmentsAndProofs() if err != nil { panic(err) } - blobData.KzgAggregatedProof = aggregatedProof + blobData.Proofs = proofs address := types.AddressSSZ(common.Address{}) sbtx := &types.SignedBlobTx{ diff --git a/core/types/data_blob.go b/core/types/data_blob.go index 2b0f4a675d..bf58ea9ee5 100644 --- a/core/types/data_blob.go +++ b/core/types/data_blob.go @@ -7,7 +7,7 @@ import ( "io" "github.com/crate-crypto/go-proto-danksharding-crypto/eth" - api "github.com/crate-crypto/go-proto-danksharding-crypto/serialisation" + api "github.com/crate-crypto/go-proto-danksharding-crypto/serialization" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/params" @@ -199,6 +199,36 @@ func (li BlobKzgs) copy() BlobKzgs { return cpy } +type KZGProofs []KZGProof + +func (li *KZGProofs) Deserialize(dr *codec.DecodingReader) error { + return dr.List(func() codec.Deserializable { + i := len(*li) + *li = append(*li, KZGProof{}) + return &(*li)[i] + }, 48, params.MaxBlobsPerBlock) +} + +func (li KZGProofs) Serialize(w *codec.EncodingWriter) error { + return w.List(func(i uint64) codec.Serializable { + return &li[i] + }, 48, uint64(len(li))) +} + +func (li KZGProofs) ByteLength() uint64 { + return uint64(len(li)) * 48 +} + +func (li KZGProofs) FixedLength() uint64 { + return 0 +} + +func (li KZGProofs) copy() KZGProofs { + cpy := make(KZGProofs, len(li)) + copy(cpy, li) + return cpy +} + type Blobs []Blob func (a *Blobs) Deserialize(dr *codec.DecodingReader) error { @@ -229,28 +259,28 @@ func (blobs Blobs) copy() Blobs { return cpy } -// Return KZG commitments, versioned hashes and the aggregated KZG proof that correspond to these blobs -func (blobs Blobs) ComputeCommitmentsAndAggregatedProof() (commitments []KZGCommitment, versionedHashes []common.Hash, aggregatedProof KZGProof, err error) { +// Return KZG commitments, versioned hashes and the proofs that correspond to these blobs +func (blobs Blobs) ComputeCommitmentsAndProofs() (commitments []KZGCommitment, versionedHashes []common.Hash, proofs []KZGProof, err error) { commitments = make([]KZGCommitment, len(blobs)) + proofs = make([]KZGProof, len(blobs)) versionedHashes = make([]common.Hash, len(blobs)) for i, blob := range blobs { - commitment, err := eth.CryptoCtx.BlobToCommitment(blob) + commitment, err := eth.CryptoCtx.BlobToKZGCommitment(blob) if err != nil { + return nil, nil, nil, fmt.Errorf("could not convert blob to commitment: %v", err) + } - return nil, nil, KZGProof{}, fmt.Errorf("could not convert blob to commitment: %v", err) + proof, err := eth.CryptoCtx.ComputeBlobKZGProof(blob, commitment) + if err != nil { + return nil, nil, nil, fmt.Errorf("could not compute proof for blob: %v", err) } commitments[i] = KZGCommitment(commitment) + proofs[i] = KZGProof(proof) versionedHashes[i] = common.Hash(eth.KZGToVersionedHash(commitment)) } - proof, _, err := eth.CryptoCtx.ComputeAggregateKZGProof(toBlobs(blobs)) - if err != nil { - return nil, nil, KZGProof{}, err - } - var kzgProof = KZGProof(proof) - - return commitments, versionedHashes, kzgProof, nil + return commitments, versionedHashes, proofs, nil } func toBlobs(_blobs Blobs) []api.Blob { @@ -267,24 +297,31 @@ func toComms(_comms BlobKzgs) []api.KZGCommitment { } return comms } +func toProofs(_proofs KZGProofs) []api.KZGProof { + proofs := make([]api.KZGProof, len(_proofs)) + for i, _proof := range _proofs { + proofs[i] = api.KZGProof(_proof) + } + return proofs +} type BlobTxWrapper struct { - Tx SignedBlobTx - BlobKzgs BlobKzgs - Blobs Blobs - KzgAggregatedProof KZGProof + Tx SignedBlobTx + BlobKzgs BlobKzgs + Blobs Blobs + Proofs KZGProofs } func (txw *BlobTxWrapper) Deserialize(dr *codec.DecodingReader) error { - return dr.Container(&txw.Tx, &txw.BlobKzgs, &txw.Blobs, &txw.KzgAggregatedProof) + return dr.Container(&txw.Tx, &txw.BlobKzgs, &txw.Blobs, &txw.Proofs) } func (txw *BlobTxWrapper) Serialize(w *codec.EncodingWriter) error { - return w.Container(&txw.Tx, &txw.BlobKzgs, &txw.Blobs, &txw.KzgAggregatedProof) + return w.Container(&txw.Tx, &txw.BlobKzgs, &txw.Blobs, &txw.Proofs) } func (txw *BlobTxWrapper) ByteLength() uint64 { - return codec.ContainerLength(&txw.Tx, &txw.BlobKzgs, &txw.Blobs, &txw.KzgAggregatedProof) + return codec.ContainerLength(&txw.Tx, &txw.BlobKzgs, &txw.Blobs, &txw.Proofs) } func (txw *BlobTxWrapper) FixedLength() uint64 { @@ -292,14 +329,14 @@ func (txw *BlobTxWrapper) FixedLength() uint64 { } type BlobTxWrapData struct { - BlobKzgs BlobKzgs - Blobs Blobs - KzgAggregatedProof KZGProof + BlobKzgs BlobKzgs + Blobs Blobs + Proofs KZGProofs } // sizeWrapData returns the size in bytes of the ssz-encoded BlobTxWrapData func (b *BlobTxWrapData) sizeWrapData() common.StorageSize { - return common.StorageSize(codec.ContainerLength(&b.BlobKzgs, &b.Blobs, &b.KzgAggregatedProof)) + return common.StorageSize(codec.ContainerLength(&b.BlobKzgs, &b.Blobs, &b.Proofs)) } // validateBlobTransactionWrapper implements validate_blob_transaction_wrapper from EIP-4844 @@ -320,7 +357,7 @@ func (b *BlobTxWrapData) validateBlobTransactionWrapper(inner TxData) error { if l1 > params.MaxBlobsPerBlock { return fmt.Errorf("number of blobs exceeds max: %v", l1) } - err := eth.CryptoCtx.VerifyAggregateKZGProof(toBlobs(b.Blobs), api.KZGProof(b.KzgAggregatedProof), toComms(b.BlobKzgs)) + err := eth.CryptoCtx.VerifyBlobKZGProofBatch(toBlobs(b.Blobs), toProofs(b.Proofs), toComms(b.BlobKzgs)) if err != nil { return fmt.Errorf("error during proof verification: %v", err) } @@ -337,9 +374,9 @@ func (b *BlobTxWrapData) validateBlobTransactionWrapper(inner TxData) error { func (b *BlobTxWrapData) copy() TxWrapData { return &BlobTxWrapData{ - BlobKzgs: b.BlobKzgs.copy(), - Blobs: b.Blobs.copy(), - KzgAggregatedProof: b.KzgAggregatedProof, + BlobKzgs: b.BlobKzgs.copy(), + Blobs: b.Blobs.copy(), + Proofs: b.Proofs.copy(), } } @@ -351,8 +388,8 @@ func (b *BlobTxWrapData) blobs() Blobs { return b.Blobs } -func (b *BlobTxWrapData) aggregatedProof() KZGProof { - return b.KzgAggregatedProof +func (b *BlobTxWrapData) proofs() KZGProofs { + return b.Proofs } func (b *BlobTxWrapData) encodeTyped(w io.Writer, txdata TxData) error { @@ -364,10 +401,10 @@ func (b *BlobTxWrapData) encodeTyped(w io.Writer, txdata TxData) error { return fmt.Errorf("expected signed blob tx, got %T", txdata) } wrapped := BlobTxWrapper{ - Tx: *blobTx, - BlobKzgs: b.BlobKzgs, - Blobs: b.Blobs, - KzgAggregatedProof: b.KzgAggregatedProof, + Tx: *blobTx, + BlobKzgs: b.BlobKzgs, + Blobs: b.Blobs, + Proofs: b.Proofs, } return EncodeSSZ(w, &wrapped) } diff --git a/core/types/transaction.go b/core/types/transaction.go index 7adc0682a8..50e1fd623e 100644 --- a/core/types/transaction.go +++ b/core/types/transaction.go @@ -95,7 +95,7 @@ type TxWrapData interface { copy() TxWrapData kzgs() BlobKzgs blobs() Blobs - aggregatedProof() KZGProof + proofs() KZGProofs encodeTyped(w io.Writer, txdata TxData) error sizeWrapData() common.StorageSize validateBlobTransactionWrapper(inner TxData) error @@ -270,7 +270,7 @@ func (tx *Transaction) decodeTyped(b []byte) (TxData, TxWrapData, error) { case BlobTxType: var wrapped BlobTxWrapper err := DecodeSSZ(b[1:], &wrapped) - return &wrapped.Tx, &BlobTxWrapData{BlobKzgs: wrapped.BlobKzgs, Blobs: wrapped.Blobs, KzgAggregatedProof: wrapped.KzgAggregatedProof}, err + return &wrapped.Tx, &BlobTxWrapData{BlobKzgs: wrapped.BlobKzgs, Blobs: wrapped.Blobs, Proofs: wrapped.Proofs}, err default: minimal, err := tx.decodeTypedMinimal(b) return minimal, nil, err @@ -555,13 +555,13 @@ func (tx *Transaction) VerifyBlobs() error { // BlobWrapData returns the blob and kzg data, if any. // kzgs and blobs may be empty if the transaction is not wrapped. -func (tx *Transaction) BlobWrapData() (versionedHashes []common.Hash, kzgs BlobKzgs, blobs Blobs, aggProof KZGProof) { +func (tx *Transaction) BlobWrapData() (versionedHashes []common.Hash, kzgs BlobKzgs, blobs Blobs, proofs KZGProofs) { if blobWrap, ok := tx.wrapData.(*BlobTxWrapData); ok { if signedBlobTx, ok := tx.inner.(*SignedBlobTx); ok { - return signedBlobTx.Message.BlobVersionedHashes, blobWrap.BlobKzgs, blobWrap.Blobs, blobWrap.KzgAggregatedProof + return signedBlobTx.Message.BlobVersionedHashes, blobWrap.BlobKzgs, blobWrap.Blobs, blobWrap.Proofs } } - return nil, nil, nil, KZGProof{} + return nil, nil, nil, nil } // WithSignature returns a new transaction with the given signature. diff --git a/core/types/transaction_marshalling.go b/core/types/transaction_marshalling.go index 6dd7a3ea87..ae5b356352 100644 --- a/core/types/transaction_marshalling.go +++ b/core/types/transaction_marshalling.go @@ -54,7 +54,7 @@ type txJSON struct { BlobVersionedHashes []common.Hash `json:"blobVersionedHashes,omitempty"` Blobs Blobs `json:"blobs,omitempty"` BlobKzgs BlobKzgs `json:"blobKzgs,omitempty"` - KzgAggregatedProof KZGProof `json:"kzgAggregatedProof,omitempty"` + Proofs KZGProofs `json:"proofs,omitempty"` // Only used for encoding: Hash common.Hash `json:"hash"` @@ -123,7 +123,7 @@ func (tx *Transaction) MarshalJSON() ([]byte, error) { if tx.wrapData != nil { enc.Blobs = tx.wrapData.blobs() enc.BlobKzgs = tx.wrapData.kzgs() - enc.KzgAggregatedProof = tx.wrapData.aggregatedProof() + enc.Proofs = tx.wrapData.proofs() } } return json.Marshal(&enc) @@ -362,9 +362,9 @@ func (tx *Transaction) UnmarshalJSON(input []byte) error { // A BlobTx may not contain data if len(dec.Blobs) != 0 || len(dec.BlobKzgs) != 0 { tx.wrapData = &BlobTxWrapData{ - BlobKzgs: dec.BlobKzgs, - Blobs: dec.Blobs, - KzgAggregatedProof: dec.KzgAggregatedProof, + BlobKzgs: dec.BlobKzgs, + Blobs: dec.Blobs, + Proofs: dec.Proofs, } // Verify that versioned hashes match kzgs, and kzgs match blobs. if err := tx.wrapData.validateBlobTransactionWrapper(&itx); err != nil { diff --git a/core/types/transaction_signing_test.go b/core/types/transaction_signing_test.go index 6b207461e1..31d43c8630 100644 --- a/core/types/transaction_signing_test.go +++ b/core/types/transaction_signing_test.go @@ -99,9 +99,9 @@ func TestEIP4844Signing(t *testing.T) { // This is the identity point serialised var kzgProof KZGProof = [48]byte{192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} wrapData := &BlobTxWrapData{ - BlobKzgs: BlobKzgs{KZGCommitment{0: 0xc0}}, - Blobs: Blobs{Blob{}}, - KzgAggregatedProof: kzgProof, + BlobKzgs: BlobKzgs{KZGCommitment{0: 0xc0}}, + Blobs: Blobs{Blob{}}, + Proofs: KZGProofs{kzgProof}, } tx := NewTx(txdata, WithTxWrapData(wrapData)) tx, err := SignTx(tx, signer, key) diff --git a/core/types/transaction_test.go b/core/types/transaction_test.go index b57fc1e8dd..d91ab457be 100644 --- a/core/types/transaction_test.go +++ b/core/types/transaction_test.go @@ -495,9 +495,9 @@ func TestTransactionCoding(t *testing.T) { // This is the identity point serialised var kzgProof KZGProof = [48]byte{192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} wrapData = &BlobTxWrapData{ - BlobKzgs: BlobKzgs{KZGCommitment{0: 0xc0}}, - Blobs: Blobs{Blob{}}, - KzgAggregatedProof: kzgProof, + BlobKzgs: BlobKzgs{KZGCommitment{0: 0xc0}}, + Blobs: Blobs{Blob{}}, + Proofs: KZGProofs{kzgProof}, } } tx, err := SignNewTx(key, signer, txdata, WithTxWrapData(wrapData)) diff --git a/core/types/types_test.go b/core/types/types_test.go index 8ec887b84f..c40212aca2 100644 --- a/core/types/types_test.go +++ b/core/types/types_test.go @@ -149,9 +149,9 @@ func benchRLP(b *testing.B, encode bool) { BlobVersionedHashes: VersionedHashesView{common.Hash{0xaa}}, }, }, WithTxWrapData(&BlobTxWrapData{ - BlobKzgs: BlobKzgs{KZGCommitment{0xbb}}, - Blobs: Blobs{Blob{}}, - KzgAggregatedProof: KZGProof{0xbc}, + BlobKzgs: BlobKzgs{KZGCommitment{0xbb}}, + Blobs: Blobs{Blob{}}, + Proofs: KZGProofs{KZGProof{0xbc}}, })), }, } { diff --git a/eth/catalyst/api_test.go b/eth/catalyst/api_test.go index f75e3d3938..ab181cca20 100644 --- a/eth/catalyst/api_test.go +++ b/eth/catalyst/api_test.go @@ -1614,7 +1614,7 @@ func newRandomBlobTx(t *testing.T, chain *core.BlockChain, nonce uint64) *types. var blobs types.Blobs blobs = append(blobs, types.Blob{}) - commitments, versionedHashes, aggregatedProof, err := blobs.ComputeCommitmentsAndAggregatedProof() + commitments, versionedHashes, proofs, err := blobs.ComputeCommitmentsAndProofs() if err != nil { t.Fatal(err) } @@ -1639,9 +1639,9 @@ func newRandomBlobTx(t *testing.T, chain *core.BlockChain, nonce uint64) *types. }, } wrapData := &types.BlobTxWrapData{ - BlobKzgs: commitments, - Blobs: blobs, - KzgAggregatedProof: aggregatedProof, + BlobKzgs: commitments, + Blobs: blobs, + Proofs: proofs, } tx := types.NewTx(txData, types.WithTxWrapData(wrapData)) signer := types.NewDankSigner(chainID) diff --git a/eth/handler_eth_test.go b/eth/handler_eth_test.go index 835f7830c6..4157d74aeb 100644 --- a/eth/handler_eth_test.go +++ b/eth/handler_eth_test.go @@ -462,9 +462,9 @@ func testTransactionPropagation(t *testing.T, protocol uint) { }, } wrapData := &types.BlobTxWrapData{ - BlobKzgs: types.BlobKzgs{types.KZGCommitment{0: 0xc0}}, - Blobs: types.Blobs{types.Blob{}}, - KzgAggregatedProof: types.KZGProof{0: 0xd0}, + BlobKzgs: types.BlobKzgs{types.KZGCommitment{0: 0xc0}}, + Blobs: types.Blobs{types.Blob{}}, + Proofs: types.KZGProofs{types.KZGProof{0: 0xd0}}, } blobTx, err := types.SignNewTx(testKey, types.NewDankSigner(common.Big1), txdata, types.WithTxWrapData(wrapData)) if err != nil { diff --git a/go.mod b/go.mod index 6ae3164b19..0e331da38d 100644 --- a/go.mod +++ b/go.mod @@ -71,7 +71,7 @@ require ( gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce ) -require github.com/crate-crypto/go-proto-danksharding-crypto v0.0.0-20230213123031-bc4b91aed74e +require github.com/crate-crypto/go-proto-danksharding-crypto v0.0.0-20230312204821-9a244123c812 require ( github.com/Azure/azure-sdk-for-go/sdk/azcore v0.21.1 // indirect diff --git a/go.sum b/go.sum index 9038dae313..3f1b96a793 100644 --- a/go.sum +++ b/go.sum @@ -118,6 +118,8 @@ github.com/crate-crypto/go-ipa v0.0.0-20220523130400-f11357ae11c7 h1:6IrxszG5G+O github.com/crate-crypto/go-ipa v0.0.0-20220523130400-f11357ae11c7/go.mod h1:gFnFS95y8HstDP6P9pPwzrxOOC5TRDkwbM+ao15ChAI= github.com/crate-crypto/go-proto-danksharding-crypto v0.0.0-20230213123031-bc4b91aed74e h1:c+QZmGarRVSxlZNpCaJQEddyy1zNM1vgMZPoQD/a9cc= github.com/crate-crypto/go-proto-danksharding-crypto v0.0.0-20230213123031-bc4b91aed74e/go.mod h1:S4I9lm+hf0TAWUA9eo7xyujhicj+VqkWUoFD0W89ifg= +github.com/crate-crypto/go-proto-danksharding-crypto v0.0.0-20230312204821-9a244123c812 h1:fvpzeIO449sb44y2Nqd0MVziJHvp0OFCG66t3ZjuYqU= +github.com/crate-crypto/go-proto-danksharding-crypto v0.0.0-20230312204821-9a244123c812/go.mod h1:ZNzUrSnC7IXKtQWnROzWVfQSivVSCPkMtwXekLDj4qI= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/cyberdelia/templates v0.0.0-20141128023046-ca7fffd4298c/go.mod h1:GyV+0YP4qX0UQ7r2MoYZ+AvYDp12OF5yg4q8rGnyNh4= github.com/dave/jennifer v1.2.0/go.mod h1:fIb+770HOpJ2fmN9EPPKOqm1vMGhB+TwXKMZhrIygKg= diff --git a/internal/ethapi/transaction_args.go b/internal/ethapi/transaction_args.go index 62ffc12c54..28eeb4af08 100644 --- a/internal/ethapi/transaction_args.go +++ b/internal/ethapi/transaction_args.go @@ -302,13 +302,13 @@ func (args *TransactionArgs) toTransaction() *types.Transaction { msg.Value.SetFromBig((*big.Int)(args.Value)) msg.Data = args.data() msg.AccessList = types.AccessListView(al) - commitments, versionedHashes, aggregatedProof, err := types.Blobs(args.Blobs).ComputeCommitmentsAndAggregatedProof() + commitments, versionedHashes, proofs, err := types.Blobs(args.Blobs).ComputeCommitmentsAndProofs() // XXX if blobs are invalid we will omit the wrap-data (and an error will pop-up later) if err == nil { opts = append(opts, types.WithTxWrapData(&types.BlobTxWrapData{ - BlobKzgs: commitments, - Blobs: args.Blobs, - KzgAggregatedProof: aggregatedProof, + BlobKzgs: commitments, + Blobs: args.Blobs, + Proofs: proofs, })) msg.BlobVersionedHashes = versionedHashes } diff --git a/signer/core/apitypes/types.go b/signer/core/apitypes/types.go index dfe7953daf..79d47399ef 100644 --- a/signer/core/apitypes/types.go +++ b/signer/core/apitypes/types.go @@ -145,15 +145,15 @@ func (args *SendTxArgs) ToTransaction() (*types.Transaction, error) { msg.Value.SetFromBig((*big.Int)(&args.Value)) msg.Data = input msg.AccessList = types.AccessListView(al) - commitments, hashes, aggProof, err := types.Blobs(args.Blobs).ComputeCommitmentsAndAggregatedProof() + commitments, hashes, proofs, err := types.Blobs(args.Blobs).ComputeCommitmentsAndProofs() if err != nil { return nil, fmt.Errorf("invalid blobs: %v", err) } msg.BlobVersionedHashes = hashes wrapData := types.BlobTxWrapData{ - Blobs: args.Blobs, - KzgAggregatedProof: aggProof, - BlobKzgs: commitments, + Blobs: args.Blobs, + Proofs: proofs, + BlobKzgs: commitments, } data = &types.SignedBlobTx{Message: msg} return types.NewTx(data, types.WithTxWrapData(&wrapData)), nil diff --git a/tests/kzg_bench_test.go b/tests/kzg_bench_test.go deleted file mode 100644 index 7b8d19601e..0000000000 --- a/tests/kzg_bench_test.go +++ /dev/null @@ -1,192 +0,0 @@ -// TODO: Migrate these to go-kzg/eth -package tests - -import ( - "fmt" - "math" - "testing" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/params" - "github.com/holiman/uint256" - gokzg "github.com/protolambda/go-kzg" - "github.com/protolambda/go-kzg/bls" - "github.com/protolambda/go-kzg/eth" - "github.com/protolambda/ztyp/view" -) - -func randomBlob() eth.Polynomial { - blob := make(eth.Polynomial, params.FieldElementsPerBlob) - for i := 0; i < len(blob); i++ { - blob[i] = *bls.RandomFr() - } - return blob -} - -func BenchmarkBlobToKzg(b *testing.B) { - blob := randomBlob() - b.ResetTimer() - for i := 0; i < b.N; i++ { - eth.PolynomialToKZGCommitment(blob) - } -} - -func BenchmarkVerifyBlobs(b *testing.B) { - blobs := make([]types.Blob, params.MaxBlobsPerBlock) - var commitments []types.KZGCommitment - var hashes []common.Hash - for i := 0; i < len(blobs); i++ { - tmp := randomBlob() - for j := range tmp { - blobs[i][j] = bls.FrTo32(&tmp[j]) - } - frs, ok := eth.BlobToPolynomial(blobs[i]) - if !ok { - b.Fatal("Could not compute commitment") - } - c := types.KZGCommitment(eth.PolynomialToKZGCommitment(frs)) - commitments = append(commitments, c) - h := common.Hash(eth.KZGToVersionedHash(eth.KZGCommitment(c))) - hashes = append(hashes, h) - } - txData := &types.SignedBlobTx{ - Message: types.BlobTxMessage{ - ChainID: view.Uint256View(*uint256.NewInt(1)), - Nonce: view.Uint64View(0), - Gas: view.Uint64View(123457), - GasTipCap: view.Uint256View(*uint256.NewInt(42)), - GasFeeCap: view.Uint256View(*uint256.NewInt(10)), - BlobVersionedHashes: hashes, - }, - } - _, _, aggregatedProof, err := types.Blobs(blobs).ComputeCommitmentsAndAggregatedProof() - if err != nil { - b.Fatal(err) - } - wrapData := &types.BlobTxWrapData{ - BlobKzgs: commitments, - Blobs: blobs, - KzgAggregatedProof: aggregatedProof, - } - tx := types.NewTx(txData, types.WithTxWrapData(wrapData)) - - b.ResetTimer() - for i := 0; i < b.N; i++ { - if err := tx.VerifyBlobs(); err != nil { - b.Fatal(err) - } - } -} - -func BenchmarkVerifyKZGProof(b *testing.B) { - // First let's do some go-kzg preparations to be able to convert polynomial between coefficient and evaluation form - fs := gokzg.NewFFTSettings(uint8(math.Log2(params.FieldElementsPerBlob))) - - // Create testing polynomial (in coefficient form) - polynomial := make([]bls.Fr, params.FieldElementsPerBlob) - for i := uint64(0); i < params.FieldElementsPerBlob; i++ { - bls.CopyFr(&polynomial[i], bls.RandomFr()) - } - - // Get polynomial in evaluation form - evalPoly, err := fs.FFT(polynomial, false) - if err != nil { - b.Fatal(err) - } - - // Now let's start testing the kzg module - // Create a commitment - k := eth.PolynomialToKZGCommitment(evalPoly) - commitment, _ := bls.FromCompressedG1(k[:]) - - // Create proof for testing - x := uint64(17) - proof := ComputeProof(polynomial, x, eth.KzgSetupG1) - - // Get actual evaluation at x - var xFr bls.Fr - bls.AsFr(&xFr, x) - var value bls.Fr - bls.EvalPolyAt(&value, polynomial, &xFr) - - b.ResetTimer() - for i := 0; i < b.N; i++ { - // Verify kzg proof - if eth.VerifyKZGProofFromPoints(commitment, &xFr, &value, proof) != true { - b.Fatal("failed proof verification") - } - } -} - -func BenchmarkVerifyMultiple(b *testing.B) { - runBenchmark := func(siz int) { - b.Run(fmt.Sprintf("%d", siz), func(b *testing.B) { - var blobsSet [][]types.Blob - var commitmentsSet [][]types.KZGCommitment - var hashesSet [][]common.Hash - for i := 0; i < siz; i++ { - var blobs []types.Blob - var commitments []types.KZGCommitment - var hashes []common.Hash - for i := 0; i < params.MaxBlobsPerBlock; i++ { - var blobElements types.Blob - blob := randomBlob() - for j := range blob { - blobElements[j] = bls.FrTo32(&blob[j]) - } - blobs = append(blobs, blobElements) - c := types.KZGCommitment(eth.PolynomialToKZGCommitment(blob)) - commitments = append(commitments, c) - h := common.Hash(eth.KZGToVersionedHash(eth.KZGCommitment(c))) - hashes = append(hashes, h) - } - blobsSet = append(blobsSet, blobs) - commitmentsSet = append(commitmentsSet, commitments) - hashesSet = append(hashesSet, hashes) - } - - var txs []*types.Transaction - for i := range blobsSet { - blobs := blobsSet[i] - commitments := commitmentsSet[i] - hashes := hashesSet[i] - - txData := &types.SignedBlobTx{ - Message: types.BlobTxMessage{ - ChainID: view.Uint256View(*uint256.NewInt(1)), - Nonce: view.Uint64View(0), - Gas: view.Uint64View(123457), - GasTipCap: view.Uint256View(*uint256.NewInt(42)), - GasFeeCap: view.Uint256View(*uint256.NewInt(10)), - BlobVersionedHashes: hashes, - }, - } - _, _, aggregatedProof, err := types.Blobs(blobs).ComputeCommitmentsAndAggregatedProof() - if err != nil { - b.Fatal(err) - } - wrapData := &types.BlobTxWrapData{ - BlobKzgs: commitments, - Blobs: blobs, - KzgAggregatedProof: aggregatedProof, - } - txs = append(txs, types.NewTx(txData, types.WithTxWrapData(wrapData))) - } - - b.ResetTimer() - for i := 0; i < b.N; i++ { - for _, tx := range txs { - if err := tx.VerifyBlobs(); err != nil { - b.Fatal(err) - } - } - } - }) - } - - //runBenchmark(2) - //runBenchmark(4) - runBenchmark(8) - runBenchmark(16) -} diff --git a/tests/kzg_test.go b/tests/kzg_test.go deleted file mode 100644 index f3e95385a2..0000000000 --- a/tests/kzg_test.go +++ /dev/null @@ -1,248 +0,0 @@ -// TODO: Migrate these to go-kzg/eth -package tests - -import ( - "encoding/json" - "io/ioutil" - "math" - "testing" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/vm" - - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/params" - - gokzg "github.com/protolambda/go-kzg" - "github.com/protolambda/go-kzg/bls" - "github.com/protolambda/go-kzg/eth" -) - -// Helper: Long polynomial division for two polynomials in coefficient form -func polyLongDiv(dividend []bls.Fr, divisor []bls.Fr) []bls.Fr { - a := make([]bls.Fr, len(dividend)) - for i := 0; i < len(a); i++ { - bls.CopyFr(&a[i], ÷nd[i]) - } - aPos := len(a) - 1 - bPos := len(divisor) - 1 - diff := aPos - bPos - out := make([]bls.Fr, diff+1) - for diff >= 0 { - quot := &out[diff] - bls.DivModFr(quot, &a[aPos], &divisor[bPos]) - var tmp, tmp2 bls.Fr - for i := bPos; i >= 0; i-- { - // In steps: a[diff + i] -= b[i] * quot - // tmp = b[i] * quot - bls.MulModFr(&tmp, quot, &divisor[i]) - // tmp2 = a[diff + i] - tmp - bls.SubModFr(&tmp2, &a[diff+i], &tmp) - // a[diff + i] = tmp2 - bls.CopyFr(&a[diff+i], &tmp2) - } - aPos -= 1 - diff -= 1 - } - return out -} - -// Helper: Compute proof for polynomial -func ComputeProof(poly []bls.Fr, x uint64, crsG1 []bls.G1Point) *bls.G1Point { - // divisor = [-x, 1] - divisor := [2]bls.Fr{} - var tmp bls.Fr - bls.AsFr(&tmp, x) - bls.SubModFr(&divisor[0], &bls.ZERO, &tmp) - bls.CopyFr(&divisor[1], &bls.ONE) - //for i := 0; i < 2; i++ { - // fmt.Printf("div poly %d: %s\n", i, FrStr(&divisor[i])) - //} - // quot = poly / divisor - quotientPolynomial := polyLongDiv(poly, divisor[:]) - //for i := 0; i < len(quotientPolynomial); i++ { - // fmt.Printf("quot poly %d: %s\n", i, FrStr("ientPolynomial[i])) - //} - - // evaluate quotient poly at shared secret, in G1 - return bls.LinCombG1(crsG1[:len(quotientPolynomial)], quotientPolynomial) -} - -// Test the go-kzg library for correctness -// Do the trusted setup, generate a polynomial, commit to it, make proof, verify proof. -func TestGoKzg(t *testing.T) { - // Generate roots of unity - fs := gokzg.NewFFTSettings(uint8(math.Log2(params.FieldElementsPerBlob))) - - // Create a CRS with `n` elements for `s` - s := "1927409816240961209460912649124" - kzgSetupG1, kzgSetupG2 := gokzg.GenerateTestingSetup(s, params.FieldElementsPerBlob) - - // Wrap it all up in KZG settings - kzgSettings := gokzg.NewKZGSettings(fs, kzgSetupG1, kzgSetupG2) - - kzgSetupLagrange, err := fs.FFTG1(kzgSettings.SecretG1[:params.FieldElementsPerBlob], true) - if err != nil { - t.Fatal(err) - } - - // Create testing polynomial (in coefficient form) - polynomial := make([]bls.Fr, params.FieldElementsPerBlob) - for i := uint64(0); i < params.FieldElementsPerBlob; i++ { - bls.CopyFr(&polynomial[i], bls.RandomFr()) - } - - // Get polynomial in evaluation form - evalPoly, err := fs.FFT(polynomial, false) - if err != nil { - t.Fatal(err) - } - - // Get commitments to polynomial - commitmentByCoeffs := kzgSettings.CommitToPoly(polynomial) - commitmentByEval := gokzg.CommitToEvalPoly(kzgSetupLagrange, evalPoly) - if !bls.EqualG1(commitmentByEval, commitmentByCoeffs) { - t.Fatalf("expected commitments to be equal, but got:\nby eval: %s\nby coeffs: %s", - commitmentByEval, commitmentByCoeffs) - } - - // Create proof for testing - x := uint64(17) - proof := ComputeProof(polynomial, x, kzgSetupG1) - - // Get actual evaluation at x - var xFr bls.Fr - bls.AsFr(&xFr, x) - var value bls.Fr - bls.EvalPolyAt(&value, polynomial, &xFr) - - // Check proof against evaluation - if !kzgSettings.CheckProofSingle(commitmentByEval, proof, &xFr, &value) { - t.Fatal("could not verify proof") - } -} - -type JSONTestdataBlobs struct { - KzgBlob1 string - KzgBlob2 string -} - -// Test the optimized VerifyBlobs function -func TestVerifyBlobs(t *testing.T) { - data, err := ioutil.ReadFile("kzg_testdata/kzg_blobs.json") - if err != nil { - t.Fatal(err) - } - - var jsonBlobs JSONTestdataBlobs - err = json.Unmarshal(data, &jsonBlobs) - if err != nil { - t.Fatal(err) - } - - // Pack all those bytes into two blobs - var blob1 types.Blob - var blob2 types.Blob - for i := 0; i < params.FieldElementsPerBlob; i++ { - // Be conservative and only pack 31 bytes per Fr element - copy(blob1[i][:], jsonBlobs.KzgBlob1[i*31:(i+1)*31]) - copy(blob2[i][:], jsonBlobs.KzgBlob2[i*31:(i+1)*31]) - } - // Compute KZG commitments for both of the blobs above - kzg1, ok1 := eth.BlobToKZGCommitment(blob1) - kzg2, ok2 := eth.BlobToKZGCommitment(blob2) - if ok1 == false || ok2 == false { - panic("failed to convert blobs") - } - - // Create the dummy object with all that data we prepared - blobData := types.BlobTxWrapData{ - BlobKzgs: []types.KZGCommitment{types.KZGCommitment(kzg1), types.KZGCommitment(kzg2)}, - Blobs: []types.Blob{types.Blob(blob1), types.Blob(blob2)}, - } - - var hashes []common.Hash - for i := 0; i < len(blobData.BlobKzgs); i++ { - hashes = append(hashes, blobData.BlobKzgs[i].ComputeVersionedHash()) - } - txData := &types.SignedBlobTx{ - Message: types.BlobTxMessage{ - BlobVersionedHashes: hashes, - }, - } - _, _, aggregatedProof, err := blobData.Blobs.ComputeCommitmentsAndAggregatedProof() - if err != nil { - t.Fatalf("bad CommitmentsAndAggregatedProof: %v", err) - } - wrapData := &types.BlobTxWrapData{ - BlobKzgs: blobData.BlobKzgs, - Blobs: blobData.Blobs, - KzgAggregatedProof: aggregatedProof, - } - tx := types.NewTx(txData, types.WithTxWrapData(wrapData)) - - // Verify the blobs against the commitments!! - err = tx.VerifyBlobs() - if err != nil { - t.Fatalf("bad verifyBlobs: %v", err) - } - - // Now let's do a bad case: - // mutate a single chunk of a single blob and VerifyBlobs() must fail - wrapData.Blobs[0][42][1] = 0x42 - tx = types.NewTx(txData, types.WithTxWrapData(wrapData)) - err = tx.VerifyBlobs() - if err == nil { - t.Fatal("bad VerifyBlobs actually succeeded, expected error") - } -} - -// Helper: Create test vector for the PointEvaluation precompile -func TestPointEvaluationTestVector(t *testing.T) { - // Create testing polynomial - polynomial := make([]bls.Fr, params.FieldElementsPerBlob) - for i := uint64(0); i < params.FieldElementsPerBlob; i++ { - bls.CopyFr(&polynomial[i], bls.RandomFr()) - } - - // Create a commitment - commitmentArray := eth.PolynomialToKZGCommitment(polynomial) - - // Create proof for testing - x := uint64(0x42) - xFr := new(bls.Fr) - bls.AsFr(xFr, x) - proofArray, err := eth.ComputeKZGProof(polynomial, xFr) - - // Get actual evaluation at x - yFr := eth.EvaluatePolynomialInEvaluationForm(polynomial, xFr) - yArray := bls.FrTo32(yFr) - xArray := bls.FrTo32(xFr) - - // Verify kzg proof - ok, err := eth.VerifyKZGProof(commitmentArray, xArray, yArray, proofArray) - if err != nil { - t.Fatal(err) - } - if !ok { - t.Fatal("failed proof verification") - } - versionedHash := types.KZGCommitment(commitmentArray).ComputeVersionedHash() - - calldata := append(versionedHash[:], xArray[:]...) - calldata = append(calldata, yArray[:]...) - calldata = append(calldata, commitmentArray[:]...) - calldata = append(calldata, proofArray[:]...) - - t.Logf("test-vector: %x", calldata) - - precompile := vm.PrecompiledContractsDanksharding[common.BytesToAddress([]byte{0x14})] - if _, err := precompile.Run(calldata); err != nil { - t.Fatalf("expected point verification to succeed") - } - // change a byte of the proof - calldata[144+7] ^= 42 - if _, err := precompile.Run(calldata); err == nil { - t.Fatalf("expected point verification to fail") - } -}