mirror of
https://github.com/OffchainLabs/prysm.git
synced 2026-01-09 23:48:06 -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"
|
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 {
|
func (f *FieldTrie) validateIndices(idxs []uint64) error {
|
||||||
length := f.length
|
length := f.length
|
||||||
if f.dataType == types.CompressedArray {
|
if f.dataType == types.CompressedArray {
|
||||||
|
|||||||
@@ -67,6 +67,7 @@ go_library(
|
|||||||
"//consensus-types/primitives:go_default_library",
|
"//consensus-types/primitives:go_default_library",
|
||||||
"//container/multi-value-slice:go_default_library",
|
"//container/multi-value-slice:go_default_library",
|
||||||
"//container/slice:go_default_library",
|
"//container/slice:go_default_library",
|
||||||
|
"//container/trie:go_default_library",
|
||||||
"//crypto/bls:go_default_library",
|
"//crypto/bls:go_default_library",
|
||||||
"//crypto/hash:go_default_library",
|
"//crypto/hash:go_default_library",
|
||||||
"//encoding/bytesutil:go_default_library",
|
"//encoding/bytesutil:go_default_library",
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"encoding/binary"
|
"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/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/encoding/bytesutil"
|
||||||
"github.com/prysmaticlabs/prysm/v5/runtime/version"
|
"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 {
|
if err := b.recomputeDirtyFields(ctx); err != nil {
|
||||||
return nil, err
|
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.
|
// 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 {
|
if err := b.recomputeDirtyFields(ctx); err != nil {
|
||||||
return nil, err
|
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
|
// 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)
|
epochRoot := bytesutil.ToBytes32(epochBuf)
|
||||||
proof := make([][]byte, 0)
|
proof := make([][]byte, 0)
|
||||||
proof = append(proof, epochRoot[:])
|
proof = append(proof, epochRoot[:])
|
||||||
branch := fieldtrie.ProofFromMerkleLayers(b.merkleLayers, types.FinalizedCheckpoint.RealPosition())
|
branch := trie.ProofFromMerkleLayers(b.merkleLayers, types.FinalizedCheckpoint.RealPosition())
|
||||||
proof = append(proof, branch...)
|
proof = append(proof, branch...)
|
||||||
return proof, nil
|
return proof, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ go_library(
|
|||||||
importpath = "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks",
|
importpath = "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks",
|
||||||
visibility = ["//visibility:public"],
|
visibility = ["//visibility:public"],
|
||||||
deps = [
|
deps = [
|
||||||
|
"//beacon-chain/state/stateutil:go_default_library",
|
||||||
"//config/fieldparams:go_default_library",
|
"//config/fieldparams:go_default_library",
|
||||||
"//config/params:go_default_library",
|
"//config/params:go_default_library",
|
||||||
"//consensus-types:go_default_library",
|
"//consensus-types:go_default_library",
|
||||||
|
|||||||
@@ -3,15 +3,23 @@ package blocks
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/prysmaticlabs/prysm/v5/beacon-chain/state/stateutil"
|
||||||
"github.com/prysmaticlabs/prysm/v5/config/params"
|
"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/crypto/hash/htr"
|
||||||
"github.com/prysmaticlabs/prysm/v5/encoding/ssz"
|
"github.com/prysmaticlabs/prysm/v5/encoding/ssz"
|
||||||
"github.com/prysmaticlabs/prysm/v5/runtime/version"
|
"github.com/prysmaticlabs/prysm/v5/runtime/version"
|
||||||
"go.opencensus.io/trace"
|
"go.opencensus.io/trace"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
payloadFieldIndex = 9
|
||||||
|
bodyFieldIndex = 4
|
||||||
|
)
|
||||||
|
|
||||||
func ComputeBlockBodyFieldRoots(ctx context.Context, blockBody *BeaconBlockBody) ([][]byte, error) {
|
func ComputeBlockBodyFieldRoots(ctx context.Context, blockBody *BeaconBlockBody) ([][]byte, error) {
|
||||||
_, span := trace.StartSpan(ctx, "blocks.ComputeBlockBodyFieldRoots")
|
_, span := trace.StartSpan(ctx, "blocks.ComputeBlockBodyFieldRoots")
|
||||||
defer span.End()
|
defer span.End()
|
||||||
@@ -172,3 +180,68 @@ func ComputeBlockBodyFieldRoots(ctx context.Context, blockBody *BeaconBlockBody)
|
|||||||
|
|
||||||
return fieldRoots, nil
|
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)
|
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