Skip to content

Commit

Permalink
Delay 10 seconds start + update watch command (#33)
Browse files Browse the repository at this point in the history
  • Loading branch information
ferranbt authored Dec 4, 2024
1 parent 74d333a commit 2462499
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 19 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/checks.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ jobs:
run: go run main.go --output /tmp/playground & > /tmp/playground.log 2>&1

- name: Validate that blocks are created
run: go run main.go validate
run: go run main.go watch-payloads --validate-payloads

- name: Move playground logs
if: ${{ failure() }}
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ Options:
- `--output` (string): The directory where the chain data and artifacts are stored. It defaults to `$HOME/.playground/devnet`.
- `--continue` (bool): Whether to restart the chain from a previous run if the output folder is not empty. It defaults to `false`.
- `--use-bin-path` (bool): Whether to use the binaries from the local path instead of downloading them. It defaults to `false`.
- `--genesis-delay` (int): The delay in seconds before the genesis block is created. It is used to account for the delay between the creation of the artifacts and the running of the services. It defaults to `5` seconds.
- `--genesis-delay` (int): The delay in seconds before the genesis block is created. It is used to account for the delay between the creation of the artifacts and the running of the services. It defaults to `10` seconds.
- `--electra`: (bool): If enabled, it enables the Electra fork at startup. It defaults to `false`.

Unless the `--continue` flag is set, the playground will delete the output directory and start a new chain from scratch on every run.
65 changes: 48 additions & 17 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,15 +97,22 @@ var downloadArtifactsCmd = &cobra.Command{
}

var numBlocksValidate uint64
var validatePayloads bool

var validateCmd = &cobra.Command{
Use: "validate",
Long: `Validate the playground`,
var watchCmd = &cobra.Command{
Use: "watch-payloads",
Long: `Watch the payload attribute events`,
RunE: func(cmd *cobra.Command, args []string) error {
// Test that blocks are being produced
log := mevRCommon.LogSetup(false, "info")
clt := beaconclient.NewProdBeaconInstance(log, "http://localhost:3500", "http://localhost:3500")

// Subscribe to head events right away even if the connection has not been established yet
// That is handled internally in the function already.
// Otherwise, if we connect only when the first head slot happens we might miss some initial slots.
ch := make(chan beaconclient.PayloadAttributesEvent)
go clt.SubscribeToPayloadAttributesEvents(ch)

{
// If the chain has not started yet, wait for it to start.
// Otherwise, the subscription will not return any data.
Expand All @@ -118,7 +125,7 @@ var validateCmd = &cobra.Command{
if err != nil {
return false
}
return sync.HeadSlot > 1
return sync.HeadSlot >= 1
}

if !isReady() {
Expand All @@ -139,49 +146,73 @@ var validateCmd = &cobra.Command{

log.Infof("Chain is alive. Subscribing to head events")

ch := make(chan beaconclient.HeadEventData)
go clt.SubscribeToHeadEvents(ch)

var lastSlot uint64
for i := uint64(0); i < numBlocksValidate; i++ {
for {
select {
case head := <-ch:
if lastSlot != 0 && lastSlot+1 != head.Slot {
return fmt.Errorf("slot mismatch, expected %d, got %d", lastSlot+1, head.Slot)
log.Infof("Slot: %d Parent block number: %d", head.Data.ProposalSlot, head.Data.ParentBlockNumber)

if validatePayloads {
// If we are being notified of a new slot, validate that the slots are contiguous
// Note that lighthouse might send multiple updates for the same slot.
if lastSlot != 0 && lastSlot != head.Data.ProposalSlot && lastSlot+1 != head.Data.ProposalSlot {
return fmt.Errorf("slot mismatch, expected %d, got %d", lastSlot+1, head.Data.ProposalSlot)
}
// if the network did not miss any initial slots, lighthouse will send payload attribute updates
// of the form: (slot = slot, parent block number = slot - 2), (slot, slot - 1).
// The -2 is in case we want to handle reorgs in the chain.
// We need to validate that at least the difference between the parent block number and the slot is 2.
if head.Data.ProposalSlot-head.Data.ParentBlockNumber > 2 {
return fmt.Errorf("parent block too big %d", head.Data.ParentBlockNumber)
}

if lastSlot != head.Data.ProposalSlot {
numBlocksValidate--
if numBlocksValidate == 0 {
return nil
}
}
}

log.Infof("Slot: %d Block: %s", head.Slot, head.Block)
lastSlot = head.Slot
lastSlot = head.Data.ProposalSlot
case <-time.After(20 * time.Second):
return fmt.Errorf("timeout waiting for block")
}
}

return nil
},
}

// minimumGenesisDelay is the minimum delay for the genesis time. This is required
// because lighthouse takes some time to start and we need to make sure it is ready
// otherwise, some blocks are missed.
var minimumGenesisDelay uint64 = 10

func main() {
rootCmd.Flags().StringVar(&outputFlag, "output", "", "")
rootCmd.Flags().BoolVar(&continueFlag, "continue", false, "")
rootCmd.Flags().BoolVar(&useBinPathFlag, "use-bin-path", false, "")
rootCmd.Flags().Uint64Var(&genesisDelayFlag, "genesis-delay", 5, "")
rootCmd.Flags().Uint64Var(&genesisDelayFlag, "genesis-delay", minimumGenesisDelay, "")
rootCmd.Flags().BoolVar(&latestForkFlag, "electra", false, "")
rootCmd.Flags().BoolVar(&useRethForValidation, "use-reth-for-validation", false, "enable flashbots_validateBuilderSubmissionV* on reth and use them for validation")
rootCmd.Flags().Uint64Var(&secondaryBuilderPort, "secondary", 1234, "port to use for the secondary builder")

downloadArtifactsCmd.Flags().BoolVar(&validateFlag, "validate", false, "")
validateCmd.Flags().Uint64Var(&numBlocksValidate, "num-blocks", 5, "")
watchCmd.Flags().Uint64Var(&numBlocksValidate, "validate-num-blocks", 5, "")
watchCmd.Flags().BoolVar(&validatePayloads, "validate-payloads", false, "")

rootCmd.AddCommand(downloadArtifactsCmd)
rootCmd.AddCommand(validateCmd)
rootCmd.AddCommand(watchCmd)
if err := rootCmd.Execute(); err != nil {
fmt.Println(err)
os.Exit(1)
}
}

func runIt() error {
if genesisDelayFlag < minimumGenesisDelay {
return fmt.Errorf("genesis delay must be at least %d", minimumGenesisDelay)
}

if outputFlag == "" {
// Use the $HOMEDIR/devnet as the default output
homeDir, err := getHomeDir()
Expand Down

0 comments on commit 2462499

Please sign in to comment.