mirror of
https://github.com/OffchainLabs/prysm.git
synced 2026-01-08 23:18:15 -05:00
fulu lc (#15995)
Co-authored-by: james-prysm <90280386+james-prysm@users.noreply.github.com>
This commit is contained in:
@@ -2804,7 +2804,7 @@ func TestProcessLightClientUpdate(t *testing.T) {
|
||||
require.NoError(t, s.cfg.BeaconDB.SaveState(ctx, headState, [32]byte{1, 2}))
|
||||
require.NoError(t, s.cfg.BeaconDB.SaveHeadBlockRoot(ctx, [32]byte{1, 2}))
|
||||
|
||||
for testVersion := version.Altair; testVersion <= version.Electra; testVersion++ {
|
||||
for _, testVersion := range version.All()[1:] {
|
||||
t.Run(version.String(testVersion), func(t *testing.T) {
|
||||
l := util.NewTestLightClient(t, testVersion)
|
||||
|
||||
|
||||
@@ -181,6 +181,13 @@ func decodeLightClientBootstrap(enc []byte) (interfaces.LightClientBootstrap, []
|
||||
}
|
||||
m = bootstrap
|
||||
syncCommitteeHash = enc[len(ElectraKey) : len(ElectraKey)+32]
|
||||
case hasFuluKey(enc):
|
||||
bootstrap := ðpb.LightClientBootstrapElectra{}
|
||||
if err := bootstrap.UnmarshalSSZ(enc[len(fuluKey)+32:]); err != nil {
|
||||
return nil, nil, errors.Wrap(err, "could not unmarshal Electra light client bootstrap")
|
||||
}
|
||||
m = bootstrap
|
||||
syncCommitteeHash = enc[len(fuluKey) : len(fuluKey)+32]
|
||||
default:
|
||||
return nil, nil, errors.New("decoding of saved light client bootstrap is unsupported")
|
||||
}
|
||||
@@ -296,6 +303,12 @@ func decodeLightClientUpdate(enc []byte) (interfaces.LightClientUpdate, error) {
|
||||
return nil, errors.Wrap(err, "could not unmarshal Electra light client update")
|
||||
}
|
||||
m = update
|
||||
case hasFuluKey(enc):
|
||||
update := ðpb.LightClientUpdateElectra{}
|
||||
if err := update.UnmarshalSSZ(enc[len(fuluKey):]); err != nil {
|
||||
return nil, errors.Wrap(err, "could not unmarshal Fulu light client update")
|
||||
}
|
||||
m = update
|
||||
default:
|
||||
return nil, errors.New("decoding of saved light client update is unsupported")
|
||||
}
|
||||
@@ -304,6 +317,8 @@ func decodeLightClientUpdate(enc []byte) (interfaces.LightClientUpdate, error) {
|
||||
|
||||
func keyForLightClientUpdate(v int) ([]byte, error) {
|
||||
switch v {
|
||||
case version.Fulu:
|
||||
return fuluKey, nil
|
||||
case version.Electra:
|
||||
return ElectraKey, nil
|
||||
case version.Deneb:
|
||||
|
||||
@@ -215,8 +215,7 @@ func TestStore_LightClientUpdate_CanSaveRetrieve(t *testing.T) {
|
||||
|
||||
db := setupDB(t)
|
||||
ctx := t.Context()
|
||||
|
||||
for testVersion := version.Altair; testVersion <= version.Electra; testVersion++ {
|
||||
for _, testVersion := range version.All()[1:] {
|
||||
t.Run(version.String(testVersion), func(t *testing.T) {
|
||||
update, err := createUpdate(t, testVersion)
|
||||
require.NoError(t, err)
|
||||
@@ -572,8 +571,7 @@ func TestStore_LightClientBootstrap_CanSaveRetrieve(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
require.IsNil(t, retrievedBootstrap)
|
||||
})
|
||||
|
||||
for testVersion := version.Altair; testVersion <= version.Electra; testVersion++ {
|
||||
for _, testVersion := range version.All()[1:] {
|
||||
t.Run(version.String(testVersion), func(t *testing.T) {
|
||||
bootstrap, err := createDefaultLightClientBootstrap(primitives.Slot(uint64(params.BeaconConfig().VersionToForkEpochMap()[testVersion]) * uint64(params.BeaconConfig().SlotsPerEpoch)))
|
||||
require.NoError(t, err)
|
||||
|
||||
@@ -29,58 +29,22 @@ func TestLightClient_NewLightClientOptimisticUpdateFromBeaconState(t *testing.T)
|
||||
cfg.CapellaForkEpoch = 3
|
||||
cfg.DenebForkEpoch = 4
|
||||
cfg.ElectraForkEpoch = 5
|
||||
cfg.FuluForkEpoch = 6
|
||||
params.OverrideBeaconConfig(cfg)
|
||||
|
||||
t.Run("Altair", func(t *testing.T) {
|
||||
l := util.NewTestLightClient(t, version.Altair)
|
||||
for _, testVersion := range version.All()[1:] {
|
||||
t.Run(version.String(testVersion), func(t *testing.T) {
|
||||
l := util.NewTestLightClient(t, testVersion)
|
||||
|
||||
update, err := lightClient.NewLightClientOptimisticUpdateFromBeaconState(l.Ctx, l.State, l.Block, l.AttestedState, l.AttestedBlock)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, update, "update is nil")
|
||||
require.Equal(t, l.Block.Block().Slot(), update.SignatureSlot(), "Signature slot is not equal")
|
||||
update, err := lightClient.NewLightClientOptimisticUpdateFromBeaconState(l.Ctx, l.State, l.Block, l.AttestedState, l.AttestedBlock)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, update, "update is nil")
|
||||
require.Equal(t, l.Block.Block().Slot(), update.SignatureSlot(), "Signature slot is not equal")
|
||||
|
||||
l.CheckSyncAggregate(update.SyncAggregate())
|
||||
l.CheckAttestedHeader(update.AttestedHeader())
|
||||
})
|
||||
|
||||
t.Run("Capella", func(t *testing.T) {
|
||||
l := util.NewTestLightClient(t, version.Capella)
|
||||
|
||||
update, err := lightClient.NewLightClientOptimisticUpdateFromBeaconState(l.Ctx, l.State, l.Block, l.AttestedState, l.AttestedBlock)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, update, "update is nil")
|
||||
|
||||
require.Equal(t, l.Block.Block().Slot(), update.SignatureSlot(), "Signature slot is not equal")
|
||||
|
||||
l.CheckSyncAggregate(update.SyncAggregate())
|
||||
l.CheckAttestedHeader(update.AttestedHeader())
|
||||
})
|
||||
|
||||
t.Run("Deneb", func(t *testing.T) {
|
||||
l := util.NewTestLightClient(t, version.Deneb)
|
||||
|
||||
update, err := lightClient.NewLightClientOptimisticUpdateFromBeaconState(l.Ctx, l.State, l.Block, l.AttestedState, l.AttestedBlock)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, update, "update is nil")
|
||||
|
||||
require.Equal(t, l.Block.Block().Slot(), update.SignatureSlot(), "Signature slot is not equal")
|
||||
|
||||
l.CheckSyncAggregate(update.SyncAggregate())
|
||||
l.CheckAttestedHeader(update.AttestedHeader())
|
||||
})
|
||||
|
||||
t.Run("Electra", func(t *testing.T) {
|
||||
l := util.NewTestLightClient(t, version.Electra)
|
||||
|
||||
update, err := lightClient.NewLightClientOptimisticUpdateFromBeaconState(l.Ctx, l.State, l.Block, l.AttestedState, l.AttestedBlock)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, update, "update is nil")
|
||||
|
||||
require.Equal(t, l.Block.Block().Slot(), update.SignatureSlot(), "Signature slot is not equal")
|
||||
|
||||
l.CheckSyncAggregate(update.SyncAggregate())
|
||||
l.CheckAttestedHeader(update.AttestedHeader())
|
||||
})
|
||||
l.CheckSyncAggregate(update.SyncAggregate())
|
||||
l.CheckAttestedHeader(update.AttestedHeader())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestLightClient_NewLightClientFinalityUpdateFromBeaconState(t *testing.T) {
|
||||
@@ -91,6 +55,7 @@ func TestLightClient_NewLightClientFinalityUpdateFromBeaconState(t *testing.T) {
|
||||
cfg.CapellaForkEpoch = 3
|
||||
cfg.DenebForkEpoch = 4
|
||||
cfg.ElectraForkEpoch = 5
|
||||
cfg.FuluForkEpoch = 6
|
||||
params.OverrideBeaconConfig(cfg)
|
||||
|
||||
t.Run("Altair", func(t *testing.T) {
|
||||
@@ -538,6 +503,157 @@ func TestLightClient_NewLightClientFinalityUpdateFromBeaconState(t *testing.T) {
|
||||
require.DeepSSZEqual(t, execution, updateExecution.Proto(), "Finalized Block Execution is not equal")
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("Fulu", func(t *testing.T) {
|
||||
t.Run("FinalizedBlock Not Nil", func(t *testing.T) {
|
||||
l := util.NewTestLightClient(t, version.Fulu)
|
||||
|
||||
update, err := lightClient.NewLightClientFinalityUpdateFromBeaconState(l.Ctx, l.State, l.Block, l.AttestedState, l.AttestedBlock, l.FinalizedBlock)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, update, "update is nil")
|
||||
|
||||
require.Equal(t, l.Block.Block().Slot(), update.SignatureSlot(), "Signature slot is not equal")
|
||||
|
||||
l.CheckSyncAggregate(update.SyncAggregate())
|
||||
l.CheckAttestedHeader(update.AttestedHeader())
|
||||
|
||||
//zeroHash := params.BeaconConfig().ZeroHash[:]
|
||||
finalizedBlockHeader, err := l.FinalizedBlock.Header()
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, update.FinalizedHeader(), "Finalized header is nil")
|
||||
updateFinalizedHeaderBeacon := update.FinalizedHeader().Beacon()
|
||||
require.Equal(t, finalizedBlockHeader.Header.Slot, updateFinalizedHeaderBeacon.Slot, "Finalized header slot is not equal")
|
||||
require.Equal(t, finalizedBlockHeader.Header.ProposerIndex, updateFinalizedHeaderBeacon.ProposerIndex, "Finalized header proposer index is not equal")
|
||||
require.DeepSSZEqual(t, finalizedBlockHeader.Header.ParentRoot, updateFinalizedHeaderBeacon.ParentRoot, "Finalized header parent root is not equal")
|
||||
require.DeepSSZEqual(t, finalizedBlockHeader.Header.StateRoot, updateFinalizedHeaderBeacon.StateRoot, "Finalized header state root is not equal")
|
||||
require.DeepSSZEqual(t, finalizedBlockHeader.Header.BodyRoot, updateFinalizedHeaderBeacon.BodyRoot, "Finalized header body root is not equal")
|
||||
fb, err := update.FinalityBranchElectra()
|
||||
require.NoError(t, err)
|
||||
proof, err := l.AttestedState.FinalizedRootProof(l.Ctx)
|
||||
require.NoError(t, err)
|
||||
for i, leaf := range fb {
|
||||
require.DeepSSZEqual(t, proof[i], leaf[:], "Leaf is not equal")
|
||||
}
|
||||
|
||||
// Check Execution BlockHash
|
||||
payloadInterface, err := l.FinalizedBlock.Block().Body().Execution()
|
||||
require.NoError(t, err)
|
||||
transactionsRoot, err := payloadInterface.TransactionsRoot()
|
||||
if errors.Is(err, consensustypes.ErrUnsupportedField) {
|
||||
transactions, err := payloadInterface.Transactions()
|
||||
require.NoError(t, err)
|
||||
transactionsRootArray, err := ssz.TransactionsRoot(transactions)
|
||||
require.NoError(t, err)
|
||||
transactionsRoot = transactionsRootArray[:]
|
||||
} else {
|
||||
require.NoError(t, err)
|
||||
}
|
||||
withdrawalsRoot, err := payloadInterface.WithdrawalsRoot()
|
||||
if errors.Is(err, consensustypes.ErrUnsupportedField) {
|
||||
withdrawals, err := payloadInterface.Withdrawals()
|
||||
require.NoError(t, err)
|
||||
withdrawalsRootArray, err := ssz.WithdrawalSliceRoot(withdrawals, fieldparams.MaxWithdrawalsPerPayload)
|
||||
require.NoError(t, err)
|
||||
withdrawalsRoot = withdrawalsRootArray[:]
|
||||
} else {
|
||||
require.NoError(t, err)
|
||||
}
|
||||
execution := &v11.ExecutionPayloadHeaderDeneb{
|
||||
ParentHash: payloadInterface.ParentHash(),
|
||||
FeeRecipient: payloadInterface.FeeRecipient(),
|
||||
StateRoot: payloadInterface.StateRoot(),
|
||||
ReceiptsRoot: payloadInterface.ReceiptsRoot(),
|
||||
LogsBloom: payloadInterface.LogsBloom(),
|
||||
PrevRandao: payloadInterface.PrevRandao(),
|
||||
BlockNumber: payloadInterface.BlockNumber(),
|
||||
GasLimit: payloadInterface.GasLimit(),
|
||||
GasUsed: payloadInterface.GasUsed(),
|
||||
Timestamp: payloadInterface.Timestamp(),
|
||||
ExtraData: payloadInterface.ExtraData(),
|
||||
BaseFeePerGas: payloadInterface.BaseFeePerGas(),
|
||||
BlockHash: payloadInterface.BlockHash(),
|
||||
TransactionsRoot: transactionsRoot,
|
||||
WithdrawalsRoot: withdrawalsRoot,
|
||||
}
|
||||
updateExecution, err := update.FinalizedHeader().Execution()
|
||||
require.NoError(t, err)
|
||||
require.DeepSSZEqual(t, execution, updateExecution.Proto(), "Finalized Block Execution is not equal")
|
||||
})
|
||||
|
||||
t.Run("FinalizedBlock In Previous Fork", func(t *testing.T) {
|
||||
l := util.NewTestLightClient(t, version.Fulu, util.WithFinalizedCheckpointInPrevFork())
|
||||
|
||||
update, err := lightClient.NewLightClientFinalityUpdateFromBeaconState(l.Ctx, l.State, l.Block, l.AttestedState, l.AttestedBlock, l.FinalizedBlock)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, update, "update is nil")
|
||||
|
||||
require.Equal(t, l.Block.Block().Slot(), update.SignatureSlot(), "Signature slot is not equal")
|
||||
|
||||
l.CheckSyncAggregate(update.SyncAggregate())
|
||||
l.CheckAttestedHeader(update.AttestedHeader())
|
||||
|
||||
finalizedBlockHeader, err := l.FinalizedBlock.Header()
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, update.FinalizedHeader(), "Finalized header is nil")
|
||||
updateFinalizedHeaderBeacon := update.FinalizedHeader().Beacon()
|
||||
require.Equal(t, finalizedBlockHeader.Header.Slot, updateFinalizedHeaderBeacon.Slot, "Finalized header slot is not equal")
|
||||
require.Equal(t, finalizedBlockHeader.Header.ProposerIndex, updateFinalizedHeaderBeacon.ProposerIndex, "Finalized header proposer index is not equal")
|
||||
require.DeepSSZEqual(t, finalizedBlockHeader.Header.ParentRoot, updateFinalizedHeaderBeacon.ParentRoot, "Finalized header parent root is not equal")
|
||||
require.DeepSSZEqual(t, finalizedBlockHeader.Header.StateRoot, updateFinalizedHeaderBeacon.StateRoot, "Finalized header state root is not equal")
|
||||
require.DeepSSZEqual(t, finalizedBlockHeader.Header.BodyRoot, updateFinalizedHeaderBeacon.BodyRoot, "Finalized header body root is not equal")
|
||||
fb, err := update.FinalityBranchElectra()
|
||||
require.NoError(t, err)
|
||||
proof, err := l.AttestedState.FinalizedRootProof(l.Ctx)
|
||||
require.NoError(t, err)
|
||||
for i, leaf := range fb {
|
||||
require.DeepSSZEqual(t, proof[i], leaf[:], "Leaf is not equal")
|
||||
}
|
||||
|
||||
// Check Execution BlockHash
|
||||
payloadInterface, err := l.FinalizedBlock.Block().Body().Execution()
|
||||
require.NoError(t, err)
|
||||
transactionsRoot, err := payloadInterface.TransactionsRoot()
|
||||
if errors.Is(err, consensustypes.ErrUnsupportedField) {
|
||||
transactions, err := payloadInterface.Transactions()
|
||||
require.NoError(t, err)
|
||||
transactionsRootArray, err := ssz.TransactionsRoot(transactions)
|
||||
require.NoError(t, err)
|
||||
transactionsRoot = transactionsRootArray[:]
|
||||
} else {
|
||||
require.NoError(t, err)
|
||||
}
|
||||
withdrawalsRoot, err := payloadInterface.WithdrawalsRoot()
|
||||
if errors.Is(err, consensustypes.ErrUnsupportedField) {
|
||||
withdrawals, err := payloadInterface.Withdrawals()
|
||||
require.NoError(t, err)
|
||||
withdrawalsRootArray, err := ssz.WithdrawalSliceRoot(withdrawals, fieldparams.MaxWithdrawalsPerPayload)
|
||||
require.NoError(t, err)
|
||||
withdrawalsRoot = withdrawalsRootArray[:]
|
||||
} else {
|
||||
require.NoError(t, err)
|
||||
}
|
||||
execution := &v11.ExecutionPayloadHeaderDeneb{
|
||||
ParentHash: payloadInterface.ParentHash(),
|
||||
FeeRecipient: payloadInterface.FeeRecipient(),
|
||||
StateRoot: payloadInterface.StateRoot(),
|
||||
ReceiptsRoot: payloadInterface.ReceiptsRoot(),
|
||||
LogsBloom: payloadInterface.LogsBloom(),
|
||||
PrevRandao: payloadInterface.PrevRandao(),
|
||||
BlockNumber: payloadInterface.BlockNumber(),
|
||||
GasLimit: payloadInterface.GasLimit(),
|
||||
GasUsed: payloadInterface.GasUsed(),
|
||||
Timestamp: payloadInterface.Timestamp(),
|
||||
ExtraData: payloadInterface.ExtraData(),
|
||||
BaseFeePerGas: payloadInterface.BaseFeePerGas(),
|
||||
BlockHash: payloadInterface.BlockHash(),
|
||||
TransactionsRoot: transactionsRoot,
|
||||
WithdrawalsRoot: withdrawalsRoot,
|
||||
}
|
||||
updateExecution, err := update.FinalizedHeader().Execution()
|
||||
require.NoError(t, err)
|
||||
require.DeepSSZEqual(t, execution, updateExecution.Proto(), "Finalized Block Execution is not equal")
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func TestLightClient_BlockToLightClientHeader(t *testing.T) {
|
||||
@@ -983,6 +1099,138 @@ func TestLightClient_BlockToLightClientHeader(t *testing.T) {
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("Fulu", func(t *testing.T) {
|
||||
t.Run("Non-Blinded Beacon Block", func(t *testing.T) {
|
||||
l := util.NewTestLightClient(t, version.Fulu)
|
||||
|
||||
header, err := lightClient.BlockToLightClientHeader(l.Ctx, version.Fulu, l.Block)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, header, "header is nil")
|
||||
|
||||
parentRoot := l.Block.Block().ParentRoot()
|
||||
stateRoot := l.Block.Block().StateRoot()
|
||||
bodyRoot, err := l.Block.Block().Body().HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
|
||||
payload, err := l.Block.Block().Body().Execution()
|
||||
require.NoError(t, err)
|
||||
|
||||
transactionsRoot, err := lightClient.ComputeTransactionsRoot(payload)
|
||||
require.NoError(t, err)
|
||||
|
||||
withdrawalsRoot, err := lightClient.ComputeWithdrawalsRoot(payload)
|
||||
require.NoError(t, err)
|
||||
|
||||
blobGasUsed, err := payload.BlobGasUsed()
|
||||
require.NoError(t, err)
|
||||
|
||||
excessBlobGas, err := payload.ExcessBlobGas()
|
||||
require.NoError(t, err)
|
||||
|
||||
executionHeader := &v11.ExecutionPayloadHeaderDeneb{
|
||||
ParentHash: payload.ParentHash(),
|
||||
FeeRecipient: payload.FeeRecipient(),
|
||||
StateRoot: payload.StateRoot(),
|
||||
ReceiptsRoot: payload.ReceiptsRoot(),
|
||||
LogsBloom: payload.LogsBloom(),
|
||||
PrevRandao: payload.PrevRandao(),
|
||||
BlockNumber: payload.BlockNumber(),
|
||||
GasLimit: payload.GasLimit(),
|
||||
GasUsed: payload.GasUsed(),
|
||||
Timestamp: payload.Timestamp(),
|
||||
ExtraData: payload.ExtraData(),
|
||||
BaseFeePerGas: payload.BaseFeePerGas(),
|
||||
BlockHash: payload.BlockHash(),
|
||||
TransactionsRoot: transactionsRoot,
|
||||
WithdrawalsRoot: withdrawalsRoot,
|
||||
BlobGasUsed: blobGasUsed,
|
||||
ExcessBlobGas: excessBlobGas,
|
||||
}
|
||||
|
||||
executionPayloadProof, err := blocks.PayloadProof(l.Ctx, l.Block.Block())
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, l.Block.Block().Slot(), header.Beacon().Slot, "Slot is not equal")
|
||||
require.Equal(t, l.Block.Block().ProposerIndex(), header.Beacon().ProposerIndex, "Proposer index is not equal")
|
||||
require.DeepSSZEqual(t, parentRoot[:], header.Beacon().ParentRoot, "Parent root is not equal")
|
||||
require.DeepSSZEqual(t, stateRoot[:], header.Beacon().StateRoot, "State root is not equal")
|
||||
require.DeepSSZEqual(t, bodyRoot[:], header.Beacon().BodyRoot, "Body root is not equal")
|
||||
|
||||
headerExecution, err := header.Execution()
|
||||
require.NoError(t, err)
|
||||
require.DeepSSZEqual(t, executionHeader, headerExecution.Proto(), "Execution headers are not equal")
|
||||
|
||||
headerExecutionBranch, err := header.ExecutionBranch()
|
||||
require.NoError(t, err)
|
||||
require.DeepSSZEqual(t, executionPayloadProof, convertArrayToSlice(headerExecutionBranch), "Execution payload proofs are not equal")
|
||||
})
|
||||
|
||||
t.Run("Blinded Beacon Block", func(t *testing.T) {
|
||||
l := util.NewTestLightClient(t, version.Fulu, util.WithBlinded())
|
||||
|
||||
header, err := lightClient.BlockToLightClientHeader(l.Ctx, version.Fulu, l.Block)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, header, "header is nil")
|
||||
|
||||
parentRoot := l.Block.Block().ParentRoot()
|
||||
stateRoot := l.Block.Block().StateRoot()
|
||||
bodyRoot, err := l.Block.Block().Body().HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
|
||||
payload, err := l.Block.Block().Body().Execution()
|
||||
require.NoError(t, err)
|
||||
|
||||
transactionsRoot, err := payload.TransactionsRoot()
|
||||
require.NoError(t, err)
|
||||
|
||||
withdrawalsRoot, err := payload.WithdrawalsRoot()
|
||||
require.NoError(t, err)
|
||||
|
||||
blobGasUsed, err := payload.BlobGasUsed()
|
||||
require.NoError(t, err)
|
||||
|
||||
excessBlobGas, err := payload.ExcessBlobGas()
|
||||
require.NoError(t, err)
|
||||
|
||||
executionHeader := &v11.ExecutionPayloadHeaderDeneb{
|
||||
ParentHash: payload.ParentHash(),
|
||||
FeeRecipient: payload.FeeRecipient(),
|
||||
StateRoot: payload.StateRoot(),
|
||||
ReceiptsRoot: payload.ReceiptsRoot(),
|
||||
LogsBloom: payload.LogsBloom(),
|
||||
PrevRandao: payload.PrevRandao(),
|
||||
BlockNumber: payload.BlockNumber(),
|
||||
GasLimit: payload.GasLimit(),
|
||||
GasUsed: payload.GasUsed(),
|
||||
Timestamp: payload.Timestamp(),
|
||||
ExtraData: payload.ExtraData(),
|
||||
BaseFeePerGas: payload.BaseFeePerGas(),
|
||||
BlockHash: payload.BlockHash(),
|
||||
TransactionsRoot: transactionsRoot,
|
||||
WithdrawalsRoot: withdrawalsRoot,
|
||||
BlobGasUsed: blobGasUsed,
|
||||
ExcessBlobGas: excessBlobGas,
|
||||
}
|
||||
|
||||
executionPayloadProof, err := blocks.PayloadProof(l.Ctx, l.Block.Block())
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, l.Block.Block().Slot(), header.Beacon().Slot, "Slot is not equal")
|
||||
require.Equal(t, l.Block.Block().ProposerIndex(), header.Beacon().ProposerIndex, "Proposer index is not equal")
|
||||
require.DeepSSZEqual(t, parentRoot[:], header.Beacon().ParentRoot, "Parent root is not equal")
|
||||
require.DeepSSZEqual(t, stateRoot[:], header.Beacon().StateRoot, "State root is not equal")
|
||||
require.DeepSSZEqual(t, bodyRoot[:], header.Beacon().BodyRoot, "Body root is not equal")
|
||||
|
||||
headerExecution, err := header.Execution()
|
||||
require.NoError(t, err)
|
||||
require.DeepSSZEqual(t, executionHeader, headerExecution.Proto(), "Execution headers are not equal")
|
||||
|
||||
headerExecutionBranch, err := header.ExecutionBranch()
|
||||
require.NoError(t, err)
|
||||
require.DeepSSZEqual(t, executionPayloadProof, convertArrayToSlice(headerExecutionBranch), "Execution payload proofs are not equal")
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("Capella fork with Altair block", func(t *testing.T) {
|
||||
l := util.NewTestLightClient(t, version.Altair)
|
||||
|
||||
|
||||
@@ -46,7 +46,7 @@ func TestLightClientHandler_GetLightClientBootstrap(t *testing.T) {
|
||||
cfg.FuluForkEpoch = 5
|
||||
params.OverrideBeaconConfig(cfg)
|
||||
|
||||
for testVersion := version.Altair; testVersion <= version.Electra; testVersion++ {
|
||||
for _, testVersion := range version.All()[1:] {
|
||||
t.Run(version.String(testVersion), func(t *testing.T) {
|
||||
l := util.NewTestLightClient(t, testVersion)
|
||||
|
||||
@@ -131,7 +131,7 @@ func TestLightClientHandler_GetLightClientBootstrap(t *testing.T) {
|
||||
resp = &pb.LightClientBootstrapCapella{}
|
||||
case version.Deneb:
|
||||
resp = &pb.LightClientBootstrapDeneb{}
|
||||
case version.Electra:
|
||||
case version.Electra, version.Fulu:
|
||||
resp = &pb.LightClientBootstrapElectra{}
|
||||
default:
|
||||
t.Fatalf("Unsupported version %s", version.String(testVersion))
|
||||
@@ -173,10 +173,11 @@ func TestLightClientHandler_GetLightClientByRange(t *testing.T) {
|
||||
config.CapellaForkEpoch = 2
|
||||
config.DenebForkEpoch = 3
|
||||
config.ElectraForkEpoch = 4
|
||||
config.FuluForkEpoch = 5
|
||||
params.OverrideBeaconConfig(config)
|
||||
|
||||
t.Run("can save retrieve", func(t *testing.T) {
|
||||
for testVersion := version.Altair; testVersion <= version.Electra; testVersion++ {
|
||||
for _, testVersion := range version.All()[1:] {
|
||||
t.Run(version.String(testVersion), func(t *testing.T) {
|
||||
|
||||
slot := primitives.Slot(params.BeaconConfig().VersionToForkEpochMap()[testVersion] * primitives.Epoch(config.SlotsPerEpoch)).Add(1)
|
||||
@@ -252,7 +253,7 @@ func TestLightClientHandler_GetLightClientByRange(t *testing.T) {
|
||||
resp = &pb.LightClientUpdateCapella{}
|
||||
case version.Deneb:
|
||||
resp = &pb.LightClientUpdateDeneb{}
|
||||
case version.Electra:
|
||||
case version.Electra, version.Fulu:
|
||||
resp = &pb.LightClientUpdateElectra{}
|
||||
default:
|
||||
t.Fatalf("Unsupported version %s", version.String(testVersion))
|
||||
@@ -313,7 +314,7 @@ func TestLightClientHandler_GetLightClientByRange(t *testing.T) {
|
||||
resp = &pb.LightClientUpdateCapella{}
|
||||
case version.Deneb:
|
||||
resp = &pb.LightClientUpdateDeneb{}
|
||||
case version.Electra:
|
||||
case version.Electra, version.Fulu:
|
||||
resp = &pb.LightClientUpdateElectra{}
|
||||
default:
|
||||
t.Fatalf("Unsupported version %s", version.String(testVersion))
|
||||
@@ -730,7 +731,7 @@ func TestLightClientHandler_GetLightClientFinalityUpdate(t *testing.T) {
|
||||
require.Equal(t, http.StatusNotFound, writer.Code)
|
||||
})
|
||||
|
||||
for testVersion := 1; testVersion < 6; testVersion++ {
|
||||
for _, testVersion := range version.All()[1:] {
|
||||
t.Run(version.String(testVersion), func(t *testing.T) {
|
||||
ctx := t.Context()
|
||||
|
||||
@@ -793,7 +794,7 @@ func TestLightClientHandler_GetLightClientFinalityUpdate(t *testing.T) {
|
||||
resp = &pb.LightClientFinalityUpdateCapella{}
|
||||
case version.Deneb:
|
||||
resp = &pb.LightClientFinalityUpdateDeneb{}
|
||||
case version.Electra:
|
||||
case version.Electra, version.Fulu:
|
||||
resp = &pb.LightClientFinalityUpdateElectra{}
|
||||
default:
|
||||
t.Fatalf("Unsupported version %s", version.String(testVersion))
|
||||
@@ -825,7 +826,7 @@ func TestLightClientHandler_GetLightClientOptimisticUpdate(t *testing.T) {
|
||||
require.Equal(t, http.StatusNotFound, writer.Code)
|
||||
})
|
||||
|
||||
for testVersion := 1; testVersion < 6; testVersion++ {
|
||||
for _, testVersion := range version.All()[1:] {
|
||||
t.Run(version.String(testVersion), func(t *testing.T) {
|
||||
ctx := t.Context()
|
||||
l := util.NewTestLightClient(t, testVersion)
|
||||
@@ -886,7 +887,7 @@ func TestLightClientHandler_GetLightClientOptimisticUpdate(t *testing.T) {
|
||||
resp = &pb.LightClientOptimisticUpdateCapella{}
|
||||
case version.Deneb:
|
||||
resp = &pb.LightClientOptimisticUpdateDeneb{}
|
||||
case version.Electra:
|
||||
case version.Electra, version.Fulu:
|
||||
resp = &pb.LightClientOptimisticUpdateDeneb{}
|
||||
default:
|
||||
t.Fatalf("Unsupported version %s", version.String(testVersion))
|
||||
|
||||
3
changelog/bastin_update-lc-for-fulu.md
Normal file
3
changelog/bastin_update-lc-for-fulu.md
Normal file
@@ -0,0 +1,3 @@
|
||||
### Added
|
||||
|
||||
- add fulu support to light client processing.
|
||||
@@ -62,6 +62,8 @@ func NewTestLightClient(t *testing.T, forkVersion int, options ...LightClientOpt
|
||||
return l.setupTestDeneb()
|
||||
case version.Electra:
|
||||
return l.setupTestElectra()
|
||||
case version.Fulu:
|
||||
return l.setupTestFulu()
|
||||
default:
|
||||
l.T.Fatalf("Unsupported version %s", version.String(l.version))
|
||||
return nil
|
||||
@@ -955,6 +957,184 @@ func (l *TestLightClient) setupTestElectra() *TestLightClient {
|
||||
return l
|
||||
}
|
||||
|
||||
func (l *TestLightClient) setupTestFulu() *TestLightClient {
|
||||
ctx := context.Background()
|
||||
|
||||
attestedSlot := primitives.Slot(uint64(params.BeaconConfig().FuluForkEpoch) * uint64(params.BeaconConfig().SlotsPerEpoch)).Add(1)
|
||||
if l.increaseAttestedSlotBy > 0 {
|
||||
attestedSlot = attestedSlot.Add(l.increaseAttestedSlotBy)
|
||||
}
|
||||
|
||||
signatureSlot := attestedSlot.Add(1)
|
||||
if l.increaseSignatureSlotBy > 0 {
|
||||
signatureSlot = signatureSlot.Add(l.increaseSignatureSlotBy)
|
||||
}
|
||||
|
||||
// Attested State & Block
|
||||
attestedState, err := NewBeaconStateFulu()
|
||||
require.NoError(l.T, err)
|
||||
require.NoError(l.T, attestedState.SetSlot(attestedSlot))
|
||||
|
||||
var signedFinalizedBlock interfaces.SignedBeaconBlock
|
||||
var finalizedState state.BeaconState
|
||||
// Finalized checkpoint
|
||||
if !l.noFinalizedCheckpoint {
|
||||
var finalizedSlot primitives.Slot
|
||||
|
||||
if l.finalizedCheckpointInPrevFork {
|
||||
finalizedSlot = primitives.Slot(uint64(params.BeaconConfig().ElectraForkEpoch) * uint64(params.BeaconConfig().SlotsPerEpoch))
|
||||
if l.increaseFinalizedSlotBy > 0 {
|
||||
finalizedSlot = finalizedSlot.Add(l.increaseFinalizedSlotBy)
|
||||
}
|
||||
|
||||
finalizedState, err = NewBeaconStateElectra()
|
||||
require.NoError(l.T, err)
|
||||
require.NoError(l.T, finalizedState.SetSlot(finalizedSlot))
|
||||
|
||||
finalizedBlock := NewBeaconBlockElectra()
|
||||
require.NoError(l.T, err)
|
||||
finalizedBlock.Block.Slot = finalizedSlot
|
||||
signedFinalizedBlock, err = blocks.NewSignedBeaconBlock(finalizedBlock)
|
||||
require.NoError(l.T, err)
|
||||
finalizedHeader, err := signedFinalizedBlock.Header()
|
||||
require.NoError(l.T, err)
|
||||
require.NoError(l.T, finalizedState.SetLatestBlockHeader(finalizedHeader.Header))
|
||||
finalizedStateRoot, err := finalizedState.HashTreeRoot(ctx)
|
||||
require.NoError(l.T, err)
|
||||
finalizedBlock.Block.StateRoot = finalizedStateRoot[:]
|
||||
signedFinalizedBlock, err = blocks.NewSignedBeaconBlock(finalizedBlock)
|
||||
require.NoError(l.T, err)
|
||||
} else {
|
||||
finalizedSlot = primitives.Slot(uint64(params.BeaconConfig().FuluForkEpoch) * uint64(params.BeaconConfig().SlotsPerEpoch))
|
||||
if l.increaseFinalizedSlotBy > 0 {
|
||||
finalizedSlot = finalizedSlot.Add(l.increaseFinalizedSlotBy)
|
||||
}
|
||||
|
||||
finalizedState, err = NewBeaconStateFulu()
|
||||
require.NoError(l.T, err)
|
||||
require.NoError(l.T, finalizedState.SetSlot(finalizedSlot))
|
||||
|
||||
finalizedBlock := NewBeaconBlockFulu()
|
||||
require.NoError(l.T, err)
|
||||
finalizedBlock.Block.Slot = finalizedSlot
|
||||
signedFinalizedBlock, err = blocks.NewSignedBeaconBlock(finalizedBlock)
|
||||
require.NoError(l.T, err)
|
||||
finalizedHeader, err := signedFinalizedBlock.Header()
|
||||
require.NoError(l.T, err)
|
||||
require.NoError(l.T, finalizedState.SetLatestBlockHeader(finalizedHeader.Header))
|
||||
finalizedStateRoot, err := finalizedState.HashTreeRoot(ctx)
|
||||
require.NoError(l.T, err)
|
||||
finalizedBlock.Block.StateRoot = finalizedStateRoot[:]
|
||||
signedFinalizedBlock, err = blocks.NewSignedBeaconBlock(finalizedBlock)
|
||||
require.NoError(l.T, err)
|
||||
}
|
||||
|
||||
// Set the finalized checkpoint
|
||||
finalizedBlockRoot, err := signedFinalizedBlock.Block().HashTreeRoot()
|
||||
require.NoError(l.T, err)
|
||||
finalizedCheckpoint := ðpb.Checkpoint{
|
||||
Epoch: slots.ToEpoch(finalizedSlot),
|
||||
Root: finalizedBlockRoot[:],
|
||||
}
|
||||
require.NoError(l.T, attestedState.SetFinalizedCheckpoint(finalizedCheckpoint))
|
||||
}
|
||||
|
||||
// Attested Block
|
||||
attestedBlock := NewBeaconBlockFulu()
|
||||
attestedBlock.Block.Slot = attestedSlot
|
||||
attestedBlock.Block.ParentRoot = l.attestedParentRoot[:]
|
||||
signedAttestedBlock, err := blocks.NewSignedBeaconBlock(attestedBlock)
|
||||
require.NoError(l.T, err)
|
||||
attestedBlockHeader, err := signedAttestedBlock.Header()
|
||||
require.NoError(l.T, err)
|
||||
require.NoError(l.T, attestedState.SetLatestBlockHeader(attestedBlockHeader.Header))
|
||||
attestedStateRoot, err := attestedState.HashTreeRoot(ctx)
|
||||
require.NoError(l.T, err)
|
||||
attestedBlock.Block.StateRoot = attestedStateRoot[:]
|
||||
signedAttestedBlock, err = blocks.NewSignedBeaconBlock(attestedBlock)
|
||||
require.NoError(l.T, err)
|
||||
|
||||
// Signature State & Block
|
||||
signatureState, err := NewBeaconStateFulu()
|
||||
require.NoError(l.T, err)
|
||||
require.NoError(l.T, signatureState.SetSlot(signatureSlot))
|
||||
|
||||
var signedSignatureBlock interfaces.SignedBeaconBlock
|
||||
if l.blinded {
|
||||
signatureBlock := NewBlindedBeaconBlockFulu()
|
||||
signatureBlock.Message.Slot = signatureSlot
|
||||
attestedBlockRoot, err := signedAttestedBlock.Block().HashTreeRoot()
|
||||
require.NoError(l.T, err)
|
||||
signatureBlock.Message.ParentRoot = attestedBlockRoot[:]
|
||||
|
||||
var trueBitNum uint64
|
||||
if l.supermajority {
|
||||
trueBitNum = uint64((float64(params.BeaconConfig().SyncCommitteeSize) * 2.0 / 3.0) + 1 + float64(l.increaseActiveParticipantsBy))
|
||||
} else {
|
||||
trueBitNum = params.BeaconConfig().MinSyncCommitteeParticipants
|
||||
}
|
||||
for i := uint64(0); i < trueBitNum; i++ {
|
||||
signatureBlock.Message.Body.SyncAggregate.SyncCommitteeBits.SetBitAt(i, true)
|
||||
}
|
||||
|
||||
signedSignatureBlock, err = blocks.NewSignedBeaconBlock(signatureBlock)
|
||||
require.NoError(l.T, err)
|
||||
|
||||
signatureBlockHeader, err := signedSignatureBlock.Header()
|
||||
require.NoError(l.T, err)
|
||||
|
||||
err = signatureState.SetLatestBlockHeader(signatureBlockHeader.Header)
|
||||
require.NoError(l.T, err)
|
||||
stateRoot, err := signatureState.HashTreeRoot(ctx)
|
||||
require.NoError(l.T, err)
|
||||
|
||||
signatureBlock.Message.StateRoot = stateRoot[:]
|
||||
signedSignatureBlock, err = blocks.NewSignedBeaconBlock(signatureBlock)
|
||||
require.NoError(l.T, err)
|
||||
} else {
|
||||
signatureBlock := NewBeaconBlockFulu()
|
||||
signatureBlock.Block.Slot = signatureSlot
|
||||
attestedBlockRoot, err := signedAttestedBlock.Block().HashTreeRoot()
|
||||
require.NoError(l.T, err)
|
||||
signatureBlock.Block.ParentRoot = attestedBlockRoot[:]
|
||||
|
||||
var trueBitNum uint64
|
||||
if l.supermajority {
|
||||
trueBitNum = uint64((float64(params.BeaconConfig().SyncCommitteeSize) * 2.0 / 3.0) + 1 + float64(l.increaseActiveParticipantsBy))
|
||||
} else {
|
||||
trueBitNum = params.BeaconConfig().MinSyncCommitteeParticipants
|
||||
}
|
||||
for i := uint64(0); i < trueBitNum; i++ {
|
||||
signatureBlock.Block.Body.SyncAggregate.SyncCommitteeBits.SetBitAt(i, true)
|
||||
}
|
||||
|
||||
signedSignatureBlock, err = blocks.NewSignedBeaconBlock(signatureBlock)
|
||||
require.NoError(l.T, err)
|
||||
|
||||
signatureBlockHeader, err := signedSignatureBlock.Header()
|
||||
require.NoError(l.T, err)
|
||||
|
||||
err = signatureState.SetLatestBlockHeader(signatureBlockHeader.Header)
|
||||
require.NoError(l.T, err)
|
||||
signatureStateRoot, err := signatureState.HashTreeRoot(ctx)
|
||||
require.NoError(l.T, err)
|
||||
|
||||
signatureBlock.Block.StateRoot = signatureStateRoot[:]
|
||||
signedSignatureBlock, err = blocks.NewSignedBeaconBlock(signatureBlock)
|
||||
require.NoError(l.T, err)
|
||||
}
|
||||
|
||||
l.State = signatureState
|
||||
l.AttestedState = attestedState
|
||||
l.AttestedBlock = signedAttestedBlock
|
||||
l.Block = signedSignatureBlock
|
||||
l.Ctx = ctx
|
||||
l.FinalizedBlock = signedFinalizedBlock
|
||||
l.FinalizedState = finalizedState
|
||||
|
||||
return l
|
||||
}
|
||||
|
||||
func (l *TestLightClient) CheckAttestedHeader(header interfaces.LightClientHeader) {
|
||||
updateAttestedHeaderBeacon := header.Beacon()
|
||||
testAttestedHeader, err := l.AttestedBlock.Header()
|
||||
|
||||
Reference in New Issue
Block a user