mirror of
https://github.com/OffchainLabs/prysm.git
synced 2026-01-08 07:03:58 -05:00
feat: implement PayloadProof function (#14356)
* feat: implement function `PayloadProof` to calculate proof of execution payload * remove comments * feat: implement function to compute field roots of * feat: implement function to compute `BeaconBlock` field roots and add tests * fix dependencies * check if interface implements the assserted type * fix: lint * replace `ok != true` with `!ok` * remove unused parameter from `PayloadProof` * remove test and move `PayloadProof` to `blocks/proofs.go` * remove `PayloadProof` from `fieldtrie` * replace `fieldtrie.ProofFromMerkleLayers` with `trie.ProofFromMerkleLayers` * Update container/trie/sparse_merkle.go * update dependencies --------- Co-authored-by: Radosław Kapka <rkapka@wp.pl> Co-authored-by: Radosław Kapka <radoslaw.kapka@gmail.com>
This commit is contained in:
@@ -14,21 +14,6 @@ import (
|
||||
ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
|
||||
)
|
||||
|
||||
// ProofFromMerkleLayers creates a proof starting at the leaf index of the state Merkle layers.
|
||||
func ProofFromMerkleLayers(layers [][][]byte, startingLeafIndex int) [][]byte {
|
||||
// The merkle tree structure looks as follows:
|
||||
// [[r1, r2, r3, r4], [parent1, parent2], [root]]
|
||||
proof := make([][]byte, 0)
|
||||
currentIndex := startingLeafIndex
|
||||
for i := 0; i < len(layers)-1; i++ {
|
||||
neighborIdx := currentIndex ^ 1
|
||||
neighbor := layers[i][neighborIdx]
|
||||
proof = append(proof, neighbor)
|
||||
currentIndex = currentIndex / 2
|
||||
}
|
||||
return proof
|
||||
}
|
||||
|
||||
func (f *FieldTrie) validateIndices(idxs []uint64) error {
|
||||
length := f.length
|
||||
if f.dataType == types.CompressedArray {
|
||||
|
||||
@@ -67,6 +67,7 @@ go_library(
|
||||
"//consensus-types/primitives:go_default_library",
|
||||
"//container/multi-value-slice:go_default_library",
|
||||
"//container/slice:go_default_library",
|
||||
"//container/trie:go_default_library",
|
||||
"//crypto/bls:go_default_library",
|
||||
"//crypto/hash:go_default_library",
|
||||
"//encoding/bytesutil:go_default_library",
|
||||
|
||||
@@ -4,8 +4,8 @@ import (
|
||||
"context"
|
||||
"encoding/binary"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/v5/beacon-chain/state/fieldtrie"
|
||||
"github.com/prysmaticlabs/prysm/v5/beacon-chain/state/state-native/types"
|
||||
"github.com/prysmaticlabs/prysm/v5/container/trie"
|
||||
"github.com/prysmaticlabs/prysm/v5/encoding/bytesutil"
|
||||
"github.com/prysmaticlabs/prysm/v5/runtime/version"
|
||||
)
|
||||
@@ -56,7 +56,7 @@ func (b *BeaconState) CurrentSyncCommitteeProof(ctx context.Context) ([][]byte,
|
||||
if err := b.recomputeDirtyFields(ctx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return fieldtrie.ProofFromMerkleLayers(b.merkleLayers, types.CurrentSyncCommittee.RealPosition()), nil
|
||||
return trie.ProofFromMerkleLayers(b.merkleLayers, types.CurrentSyncCommittee.RealPosition()), nil
|
||||
}
|
||||
|
||||
// NextSyncCommitteeProof from the state's Merkle trie representation.
|
||||
@@ -74,7 +74,7 @@ func (b *BeaconState) NextSyncCommitteeProof(ctx context.Context) ([][]byte, err
|
||||
if err := b.recomputeDirtyFields(ctx); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return fieldtrie.ProofFromMerkleLayers(b.merkleLayers, types.NextSyncCommittee.RealPosition()), nil
|
||||
return trie.ProofFromMerkleLayers(b.merkleLayers, types.NextSyncCommittee.RealPosition()), nil
|
||||
}
|
||||
|
||||
// FinalizedRootProof crafts a Merkle proof for the finalized root
|
||||
@@ -102,7 +102,7 @@ func (b *BeaconState) FinalizedRootProof(ctx context.Context) ([][]byte, error)
|
||||
epochRoot := bytesutil.ToBytes32(epochBuf)
|
||||
proof := make([][]byte, 0)
|
||||
proof = append(proof, epochRoot[:])
|
||||
branch := fieldtrie.ProofFromMerkleLayers(b.merkleLayers, types.FinalizedCheckpoint.RealPosition())
|
||||
branch := trie.ProofFromMerkleLayers(b.merkleLayers, types.FinalizedCheckpoint.RealPosition())
|
||||
proof = append(proof, branch...)
|
||||
return proof, nil
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ go_library(
|
||||
importpath = "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//beacon-chain/state/stateutil:go_default_library",
|
||||
"//config/fieldparams:go_default_library",
|
||||
"//config/params:go_default_library",
|
||||
"//consensus-types:go_default_library",
|
||||
|
||||
@@ -3,15 +3,23 @@ package blocks
|
||||
import (
|
||||
"context"
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/v5/beacon-chain/state/stateutil"
|
||||
"github.com/prysmaticlabs/prysm/v5/config/params"
|
||||
"github.com/prysmaticlabs/prysm/v5/container/trie"
|
||||
"github.com/prysmaticlabs/prysm/v5/crypto/hash/htr"
|
||||
"github.com/prysmaticlabs/prysm/v5/encoding/ssz"
|
||||
"github.com/prysmaticlabs/prysm/v5/runtime/version"
|
||||
"go.opencensus.io/trace"
|
||||
)
|
||||
|
||||
const (
|
||||
payloadFieldIndex = 9
|
||||
bodyFieldIndex = 4
|
||||
)
|
||||
|
||||
func ComputeBlockBodyFieldRoots(ctx context.Context, blockBody *BeaconBlockBody) ([][]byte, error) {
|
||||
_, span := trace.StartSpan(ctx, "blocks.ComputeBlockBodyFieldRoots")
|
||||
defer span.End()
|
||||
@@ -172,3 +180,68 @@ func ComputeBlockBodyFieldRoots(ctx context.Context, blockBody *BeaconBlockBody)
|
||||
|
||||
return fieldRoots, nil
|
||||
}
|
||||
|
||||
func ComputeBlockFieldRoots(ctx context.Context, block *BeaconBlock) ([][]byte, error) {
|
||||
_, span := trace.StartSpan(ctx, "blocks.ComputeBlockFieldRoots")
|
||||
defer span.End()
|
||||
|
||||
if block == nil {
|
||||
return nil, errNilBlock
|
||||
}
|
||||
|
||||
fieldRoots := make([][]byte, 5)
|
||||
for i := range fieldRoots {
|
||||
fieldRoots[i] = make([]byte, 32)
|
||||
}
|
||||
|
||||
// Slot
|
||||
slotRoot := ssz.Uint64Root(uint64(block.slot))
|
||||
copy(fieldRoots[0], slotRoot[:])
|
||||
|
||||
// Proposer Index
|
||||
proposerRoot := ssz.Uint64Root(uint64(block.proposerIndex))
|
||||
copy(fieldRoots[1], proposerRoot[:])
|
||||
|
||||
// Parent Root
|
||||
copy(fieldRoots[2], block.parentRoot[:])
|
||||
|
||||
// State Root
|
||||
copy(fieldRoots[3], block.stateRoot[:])
|
||||
|
||||
// block body Root
|
||||
blockBodyRoot, err := block.body.HashTreeRoot()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
copy(fieldRoots[4], blockBodyRoot[:])
|
||||
|
||||
return fieldRoots, nil
|
||||
}
|
||||
|
||||
func PayloadProof(ctx context.Context, block *BeaconBlock) ([][]byte, error) {
|
||||
i := block.Body()
|
||||
blockBody, ok := i.(*BeaconBlockBody)
|
||||
if !ok {
|
||||
return nil, errors.New("failed to cast block body")
|
||||
}
|
||||
|
||||
blockBodyFieldRoots, err := ComputeBlockBodyFieldRoots(ctx, blockBody)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
blockBodyFieldRootsTrie := stateutil.Merkleize(blockBodyFieldRoots)
|
||||
blockBodyProof := trie.ProofFromMerkleLayers(blockBodyFieldRootsTrie, payloadFieldIndex)
|
||||
|
||||
beaconBlockFieldRoots, err := ComputeBlockFieldRoots(ctx, block)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
beaconBlockFieldRootsTrie := stateutil.Merkleize(beaconBlockFieldRoots)
|
||||
beaconBlockProof := trie.ProofFromMerkleLayers(beaconBlockFieldRootsTrie, bodyFieldIndex)
|
||||
|
||||
finalProof := append(blockBodyProof, beaconBlockProof...)
|
||||
|
||||
return finalProof, nil
|
||||
}
|
||||
|
||||
@@ -259,3 +259,18 @@ func (m *SparseMerkleTrie) NumOfItems() int {
|
||||
}
|
||||
return len(m.originalItems)
|
||||
}
|
||||
|
||||
// ProofFromMerkleLayers creates a proof starting at the leaf index of the merkle layers.
|
||||
func ProofFromMerkleLayers(layers [][][]byte, startingLeafIndex int) [][]byte {
|
||||
// The merkle tree structure looks as follows:
|
||||
// [[r1, r2, r3, r4], [parent1, parent2], [root]]
|
||||
proof := make([][]byte, 0)
|
||||
currentIndex := startingLeafIndex
|
||||
for i := 0; i < len(layers)-1; i++ {
|
||||
neighborIdx := currentIndex ^ 1
|
||||
neighbor := layers[i][neighborIdx]
|
||||
proof = append(proof, neighbor)
|
||||
currentIndex = currentIndex / 2
|
||||
}
|
||||
return proof
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user