diff --git a/Dockerfile b/Dockerfile index 367d76d4b1..c1a28760c4 100644 --- a/Dockerfile +++ b/Dockerfile @@ -202,6 +202,7 @@ WORKDIR /home/user COPY --from=node-builder /workspace/target/bin/nitro /usr/local/bin/ COPY --from=node-builder /workspace/target/bin/relay /usr/local/bin/ COPY --from=node-builder /workspace/target/bin/nitro-val /usr/local/bin/ +COPY --from=node-builder /workspace/target/bin/seq-coordinator-manager /usr/local/bin/ COPY --from=machine-versions /workspace/machines /home/user/target/machines USER root RUN export DEBIAN_FRONTEND=noninteractive && \ diff --git a/Makefile b/Makefile index 0d93958c2d..9c898f03c9 100644 --- a/Makefile +++ b/Makefile @@ -88,7 +88,7 @@ push: lint test-go .make/fmt all: build build-replay-env test-gen-proofs @touch .make/all -build: $(patsubst %,$(output_root)/bin/%, nitro deploy relay daserver datool seq-coordinator-invalidate nitro-val) +build: $(patsubst %,$(output_root)/bin/%, nitro deploy relay daserver datool seq-coordinator-invalidate nitro-val seq-coordinator-manager) @printf $(done) build-node-deps: $(go_source) build-prover-header build-prover-lib build-jit .make/solgen .make/cbrotli-lib @@ -185,6 +185,9 @@ $(output_root)/bin/seq-coordinator-invalidate: $(DEP_PREDICATE) build-node-deps $(output_root)/bin/nitro-val: $(DEP_PREDICATE) build-node-deps go build $(GOLANG_PARAMS) -o $@ "$(CURDIR)/cmd/nitro-val" +$(output_root)/bin/seq-coordinator-manager: $(DEP_PREDICATE) build-node-deps + go build $(GOLANG_PARAMS) -o $@ "$(CURDIR)/cmd/seq-coordinator-manager" + # recompile wasm, but don't change timestamp unless files differ $(replay_wasm): $(DEP_PREDICATE) $(go_source) .make/solgen mkdir -p `dirname $(replay_wasm)` diff --git a/arbnode/batch_poster.go b/arbnode/batch_poster.go index 42b983f0fb..89a36eba91 100644 --- a/arbnode/batch_poster.go +++ b/arbnode/batch_poster.go @@ -11,6 +11,7 @@ import ( "fmt" "math" "math/big" + "strings" "sync/atomic" "time" @@ -75,7 +76,8 @@ type BatchPoster struct { backlog uint64 lastHitL1Bounds time.Time // The last time we wanted to post a message but hit the L1 bounds - batchReverted atomic.Bool // indicates whether data poster batch was reverted + batchReverted atomic.Bool // indicates whether data poster batch was reverted + nextRevertCheckBlock int64 // the last parent block scanned for reverting batches } type l1BlockBound int @@ -262,12 +264,12 @@ func NewBatchPoster(dataPosterDB ethdb.Database, l1Reader *headerreader.HeaderRe // contain reverted batch_poster transaction. // It returns true if it finds batch posting needs to halt, which is true if a batch reverts // unless the data poster is configured with noop storage which can tolerate reverts. -func (b *BatchPoster) checkReverts(ctx context.Context, from, to int64) (bool, error) { - if from > to { - return false, fmt.Errorf("wrong range, from: %d is more to: %d", from, to) +func (b *BatchPoster) checkReverts(ctx context.Context, to int64) (bool, error) { + if b.nextRevertCheckBlock > to { + return false, fmt.Errorf("wrong range, from: %d > to: %d", b.nextRevertCheckBlock, to) } - for idx := from; idx <= to; idx++ { - number := big.NewInt(idx) + for ; b.nextRevertCheckBlock <= to; b.nextRevertCheckBlock++ { + number := big.NewInt(b.nextRevertCheckBlock) block, err := b.l1Reader.Client().BlockByNumber(ctx, number) if err != nil { return false, fmt.Errorf("getting block: %v by number: %w", number, err) @@ -277,7 +279,7 @@ func (b *BatchPoster) checkReverts(ctx context.Context, from, to int64) (bool, e if err != nil { return false, fmt.Errorf("getting sender of transaction tx: %v, %w", tx.Hash(), err) } - if bytes.Equal(from.Bytes(), b.dataPoster.Sender().Bytes()) { + if from == b.dataPoster.Sender() { r, err := b.l1Reader.Client().TransactionReceipt(ctx, tx.Hash()) if err != nil { return false, fmt.Errorf("getting a receipt for transaction: %v, %w", tx.Hash(), err) @@ -303,7 +305,6 @@ func (b *BatchPoster) pollForReverts(ctx context.Context) { headerCh, unsubscribe := b.l1Reader.Subscribe(false) defer unsubscribe() - last := int64(0) // number of last seen block for { // Poll until: // - L1 headers reader channel is closed, or @@ -312,31 +313,38 @@ func (b *BatchPoster) pollForReverts(ctx context.Context) { select { case h, ok := <-headerCh: if !ok { - log.Info("L1 headers channel has been closed") + log.Info("L1 headers channel checking for batch poster reverts has been closed") return } + blockNum := h.Number.Int64() // If this is the first block header, set last seen as number-1. // We may see same block number again if there is L1 reorg, in that // case we check the block again. - if last == 0 || last == h.Number.Int64() { - last = h.Number.Int64() - 1 + if b.nextRevertCheckBlock == 0 || b.nextRevertCheckBlock > blockNum { + b.nextRevertCheckBlock = blockNum } - if h.Number.Int64()-last > 100 { - log.Warn("Large gap between last seen and current block number, skipping check for reverts", "last", last, "current", h.Number) - last = h.Number.Int64() + if blockNum-b.nextRevertCheckBlock > 100 { + log.Warn("Large gap between last seen and current block number, skipping check for reverts", "last", b.nextRevertCheckBlock, "current", blockNum) + b.nextRevertCheckBlock = blockNum continue } - reverted, err := b.checkReverts(ctx, last+1, h.Number.Int64()) + reverted, err := b.checkReverts(ctx, blockNum) if err != nil { - log.Error("Checking batch reverts", "error", err) + logLevel := log.Error + if strings.Contains(err.Error(), "not found") { + // Just parent chain node inconsistency + // One node sent us a block, but another didn't have it + // We'll try to check this block again next loop + logLevel = log.Debug + } + logLevel("Error checking batch reverts", "err", err) continue } if reverted { b.batchReverted.Store(true) return } - last = h.Number.Int64() case <-ctx.Done(): return } diff --git a/arbnode/execution/tx_pre_checker.go b/arbnode/execution/tx_pre_checker.go index dc069a6d18..968a1f266b 100644 --- a/arbnode/execution/tx_pre_checker.go +++ b/arbnode/execution/tx_pre_checker.go @@ -145,11 +145,6 @@ func PreCheckTx(bc *core.BlockChain, chainConfig *params.ChainConfig, header *ty if config.Strictness < TxPreCheckerStrictnessLikelyCompatible { return nil } - balance := statedb.GetBalance(sender) - cost := tx.Cost() - if arbmath.BigLessThan(balance, cost) { - return fmt.Errorf("%w: address %v have %v want %v", core.ErrInsufficientFunds, sender, balance, cost) - } if options != nil { if err := options.Check(extraInfo.L1BlockNumber, header.Time, statedb); err != nil { conditionalTxRejectedByTxPreCheckerCurrentStateCounter.Inc(1) @@ -185,6 +180,11 @@ func PreCheckTx(bc *core.BlockChain, chainConfig *params.ChainConfig, header *ty conditionalTxAcceptedByTxPreCheckerOldStateCounter.Inc(1) } } + balance := statedb.GetBalance(sender) + cost := tx.Cost() + if arbmath.BigLessThan(balance, cost) { + return fmt.Errorf("%w: address %v have %v want %v", core.ErrInsufficientFunds, sender, balance, cost) + } if config.Strictness >= TxPreCheckerStrictnessFullValidation && tx.Nonce() > stateNonce { return MakeNonceError(sender, tx.Nonce(), stateNonce) } diff --git a/arbnode/node.go b/arbnode/node.go index 356c46681f..5bdc716264 100644 --- a/arbnode/node.go +++ b/arbnode/node.go @@ -40,6 +40,7 @@ import ( "github.com/offchainlabs/nitro/solgen/go/bridgegen" "github.com/offchainlabs/nitro/solgen/go/challengegen" "github.com/offchainlabs/nitro/solgen/go/ospgen" + "github.com/offchainlabs/nitro/solgen/go/precompilesgen" "github.com/offchainlabs/nitro/solgen/go/rollupgen" "github.com/offchainlabs/nitro/staker" "github.com/offchainlabs/nitro/util/contracts" @@ -604,7 +605,8 @@ func createNodeImpl( var l1Reader *headerreader.HeaderReader if config.ParentChainReader.Enable { - l1Reader, err = headerreader.New(ctx, l1client, func() *headerreader.Config { return &configFetcher.Get().ParentChainReader }) + arbSys, _ := precompilesgen.NewArbSys(types.ArbSysAddress, l1client) + l1Reader, err = headerreader.New(ctx, l1client, func() *headerreader.Config { return &configFetcher.Get().ParentChainReader }, arbSys) if err != nil { return nil, err } diff --git a/cmd/daserver/daserver.go b/cmd/daserver/daserver.go index 7cdfc39915..335aba6a1b 100644 --- a/cmd/daserver/daserver.go +++ b/cmd/daserver/daserver.go @@ -17,6 +17,7 @@ import ( flag "github.com/spf13/pflag" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/metrics" "github.com/ethereum/go-ethereum/metrics/exp" @@ -24,6 +25,7 @@ import ( "github.com/offchainlabs/nitro/cmd/genericconf" "github.com/offchainlabs/nitro/cmd/util/confighelpers" "github.com/offchainlabs/nitro/das" + "github.com/offchainlabs/nitro/solgen/go/precompilesgen" "github.com/offchainlabs/nitro/util/headerreader" ) @@ -196,7 +198,8 @@ func startup() error { if err != nil { return err } - l1Reader, err = headerreader.New(ctx, l1Client, func() *headerreader.Config { return &headerreader.DefaultConfig }) // TODO: config + arbSys, _ := precompilesgen.NewArbSys(types.ArbSysAddress, l1Client) + l1Reader, err = headerreader.New(ctx, l1Client, func() *headerreader.Config { return &headerreader.DefaultConfig }, arbSys) // TODO: config if err != nil { return err } diff --git a/cmd/deploy/deploy.go b/cmd/deploy/deploy.go index 17725a7a4c..d687821e8b 100644 --- a/cmd/deploy/deploy.go +++ b/cmd/deploy/deploy.go @@ -14,10 +14,12 @@ import ( "github.com/offchainlabs/nitro/cmd/chaininfo" "github.com/offchainlabs/nitro/cmd/genericconf" + "github.com/offchainlabs/nitro/solgen/go/precompilesgen" "github.com/offchainlabs/nitro/util/headerreader" "github.com/offchainlabs/nitro/validator/server_common" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/ethclient" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/params" @@ -127,7 +129,8 @@ func main() { panic(fmt.Errorf("failed to deserialize chain config: %w", err)) } - l1Reader, err := headerreader.New(ctx, l1client, func() *headerreader.Config { return &headerReaderConfig }) + arbSys, _ := precompilesgen.NewArbSys(types.ArbSysAddress, l1client) + l1Reader, err := headerreader.New(ctx, l1client, func() *headerreader.Config { return &headerReaderConfig }, arbSys) if err != nil { panic(fmt.Errorf("failed to create header reader: %w", err)) } diff --git a/cmd/nitro/nitro.go b/cmd/nitro/nitro.go index 4ebe598ee9..a7dc7f26f9 100644 --- a/cmd/nitro/nitro.go +++ b/cmd/nitro/nitro.go @@ -28,6 +28,7 @@ import ( "github.com/ethereum/go-ethereum/accounts/keystore" "github.com/ethereum/go-ethereum/arbitrum" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" _ "github.com/ethereum/go-ethereum/eth/tracers/js" _ "github.com/ethereum/go-ethereum/eth/tracers/native" @@ -48,6 +49,7 @@ import ( "github.com/offchainlabs/nitro/cmd/util" "github.com/offchainlabs/nitro/cmd/util/confighelpers" _ "github.com/offchainlabs/nitro/nodeInterface" + "github.com/offchainlabs/nitro/solgen/go/precompilesgen" "github.com/offchainlabs/nitro/staker" "github.com/offchainlabs/nitro/util/colors" "github.com/offchainlabs/nitro/util/headerreader" @@ -354,7 +356,8 @@ func mainImpl() int { flag.Usage() log.Crit("--node.validator.only-create-wallet-contract requires --node.validator.use-smart-contract-wallet") } - l1Reader, err := headerreader.New(ctx, l1Client, func() *headerreader.Config { return &liveNodeConfig.Get().Node.ParentChainReader }) + arbSys, _ := precompilesgen.NewArbSys(types.ArbSysAddress, l1Client) + l1Reader, err := headerreader.New(ctx, l1Client, func() *headerreader.Config { return &liveNodeConfig.Get().Node.ParentChainReader }, arbSys) if err != nil { log.Crit("failed to get L1 headerreader", "error", err) } diff --git a/cmd/seq-coordinator-manager/rediscoordinator/redis_coordinator.go b/cmd/seq-coordinator-manager/rediscoordinator/redis_coordinator.go new file mode 100644 index 0000000000..782ab3801b --- /dev/null +++ b/cmd/seq-coordinator-manager/rediscoordinator/redis_coordinator.go @@ -0,0 +1,28 @@ +package rediscoordinator + +import ( + "context" + "errors" + "strings" + + "github.com/go-redis/redis/v8" + "github.com/offchainlabs/nitro/util/redisutil" +) + +// RedisCoordinator builds upon RedisCoordinator of redisutil with additional functionality +type RedisCoordinator struct { + *redisutil.RedisCoordinator +} + +// UpdatePriorities updates the priority list of sequencers +func (rc *RedisCoordinator) UpdatePriorities(ctx context.Context, priorities []string) error { + prioritiesString := strings.Join(priorities, ",") + err := rc.Client.Set(ctx, redisutil.PRIORITIES_KEY, prioritiesString, 0).Err() + if err != nil { + if errors.Is(err, redis.Nil) { + err = errors.New("sequencer priorities unset") + } + return err + } + return nil +} diff --git a/cmd/seq-coordinator-manager/seq-coordinator-manager.go b/cmd/seq-coordinator-manager/seq-coordinator-manager.go new file mode 100644 index 0000000000..a0123a9123 --- /dev/null +++ b/cmd/seq-coordinator-manager/seq-coordinator-manager.go @@ -0,0 +1,318 @@ +package main + +import ( + "context" + "fmt" + "os" + "strconv" + + "github.com/enescakir/emoji" + "github.com/ethereum/go-ethereum/log" + "github.com/gdamore/tcell/v2" + "github.com/offchainlabs/nitro/cmd/seq-coordinator-manager/rediscoordinator" + "github.com/offchainlabs/nitro/util/redisutil" + "github.com/rivo/tview" +) + +// Tview +var pages = tview.NewPages() +var app = tview.NewApplication() + +// Lists +var prioritySeqList = tview.NewList().ShowSecondaryText(false) +var nonPrioritySeqList = tview.NewList().ShowSecondaryText(false) + +// Forms +var addSeqForm = tview.NewForm() +var priorityForm = tview.NewForm() +var nonPriorityForm = tview.NewForm() + +// Sequencer coordinator managment UI data store +type manager struct { + redisCoordinator *rediscoordinator.RedisCoordinator + prioritiesSet map[string]bool + livelinessSet map[string]bool + priorityList []string + nonPriorityList []string +} + +func main() { + ctx, cancelFunc := context.WithCancel(context.Background()) + defer cancelFunc() + + args := os.Args[1:] + if len(args) != 1 { + fmt.Fprintf(os.Stderr, "Usage: seq-coordinator-manager [redis-url]\n") + os.Exit(1) + } + redisURL := args[0] + redisutilCoordinator, err := redisutil.NewRedisCoordinator(redisURL) + if err != nil { + panic(err) + } + + seqManager := &manager{ + redisCoordinator: &rediscoordinator.RedisCoordinator{ + RedisCoordinator: redisutilCoordinator, + }, + prioritiesSet: make(map[string]bool), + livelinessSet: make(map[string]bool), + } + + seqManager.refreshAllLists(ctx) + seqManager.populateLists(ctx) + + prioritySeqList.SetSelectedFunc(func(index int, name string, second_name string, shortcut rune) { + nonPriorityForm.Clear(true) + + n := len(seqManager.priorityList) + priorities := make([]string, n) + for i := 0; i < n; i++ { + priorities[i] = strconv.Itoa(i) + } + + target := index + priorityForm.Clear(true) + priorityForm.AddDropDown("Change priority to ->", priorities, index, func(priority string, selection int) { + target = selection + }) + priorityForm.AddButton("Update", func() { + if target != index { + seqManager.updatePriorityList(ctx, index, target) + } + priorityForm.Clear(true) + seqManager.populateLists(ctx) + pages.SwitchToPage("Menu") + app.SetFocus(prioritySeqList) + }) + priorityForm.AddButton("Cancel", func() { + priorityForm.Clear(true) + pages.SwitchToPage("Menu") + app.SetFocus(prioritySeqList) + }) + priorityForm.AddButton("Remove", func() { + url := seqManager.priorityList[index] + delete(seqManager.prioritiesSet, url) + seqManager.updatePriorityList(ctx, index, 0) + seqManager.priorityList = seqManager.priorityList[1:] + + priorityForm.Clear(true) + seqManager.populateLists(ctx) + pages.SwitchToPage("Menu") + app.SetFocus(prioritySeqList) + }) + priorityForm.SetFocus(0) + app.SetFocus(priorityForm) + }) + + nonPrioritySeqList.SetSelectedFunc(func(index int, name string, second_name string, shortcut rune) { + priorityForm.Clear(true) + + n := len(seqManager.priorityList) + priorities := make([]string, n+1) + for i := 0; i < n+1; i++ { + priorities[i] = strconv.Itoa(i) + } + + target := index + nonPriorityForm.Clear(true) + nonPriorityForm.AddDropDown("Set priority to ->", priorities, index, func(priority string, selection int) { + target = selection + }) + nonPriorityForm.AddButton("Update", func() { + key := seqManager.nonPriorityList[index] + seqManager.priorityList = append(seqManager.priorityList, key) + seqManager.prioritiesSet[key] = true + + index = len(seqManager.priorityList) - 1 + seqManager.updatePriorityList(ctx, index, target) + + nonPriorityForm.Clear(true) + seqManager.populateLists(ctx) + pages.SwitchToPage("Menu") + if len(seqManager.nonPriorityList) > 0 { + app.SetFocus(nonPrioritySeqList) + } else { + app.SetFocus(prioritySeqList) + } + }) + nonPriorityForm.AddButton("Cancel", func() { + nonPriorityForm.Clear(true) + pages.SwitchToPage("Menu") + app.SetFocus(nonPrioritySeqList) + }) + nonPriorityForm.SetFocus(0) + app.SetFocus(nonPriorityForm) + }) + + // UI design + flex := tview.NewFlex() + priorityHeading := tview.NewTextView(). + SetTextColor(tcell.ColorYellow). + SetText("-----Priority List-----") + nonPriorityHeading := tview.NewTextView(). + SetTextColor(tcell.ColorYellow). + SetText("-----Not in priority list but online-----") + instructions := tview.NewTextView(). + SetTextColor(tcell.ColorYellow). + SetText("(r) to refresh\n(s) to save all changes\n(c) to switch between lists\n(a) to add sequencer\n(q) to quit\n(tab) to navigate") + + flex.SetDirection(tview.FlexRow). + AddItem(priorityHeading, 0, 1, false). + AddItem(tview.NewFlex(). + AddItem(prioritySeqList, 0, 2, true). + AddItem(priorityForm, 0, 3, true), 0, 12, true). + AddItem(nonPriorityHeading, 0, 1, false). + AddItem(tview.NewFlex(). + AddItem(nonPrioritySeqList, 0, 2, true). + AddItem(nonPriorityForm, 0, 3, true), 0, 12, true). + AddItem(instructions, 0, 3, false).SetBorder(true) + + flex.SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey { + if event.Rune() == 114 { + seqManager.refreshAllLists(ctx) + priorityForm.Clear(true) + nonPriorityForm.Clear(true) + seqManager.populateLists(ctx) + pages.SwitchToPage("Menu") + app.SetFocus(prioritySeqList) + } else if event.Rune() == 115 { + seqManager.pushUpdates(ctx) + priorityForm.Clear(true) + nonPriorityForm.Clear(true) + seqManager.populateLists(ctx) + pages.SwitchToPage("Menu") + app.SetFocus(prioritySeqList) + } else if event.Rune() == 97 { + addSeqForm.Clear(true) + seqManager.addSeqPriorityForm(ctx) + pages.SwitchToPage("Add Sequencer") + } else if event.Rune() == 99 { + if prioritySeqList.HasFocus() || priorityForm.HasFocus() { + priorityForm.Clear(true) + app.SetFocus(nonPrioritySeqList) + } else { + nonPriorityForm.Clear(true) + app.SetFocus(prioritySeqList) + } + } else if event.Rune() == 113 { + app.Stop() + } + return event + }) + + pages.AddPage("Menu", flex, true, true) + pages.AddPage("Add Sequencer", addSeqForm, true, false) + + if err := app.SetRoot(pages, true).EnableMouse(true).Run(); err != nil { + panic(err) + } +} + +// updatePriorityList updates the list by changing the position of seq present at `index` to target +func (sm *manager) updatePriorityList(ctx context.Context, index int, target int) { + for i := index - 1; i >= target; i-- { + sm.priorityList[i], sm.priorityList[i+1] = sm.priorityList[i+1], sm.priorityList[i] + } + for i := index + 1; i <= target; i++ { + sm.priorityList[i], sm.priorityList[i-1] = sm.priorityList[i-1], sm.priorityList[i] + } + + urlList := []string{} + for url := range sm.livelinessSet { + if _, ok := sm.prioritiesSet[url]; !ok { + urlList = append(urlList, url) + } + } + sm.nonPriorityList = urlList +} + +// populateLists populates seq's in priority list and seq's that are online but not in priority +func (sm *manager) populateLists(ctx context.Context) { + prioritySeqList.Clear() + chosen, err := sm.redisCoordinator.CurrentChosenSequencer(ctx) + if err != nil { + panic(err) + } + for index, seqURL := range sm.priorityList { + sec := "" + if seqURL == chosen { + sec = fmt.Sprintf(" %vchosen", emoji.LeftArrow) + } + status := fmt.Sprintf("(%d) %v ", index, emoji.RedCircle) + if _, ok := sm.livelinessSet[seqURL]; ok { + status = fmt.Sprintf("(%d) %v ", index, emoji.GreenCircle) + } + prioritySeqList.AddItem(status+seqURL+sec, "", rune(0), nil).SetSecondaryTextColor(tcell.ColorPurple) + } + + nonPrioritySeqList.Clear() + status := fmt.Sprintf("(-) %v ", emoji.GreenCircle) + for _, seqURL := range sm.nonPriorityList { + nonPrioritySeqList.AddItem(status+seqURL, "", rune(0), nil) + } +} + +// addSeqPriorityForm returns a form with fields to add a new sequencer to priority list +func (sm *manager) addSeqPriorityForm(ctx context.Context) *tview.Form { + URL := "" + addSeqForm.AddInputField("Sequencer URL", "", 0, nil, func(url string) { + URL = url + }) + addSeqForm.AddButton("Cancel", func() { + priorityForm.Clear(true) + sm.populateLists(ctx) + pages.SwitchToPage("Menu") + }) + addSeqForm.AddButton("Add", func() { + // check if url is valid, i.e it doesnt already exist in the priority list + if _, ok := sm.prioritiesSet[URL]; !ok && URL != "" { + sm.prioritiesSet[URL] = true + sm.priorityList = append(sm.priorityList, URL) + } + sm.populateLists(ctx) + pages.SwitchToPage("Menu") + }) + return addSeqForm +} + +// pushUpdates pushes the local changes to the redis server +func (sm *manager) pushUpdates(ctx context.Context) { + err := sm.redisCoordinator.UpdatePriorities(ctx, sm.priorityList) + if err != nil { + log.Warn("Failed to push local changes to the priority list") + } + sm.refreshAllLists(ctx) +} + +// refreshAllLists gets the current status of all the lists displayed in the UI +func (sm *manager) refreshAllLists(ctx context.Context) { + priorityList, err := sm.redisCoordinator.GetPriorities(ctx) + if err != nil { + panic(err) + } + sm.priorityList = priorityList + sm.prioritiesSet = getMapfromlist(priorityList) + + livelinessList, err := sm.redisCoordinator.GetLiveliness(ctx) + if err != nil { + panic(err) + } + sm.livelinessSet = getMapfromlist(livelinessList) + + urlList := []string{} + for url := range sm.livelinessSet { + if _, ok := sm.prioritiesSet[url]; !ok { + urlList = append(urlList, url) + } + } + sm.nonPriorityList = urlList +} + +func getMapfromlist(list []string) map[string]bool { + mapping := make(map[string]bool) + for _, url := range list { + mapping[url] = true + } + return mapping +} diff --git a/go.mod b/go.mod index 10991bc3a2..cc31c4a23d 100644 --- a/go.mod +++ b/go.mod @@ -88,11 +88,14 @@ require ( github.com/dustin/go-humanize v1.0.0 // indirect github.com/elastic/gosigar v0.14.2 // indirect github.com/emirpasic/gods v1.18.1 // indirect + github.com/enescakir/emoji v1.0.0 // indirect github.com/facebookgo/atomicfile v0.0.0-20151019160806-2de1f203e7d5 // indirect github.com/flynn/noise v1.0.0 // indirect github.com/francoispqt/gojay v1.2.13 // indirect github.com/fsnotify/fsnotify v1.6.0 // indirect github.com/gammazero/deque v0.2.1 // indirect + github.com/gdamore/encoding v1.0.0 // indirect + github.com/gdamore/tcell/v2 v2.6.0 // indirect github.com/getsentry/sentry-go v0.18.0 // indirect github.com/go-logr/logr v1.2.3 // indirect github.com/go-logr/stdr v1.2.2 // indirect @@ -190,6 +193,7 @@ require ( github.com/libp2p/go-reuseport v0.2.0 // indirect github.com/libp2p/go-yamux/v4 v4.0.0 // indirect github.com/libp2p/zeroconf/v2 v2.2.0 // indirect + github.com/lucasb-eyer/go-colorful v1.2.0 // indirect github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd // indirect github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect github.com/miekg/dns v1.1.50 // indirect @@ -226,6 +230,8 @@ require ( github.com/quic-go/webtransport-go v0.5.2 // indirect github.com/raulk/go-watchdog v1.3.0 // indirect github.com/rhnvrm/simples3 v0.6.1 // indirect + github.com/rivo/tview v0.0.0-20230814110005-ccc2c8119703 // indirect + github.com/rivo/uniseg v0.4.3 // indirect github.com/rogpeppe/go-internal v1.9.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/samber/lo v1.36.0 // indirect @@ -298,7 +304,7 @@ require ( github.com/jackpal/go-nat-pmp v1.0.2 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.17 // indirect - github.com/mattn/go-runewidth v0.0.9 // indirect + github.com/mattn/go-runewidth v0.0.14 // indirect github.com/mitchellh/mapstructure v1.4.2 github.com/mitchellh/pointerstructure v1.2.0 // indirect github.com/olekukonko/tablewriter v0.0.5 // indirect diff --git a/go.sum b/go.sum index 83b480bed8..4362d4b01d 100644 --- a/go.sum +++ b/go.sum @@ -309,6 +309,8 @@ github.com/elastic/gosigar v0.14.2 h1:Dg80n8cr90OZ7x+bAax/QjoW/XqTI11RmA79ZwIm9/ github.com/elastic/gosigar v0.14.2/go.mod h1:iXRIGg2tLnu7LBdpqzyQfGDEidKCfWcCMS0WKyPWoMs= github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= +github.com/enescakir/emoji v1.0.0 h1:W+HsNql8swfCQFtioDGDHCHri8nudlK1n5p2rHCJoog= +github.com/enescakir/emoji v1.0.0/go.mod h1:Bt1EKuLnKDTYpLALApstIkAjdDrS/8IAgTkKp+WKFD0= github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= @@ -349,6 +351,10 @@ github.com/gammazero/deque v0.2.1/go.mod h1:LFroj8x4cMYCukHJDbxFCkT+r9AndaJnFMuZ github.com/gavv/httpexpect v2.0.0+incompatible/go.mod h1:x+9tiU1YnrOvnB725RkpoLv1M62hOWzwo5OXotisrKc= github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff h1:tY80oXqGNY4FhTFhk+o9oFHGINQ/+vhlm8HFzi6znCI= github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww= +github.com/gdamore/encoding v1.0.0 h1:+7OoQ1Bc6eTm5niUzBa0Ctsh6JbMW6Ra+YNuAtDBdko= +github.com/gdamore/encoding v1.0.0/go.mod h1:alR0ol34c49FCSBLjhosxzcPHQbf2trDkoo5dl+VrEg= +github.com/gdamore/tcell/v2 v2.6.0 h1:OKbluoP9VYmJwZwq/iLb4BxwKcwGthaa1YNBJIyCySg= +github.com/gdamore/tcell/v2 v2.6.0/go.mod h1:be9omFATkdr0D9qewWW3d+MEvl5dha+Etb5y65J2H8Y= github.com/getsentry/sentry-go v0.12.0/go.mod h1:NSap0JBYWzHND8oMbyi0+XZhUalc1TBdRL1M71JZW2c= github.com/getsentry/sentry-go v0.18.0 h1:MtBW5H9QgdcJabtZcuJG80BMOwaBpkRDZkxRkNC1sN0= github.com/getsentry/sentry-go v0.18.0/go.mod h1:Kgon4Mby+FJ7ZWHFUAZgVaIa8sxHtnRJRLTXZr51aKQ= @@ -1141,6 +1147,8 @@ github.com/libp2p/zeroconf/v2 v2.2.0/go.mod h1:fuJqLnUwZTshS3U/bMRJ3+ow/v9oid1n0 github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM= github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4= github.com/lucas-clemente/quic-go v0.19.3/go.mod h1:ADXpNbTQjq1hIzCpB+y/k5iz4n4z4IwqoLb94Kh5Hu8= +github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY= +github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI= github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= @@ -1175,6 +1183,8 @@ github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/ github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= +github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU= +github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= @@ -1444,6 +1454,11 @@ github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqn github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/rhnvrm/simples3 v0.6.1 h1:H0DJwybR6ryQE+Odi9eqkHuzjYAeJgtGcGtuBwOhsH8= github.com/rhnvrm/simples3 v0.6.1/go.mod h1:Y+3vYm2V7Y4VijFoJHHTrja6OgPrJ2cBti8dPGkC3sA= +github.com/rivo/tview v0.0.0-20230814110005-ccc2c8119703 h1:ZyM/+FYnpbZsFWuCohniM56kRoHRB4r5EuIzXEYkpxo= +github.com/rivo/tview v0.0.0-20230814110005-ccc2c8119703/go.mod h1:nVwGv4MP47T0jvlk7KuTTjjuSmrGO4JF0iaiNt4bufE= +github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= +github.com/rivo/uniseg v0.4.3 h1:utMvzDsuh3suAEnhH0RdHmoPbU648o6CvXxTx4SBMOw= +github.com/rivo/uniseg v0.4.3/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= @@ -1632,6 +1647,7 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/yuin/gopher-lua v0.0.0-20210529063254-f4c35e4016d9 h1:k/gmLsJDWwWqbLCur2yWnJzwQEKRcAHXo6seXGuSwWw= github.com/yuin/gopher-lua v0.0.0-20210529063254-f4c35e4016d9/go.mod h1:E1AXubJBdNmFERAOucpDIxNzeGfLzg0mYh+UfMWdChA= go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= @@ -1775,6 +1791,7 @@ golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzB golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.9.0 h1:KENHtAZL2y3NLMYZeHY9DW8HW8V+kQyJsY/V9JlKvCs= golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20180406214816-61147c48b25b/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -1836,6 +1853,7 @@ golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210917221730-978cfadd31cf/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211008194852-3b03d305991f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ= golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -1858,6 +1876,7 @@ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180810173357-98c5dad5d1a0/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -1949,13 +1968,20 @@ golang.org/x/sys v0.0.0-20210910150752-751e447fb3d0/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU= golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.6.0 h1:clScbb1cHjoCkyRbWwBEUZ5H/tIFu5TAXIqaZD0Gcjw= golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -1967,6 +1993,7 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68= golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -2036,6 +2063,7 @@ golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.7.0 h1:W4OVu8VVOaIO0yzWMNdepAulS7YfoS3Zabrm8DOXXU4= golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/staker/staker.go b/staker/staker.go index 8fdbbd648f..1b6538b161 100644 --- a/staker/staker.go +++ b/staker/staker.go @@ -552,11 +552,11 @@ func (s *Staker) confirmDataPosterIsReady(ctx context.Context) error { } func (s *Staker) Act(ctx context.Context) (*types.Transaction, error) { - err := s.confirmDataPosterIsReady(ctx) - if err != nil { - return nil, err - } if s.config.strategy != WatchtowerStrategy { + err := s.confirmDataPosterIsReady(ctx) + if err != nil { + return nil, err + } whitelisted, err := s.IsWhitelisted(ctx) if err != nil { return nil, fmt.Errorf("error checking if whitelisted: %w", err) diff --git a/system_tests/common_test.go b/system_tests/common_test.go index b92fbf7578..9fd002bd94 100644 --- a/system_tests/common_test.go +++ b/system_tests/common_test.go @@ -476,7 +476,8 @@ func DeployOnTestL1( serializedChainConfig, err := json.Marshal(chainConfig) Require(t, err) - l1Reader, err := headerreader.New(ctx, l1client, func() *headerreader.Config { return &headerreader.TestConfig }) + arbSys, _ := precompilesgen.NewArbSys(types.ArbSysAddress, l1client) + l1Reader, err := headerreader.New(ctx, l1client, func() *headerreader.Config { return &headerreader.TestConfig }, arbSys) Require(t, err) l1Reader.Start(ctx) defer l1Reader.StopAndWait() diff --git a/system_tests/das_test.go b/system_tests/das_test.go index 7952120933..8889d2d53d 100644 --- a/system_tests/das_test.go +++ b/system_tests/das_test.go @@ -28,6 +28,7 @@ import ( "github.com/offchainlabs/nitro/cmd/genericconf" "github.com/offchainlabs/nitro/das" "github.com/offchainlabs/nitro/solgen/go/bridgegen" + "github.com/offchainlabs/nitro/solgen/go/precompilesgen" "github.com/offchainlabs/nitro/util/headerreader" "github.com/offchainlabs/nitro/util/signature" ) @@ -233,7 +234,8 @@ func TestDASComplexConfigAndRestMirror(t *testing.T) { chainConfig := params.ArbitrumDevTestDASChainConfig() l1info, l1client, _, l1stack := createTestL1BlockChain(t, nil) defer requireClose(t, l1stack) - l1Reader, err := headerreader.New(ctx, l1client, func() *headerreader.Config { return &headerreader.TestConfig }) + arbSys, _ := precompilesgen.NewArbSys(types.ArbSysAddress, l1client) + l1Reader, err := headerreader.New(ctx, l1client, func() *headerreader.Config { return &headerreader.TestConfig }, arbSys) Require(t, err) l1Reader.Start(ctx) defer l1Reader.StopAndWait() diff --git a/util/headerreader/header_reader.go b/util/headerreader/header_reader.go index e5807224c0..befd54ace3 100644 --- a/util/headerreader/header_reader.go +++ b/util/headerreader/header_reader.go @@ -18,17 +18,20 @@ import ( "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/rpc" "github.com/offchainlabs/nitro/arbutil" - "github.com/offchainlabs/nitro/solgen/go/precompilesgen" "github.com/offchainlabs/nitro/util/stopwaiter" flag "github.com/spf13/pflag" ) +type ArbSysInterface interface { + ArbBlockNumber(*bind.CallOpts) (*big.Int, error) +} + type HeaderReader struct { stopwaiter.StopWaiter config ConfigFetcher client arbutil.L1Interface isParentChainArbitrum bool - arbSys *precompilesgen.ArbSys + arbSys ArbSysInterface chanMutex sync.RWMutex // All fields below require the chanMutex @@ -91,19 +94,18 @@ var TestConfig = Config{ UseFinalityData: false, } -func New(ctx context.Context, client arbutil.L1Interface, config ConfigFetcher) (*HeaderReader, error) { +func New(ctx context.Context, client arbutil.L1Interface, config ConfigFetcher, arbSysPrecompile ArbSysInterface) (*HeaderReader, error) { isParentChainArbitrum := false - var arbSys *precompilesgen.ArbSys - codeAt, err := client.CodeAt(ctx, types.ArbSysAddress, nil) - if err != nil { - return nil, err - } - if len(codeAt) != 0 { - isParentChainArbitrum = true - arbSys, err = precompilesgen.NewArbSys(types.ArbSysAddress, client) + var arbSys ArbSysInterface + if arbSysPrecompile != nil { + codeAt, err := client.CodeAt(ctx, types.ArbSysAddress, nil) if err != nil { return nil, err } + if len(codeAt) != 0 { + isParentChainArbitrum = true + arbSys = arbSysPrecompile + } } return &HeaderReader{ client: client, diff --git a/util/redisutil/redis_coordinator.go b/util/redisutil/redis_coordinator.go index 0ee92fef17..357dfb2e93 100644 --- a/util/redisutil/redis_coordinator.go +++ b/util/redisutil/redis_coordinator.go @@ -76,6 +76,32 @@ func (c *RedisCoordinator) CurrentChosenSequencer(ctx context.Context) (string, return current, nil } +// GetPriorities returns the priority list of sequencers +func (rc *RedisCoordinator) GetPriorities(ctx context.Context) ([]string, error) { + prioritiesString, err := rc.Client.Get(ctx, PRIORITIES_KEY).Result() + if err != nil { + if errors.Is(err, redis.Nil) { + err = errors.New("sequencer priorities unset") + } + return []string{}, err + } + prioritiesList := strings.Split(prioritiesString, ",") + return prioritiesList, nil +} + +// GetLiveliness returns a map whose keys are sequencers that have their liveliness set to OK +func (rc *RedisCoordinator) GetLiveliness(ctx context.Context) ([]string, error) { + livelinessList, _, err := rc.Client.Scan(ctx, 0, WANTS_LOCKOUT_KEY_PREFIX+"*", 0).Result() + if err != nil { + return []string{}, err + } + for i, elem := range livelinessList { + url := strings.TrimPrefix(elem, WANTS_LOCKOUT_KEY_PREFIX) + livelinessList[i] = url + } + return livelinessList, nil +} + func MessageKeyFor(pos arbutil.MessageIndex) string { return fmt.Sprintf("%s%d", MESSAGE_KEY_PREFIX, pos) }