2023-07-25 21:57:01 +00:00
|
|
|
package util
|
|
|
|
|
|
|
|
import (
|
|
|
|
"encoding/binary"
|
2023-12-07 02:36:25 +00:00
|
|
|
"math"
|
2023-07-25 21:57:01 +00:00
|
|
|
"math/big"
|
|
|
|
"testing"
|
|
|
|
|
|
|
|
"github.com/ethereum/go-ethereum/common"
|
|
|
|
gethTypes "github.com/ethereum/go-ethereum/core/types"
|
2024-02-15 05:46:47 +00:00
|
|
|
"github.com/prysmaticlabs/prysm/v5/beacon-chain/core/signing"
|
|
|
|
fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams"
|
|
|
|
"github.com/prysmaticlabs/prysm/v5/config/params"
|
|
|
|
"github.com/prysmaticlabs/prysm/v5/consensus-types/blocks"
|
|
|
|
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
|
|
|
|
"github.com/prysmaticlabs/prysm/v5/crypto/bls"
|
|
|
|
"github.com/prysmaticlabs/prysm/v5/encoding/bytesutil"
|
|
|
|
"github.com/prysmaticlabs/prysm/v5/network/forks"
|
|
|
|
enginev1 "github.com/prysmaticlabs/prysm/v5/proto/engine/v1"
|
|
|
|
ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
|
|
|
|
"github.com/prysmaticlabs/prysm/v5/testing/require"
|
|
|
|
"github.com/prysmaticlabs/prysm/v5/time/slots"
|
2023-07-25 21:57:01 +00:00
|
|
|
)
|
|
|
|
|
2023-12-07 02:36:25 +00:00
|
|
|
type DenebBlockGeneratorOption func(*denebBlockGenerator)
|
|
|
|
|
|
|
|
type denebBlockGenerator struct {
|
|
|
|
parent [32]byte
|
|
|
|
slot primitives.Slot
|
|
|
|
nblobs int
|
|
|
|
sign bool
|
|
|
|
sk bls.SecretKey
|
|
|
|
proposer primitives.ValidatorIndex
|
|
|
|
valRoot []byte
|
|
|
|
}
|
|
|
|
|
2024-01-23 07:54:30 +00:00
|
|
|
func WithProposerSigning(idx primitives.ValidatorIndex, sk bls.SecretKey, valRoot []byte) DenebBlockGeneratorOption {
|
2023-12-07 02:36:25 +00:00
|
|
|
return func(g *denebBlockGenerator) {
|
|
|
|
g.sign = true
|
|
|
|
g.proposer = idx
|
|
|
|
g.sk = sk
|
|
|
|
g.valRoot = valRoot
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func GenerateTestDenebBlockWithSidecar(t *testing.T, parent [32]byte, slot primitives.Slot, nblobs int, opts ...DenebBlockGeneratorOption) (blocks.ROBlock, []blocks.ROBlob) {
|
|
|
|
g := &denebBlockGenerator{
|
|
|
|
parent: parent,
|
|
|
|
slot: slot,
|
|
|
|
nblobs: nblobs,
|
|
|
|
}
|
|
|
|
for _, o := range opts {
|
|
|
|
o(g)
|
|
|
|
}
|
2023-07-25 21:57:01 +00:00
|
|
|
stateRoot := bytesutil.PadTo([]byte("stateRoot"), fieldparams.RootLength)
|
|
|
|
receiptsRoot := bytesutil.PadTo([]byte("receiptsRoot"), fieldparams.RootLength)
|
|
|
|
logsBloom := bytesutil.PadTo([]byte("logs"), fieldparams.LogsBloomLength)
|
|
|
|
parentHash := bytesutil.PadTo([]byte("parentHash"), fieldparams.RootLength)
|
2023-11-29 14:28:37 +00:00
|
|
|
ads := common.HexToAddress("095e7baea6a6c7c4c2dfeb977efac326af552d87")
|
|
|
|
tx := gethTypes.NewTx(&gethTypes.LegacyTx{
|
|
|
|
Nonce: 0,
|
|
|
|
To: &ads,
|
|
|
|
Value: big.NewInt(0),
|
|
|
|
Gas: 0,
|
|
|
|
GasPrice: big.NewInt(0),
|
|
|
|
Data: nil,
|
|
|
|
})
|
|
|
|
|
2023-07-25 21:57:01 +00:00
|
|
|
txs := []*gethTypes.Transaction{tx}
|
|
|
|
encodedBinaryTxs := make([][]byte, 1)
|
|
|
|
var err error
|
|
|
|
encodedBinaryTxs[0], err = txs[0].MarshalBinary()
|
|
|
|
require.NoError(t, err)
|
|
|
|
blockHash := bytesutil.ToBytes32([]byte("foo"))
|
|
|
|
payload := &enginev1.ExecutionPayloadDeneb{
|
|
|
|
ParentHash: parentHash,
|
|
|
|
FeeRecipient: make([]byte, fieldparams.FeeRecipientLength),
|
|
|
|
StateRoot: stateRoot,
|
|
|
|
ReceiptsRoot: receiptsRoot,
|
|
|
|
LogsBloom: logsBloom,
|
|
|
|
PrevRandao: blockHash[:],
|
|
|
|
BlockNumber: 0,
|
|
|
|
GasLimit: 0,
|
|
|
|
GasUsed: 0,
|
|
|
|
Timestamp: 0,
|
|
|
|
ExtraData: make([]byte, 0),
|
|
|
|
BaseFeePerGas: bytesutil.PadTo([]byte("baseFeePerGas"), fieldparams.RootLength),
|
|
|
|
BlockHash: blockHash[:],
|
|
|
|
Transactions: encodedBinaryTxs,
|
2024-01-09 21:49:35 +00:00
|
|
|
Withdrawals: make([]*enginev1.Withdrawal, 0),
|
|
|
|
BlobGasUsed: 0,
|
|
|
|
ExcessBlobGas: 0,
|
2023-07-25 21:57:01 +00:00
|
|
|
}
|
|
|
|
block := NewBeaconBlockDeneb()
|
|
|
|
block.Block.Body.ExecutionPayload = payload
|
2023-12-07 02:36:25 +00:00
|
|
|
block.Block.Slot = g.slot
|
|
|
|
block.Block.ParentRoot = g.parent[:]
|
2024-01-23 07:54:30 +00:00
|
|
|
block.Block.ProposerIndex = g.proposer
|
2023-12-07 02:36:25 +00:00
|
|
|
commitments := make([][48]byte, g.nblobs)
|
|
|
|
block.Block.Body.BlobKzgCommitments = make([][]byte, g.nblobs)
|
2023-07-25 21:57:01 +00:00
|
|
|
for i := range commitments {
|
|
|
|
binary.LittleEndian.PutUint16(commitments[i][0:16], uint16(i))
|
2023-12-07 02:36:25 +00:00
|
|
|
binary.LittleEndian.PutUint16(commitments[i][16:32], uint16(g.slot))
|
2023-07-25 21:57:01 +00:00
|
|
|
block.Block.Body.BlobKzgCommitments[i] = commitments[i][:]
|
|
|
|
}
|
|
|
|
|
2023-12-07 02:36:25 +00:00
|
|
|
body, err := blocks.NewBeaconBlockBody(block.Block.Body)
|
|
|
|
require.NoError(t, err)
|
|
|
|
inclusion := make([][][]byte, len(commitments))
|
|
|
|
for i := range commitments {
|
|
|
|
proof, err := blocks.MerkleProofKZGCommitment(body, i)
|
|
|
|
require.NoError(t, err)
|
|
|
|
inclusion[i] = proof
|
|
|
|
}
|
|
|
|
if g.sign {
|
|
|
|
epoch := slots.ToEpoch(block.Block.Slot)
|
|
|
|
schedule := forks.NewOrderedSchedule(params.BeaconConfig())
|
|
|
|
version, err := schedule.VersionForEpoch(epoch)
|
|
|
|
require.NoError(t, err)
|
|
|
|
fork, err := schedule.ForkFromVersion(version)
|
|
|
|
require.NoError(t, err)
|
|
|
|
domain := params.BeaconConfig().DomainBeaconProposer
|
|
|
|
sig, err := signing.ComputeDomainAndSignWithoutState(fork, epoch, domain, g.valRoot, block.Block, g.sk)
|
|
|
|
require.NoError(t, err)
|
|
|
|
block.Signature = sig
|
|
|
|
}
|
|
|
|
|
2023-07-25 21:57:01 +00:00
|
|
|
root, err := block.Block.HashTreeRoot()
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
2023-11-21 18:44:38 +00:00
|
|
|
sidecars := make([]blocks.ROBlob, len(commitments))
|
|
|
|
sbb, err := blocks.NewSignedBeaconBlock(block)
|
|
|
|
require.NoError(t, err)
|
2023-11-29 14:28:37 +00:00
|
|
|
|
2023-11-21 18:44:38 +00:00
|
|
|
sh, err := sbb.Header()
|
|
|
|
require.NoError(t, err)
|
2023-07-25 21:57:01 +00:00
|
|
|
for i, c := range block.Block.Body.BlobKzgCommitments {
|
2023-12-07 02:36:25 +00:00
|
|
|
sidecars[i] = GenerateTestDenebBlobSidecar(t, root, sh, i, c, inclusion[i])
|
2023-07-25 21:57:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
rob, err := blocks.NewROBlock(sbb)
|
|
|
|
require.NoError(t, err)
|
|
|
|
return rob, sidecars
|
|
|
|
}
|
|
|
|
|
2023-12-07 02:36:25 +00:00
|
|
|
func GenerateTestDenebBlobSidecar(t *testing.T, root [32]byte, header *ethpb.SignedBeaconBlockHeader, index int, commitment []byte, incProof [][]byte) blocks.ROBlob {
|
2023-11-21 18:44:38 +00:00
|
|
|
blob := make([]byte, fieldparams.BlobSize)
|
|
|
|
binary.LittleEndian.PutUint64(blob, uint64(index))
|
|
|
|
pb := ðpb.BlobSidecar{
|
|
|
|
SignedBlockHeader: header,
|
|
|
|
Index: uint64(index),
|
|
|
|
Blob: blob,
|
|
|
|
KzgCommitment: commitment,
|
|
|
|
KzgProof: commitment,
|
|
|
|
}
|
2023-12-07 02:36:25 +00:00
|
|
|
if len(incProof) == 0 {
|
|
|
|
incProof = fakeEmptyProof(t, pb)
|
|
|
|
}
|
|
|
|
pb.CommitmentInclusionProof = incProof
|
2023-11-21 18:44:38 +00:00
|
|
|
r, err := blocks.NewROBlobWithRoot(pb, root)
|
|
|
|
require.NoError(t, err)
|
|
|
|
return r
|
|
|
|
}
|
|
|
|
|
|
|
|
func fakeEmptyProof(_ *testing.T, _ *ethpb.BlobSidecar) [][]byte {
|
|
|
|
r := make([][]byte, fieldparams.KzgCommitmentInclusionProofDepth)
|
|
|
|
for i := range r {
|
|
|
|
r[i] = make([]byte, fieldparams.RootLength)
|
|
|
|
}
|
|
|
|
return r
|
|
|
|
}
|
|
|
|
|
|
|
|
func ExtendBlocksPlusBlobs(t *testing.T, blks []blocks.ROBlock, size int) ([]blocks.ROBlock, []blocks.ROBlob) {
|
|
|
|
blobs := make([]blocks.ROBlob, 0)
|
2023-07-25 21:57:01 +00:00
|
|
|
if len(blks) == 0 {
|
|
|
|
blk, blb := GenerateTestDenebBlockWithSidecar(t, [32]byte{}, 0, 6)
|
|
|
|
blobs = append(blobs, blb...)
|
|
|
|
blks = append(blks, blk)
|
|
|
|
}
|
|
|
|
|
|
|
|
for i := 0; i < size; i++ {
|
|
|
|
prev := blks[len(blks)-1]
|
|
|
|
blk, blb := GenerateTestDenebBlockWithSidecar(t, prev.Root(), prev.Block().Slot()+1, 6)
|
|
|
|
blobs = append(blobs, blb...)
|
|
|
|
blks = append(blks, blk)
|
|
|
|
}
|
|
|
|
|
|
|
|
return blks, blobs
|
|
|
|
}
|
2023-12-07 02:36:25 +00:00
|
|
|
|
2024-01-09 22:14:03 +00:00
|
|
|
// HackDenebMaxuint is helpful for tests that need to set up cases where the deneb fork has passed.
|
2023-12-07 02:36:25 +00:00
|
|
|
// We have unit tests that assert our config matches the upstream config, where the next fork is always
|
|
|
|
// set to MaxUint64 until the fork epoch is formally set. This creates an issue for tests that want to
|
|
|
|
// work with slots that are defined to be after deneb because converting the max epoch to a slot leads
|
|
|
|
// to multiplication overflow.
|
|
|
|
// Monkey patching tests with this function is the simplest workaround in these cases.
|
|
|
|
func HackDenebMaxuint(t *testing.T) func() {
|
|
|
|
bc := params.MainnetConfig().Copy()
|
|
|
|
bc.DenebForkEpoch = math.MaxUint32
|
|
|
|
undo, err := params.SetActiveWithUndo(bc)
|
|
|
|
require.NoError(t, err)
|
|
|
|
return func() {
|
|
|
|
require.NoError(t, undo())
|
|
|
|
}
|
|
|
|
}
|