mirror of
https://gitlab.com/pulsechaincom/prysm-pulse.git
synced 2024-12-22 03:30:35 +00:00
KZG Commitment inclusion proof verifier (#13174)
Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
This commit is contained in:
parent
3097601530
commit
e46f9c5631
@ -15,12 +15,39 @@ const (
|
||||
bodyLength = 12 // The number of elements in the BeaconBlockBody Container
|
||||
logBodyLength = 4 // The log 2 of bodyLength
|
||||
kzgPosition = 11 // The index of the KZG commitment list in the Body
|
||||
KZGOffset = 54 * field_params.MaxBlobCommitmentsPerBlock
|
||||
)
|
||||
|
||||
var (
|
||||
errInvalidIndex = errors.New("index out of bounds")
|
||||
errInvalidIndex = errors.New("index out of bounds")
|
||||
errInvalidBodyRoot = errors.New("invalid Beacon Block Body root")
|
||||
errInvalidInclusionProof = errors.New("invalid KZG commitment inclusion proof")
|
||||
)
|
||||
|
||||
// VerifyKZGIncusionProof verifies the Merkle proof in a Blob sidecar against
|
||||
// the beacon block body root.
|
||||
func VerifyKZGInclusionProof(blob ROBlob) error {
|
||||
if blob.SignedBlockHeader == nil {
|
||||
return errNilBlockHeader
|
||||
}
|
||||
if blob.SignedBlockHeader.Header == nil {
|
||||
return errNilBlockHeader
|
||||
}
|
||||
root := blob.SignedBlockHeader.Header.BodyRoot
|
||||
if len(root) != field_params.RootLength {
|
||||
return errInvalidBodyRoot
|
||||
}
|
||||
chunks := make([][32]byte, 2)
|
||||
copy(chunks[0][:], blob.KzgCommitment)
|
||||
copy(chunks[1][:], blob.KzgCommitment[field_params.RootLength:])
|
||||
gohashtree.HashChunks(chunks, chunks)
|
||||
verified := trie.VerifyMerkleProof(root, chunks[0][:], blob.Index+KZGOffset, blob.CommitmentInclusionProof)
|
||||
if !verified {
|
||||
return errInvalidInclusionProof
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// MerkleProofKZGCommitment constructs a Merkle proof of inclusion of the KZG
|
||||
// commitment of index `index` into the Beacon Block with the given `body`
|
||||
func MerkleProofKZGCommitment(body interfaces.ReadOnlyBeaconBlockBody, index int) ([][]byte, error) {
|
||||
|
@ -128,3 +128,67 @@ func Benchmark_MerkleProofKZGCommitment(b *testing.B) {
|
||||
require.NoError(b, err)
|
||||
}
|
||||
}
|
||||
|
||||
func Test_VerifyKZGInclusionProof(t *testing.T) {
|
||||
kzgs := make([][]byte, 3)
|
||||
kzgs[0] = make([]byte, 48)
|
||||
_, err := rand.Read(kzgs[0])
|
||||
require.NoError(t, err)
|
||||
kzgs[1] = make([]byte, 48)
|
||||
_, err = rand.Read(kzgs[1])
|
||||
require.NoError(t, err)
|
||||
kzgs[2] = make([]byte, 48)
|
||||
_, err = rand.Read(kzgs[2])
|
||||
require.NoError(t, err)
|
||||
pbBody := ðpb.BeaconBlockBodyDeneb{
|
||||
SyncAggregate: ðpb.SyncAggregate{
|
||||
SyncCommitteeBits: make([]byte, fieldparams.SyncAggregateSyncCommitteeBytesLength),
|
||||
SyncCommitteeSignature: make([]byte, fieldparams.BLSSignatureLength),
|
||||
},
|
||||
ExecutionPayload: &enginev1.ExecutionPayloadDeneb{
|
||||
ParentHash: make([]byte, fieldparams.RootLength),
|
||||
FeeRecipient: make([]byte, 20),
|
||||
StateRoot: make([]byte, fieldparams.RootLength),
|
||||
ReceiptsRoot: make([]byte, fieldparams.RootLength),
|
||||
LogsBloom: make([]byte, 256),
|
||||
PrevRandao: make([]byte, fieldparams.RootLength),
|
||||
BaseFeePerGas: make([]byte, fieldparams.RootLength),
|
||||
BlockHash: make([]byte, fieldparams.RootLength),
|
||||
Transactions: make([][]byte, 0),
|
||||
ExtraData: make([]byte, 0),
|
||||
},
|
||||
Eth1Data: ðpb.Eth1Data{
|
||||
DepositRoot: make([]byte, fieldparams.RootLength),
|
||||
BlockHash: make([]byte, fieldparams.RootLength),
|
||||
},
|
||||
BlobKzgCommitments: kzgs,
|
||||
}
|
||||
|
||||
body, err := NewBeaconBlockBody(pbBody)
|
||||
require.NoError(t, err)
|
||||
root, err := body.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
index := 1
|
||||
proof, err := MerkleProofKZGCommitment(body, index)
|
||||
require.NoError(t, err)
|
||||
|
||||
header := ðpb.BeaconBlockHeader{
|
||||
BodyRoot: root[:],
|
||||
ParentRoot: make([]byte, 32),
|
||||
StateRoot: make([]byte, 32),
|
||||
}
|
||||
signedHeader := ðpb.SignedBeaconBlockHeader{
|
||||
Header: header,
|
||||
}
|
||||
sidecar := ðpb.BlobSidecar{
|
||||
Index: uint64(index),
|
||||
KzgCommitment: kzgs[index],
|
||||
CommitmentInclusionProof: proof,
|
||||
SignedBlockHeader: signedHeader,
|
||||
}
|
||||
blob, err := NewROBlob(sidecar)
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, VerifyKZGInclusionProof(blob))
|
||||
proof[2] = make([]byte, 32)
|
||||
require.ErrorIs(t, errInvalidInclusionProof, VerifyKZGInclusionProof(blob))
|
||||
}
|
||||
|
@ -18,8 +18,6 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/v4/testing/util"
|
||||
)
|
||||
|
||||
const kzgOffset = 54 * field_params.MaxBlobCommitmentsPerBlock
|
||||
|
||||
// SingleMerkleProof is the format used to read spectest Merkle Proof test data.
|
||||
type SingleMerkleProof struct {
|
||||
Leaf string `json:"leaf"`
|
||||
@ -83,10 +81,10 @@ func runSingleMerkleProofTests(t *testing.T, config, forkOrPhase string, unmarsh
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if index < kzgOffset || index > kzgOffset+field_params.MaxBlobsPerBlock {
|
||||
if index < consensus_blocks.KZGOffset || index > consensus_blocks.KZGOffset+field_params.MaxBlobsPerBlock {
|
||||
return
|
||||
}
|
||||
localProof, err := consensus_blocks.MerkleProofKZGCommitment(body, int(index-kzgOffset))
|
||||
localProof, err := consensus_blocks.MerkleProofKZGCommitment(body, int(index-consensus_blocks.KZGOffset))
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, len(branch), len(localProof))
|
||||
for i, root := range localProof {
|
||||
|
Loading…
Reference in New Issue
Block a user