From fbb47c9648c66e10241b3db955bbf056698a3083 Mon Sep 17 00:00:00 2001 From: Omri Date: Sun, 3 Sep 2023 12:44:17 +0300 Subject: [PATCH 1/7] feat: try to append empty block at the end of each non-empty batch (#472) --- block/manager.go | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/block/manager.go b/block/manager.go index e971bbf4d..1fbe512ab 100644 --- a/block/manager.go +++ b/block/manager.go @@ -71,11 +71,13 @@ type Manager struct { syncTargetDiode diodes.Diode shouldProduceBlocksCh chan bool + produceEmptyBlockCh chan bool syncTarget uint64 lastSubmissionTime int64 batchInProcess atomic.Value isSyncedCond sync.Cond + produceBlockMutex sync.Mutex syncCache map[uint64]*types.Block @@ -167,6 +169,7 @@ func NewManager( isSyncedCond: *sync.NewCond(new(sync.Mutex)), batchInProcess: batchInProcess, shouldProduceBlocksCh: make(chan bool, 1), + produceEmptyBlockCh: make(chan bool, 1), logger: logger, } @@ -310,6 +313,11 @@ func (m *Manager) SubmitLoop(ctx context.Context) { } m.batchInProcess.Store(true) + // We try and produce an empty block to make sure releavnt ibc messages will pass through during the batch submission: https://github.com/dymensionxyz/research/issues/173. + err := m.produceBlock(ctx, true) + if err != nil { + m.logger.Error("error while producing empty block", "error", err) + } m.submitNextBatch(ctx) } } @@ -346,6 +354,9 @@ func (m *Manager) ProduceBlockLoop(ctx context.Context) { //Context canceled case <-ctx.Done(): return + // If we got a request for an empty block produce it and don't wait for the ticker + case <-m.produceEmptyBlockCh: + produceEmptyBlock = true //Empty blocks timeout case <-tickerEmptyBlocksMaxTimeCh: m.logger.Debug(fmt.Sprintf("No transactions for %.2f seconds, producing empty block", m.conf.EmptyBlocksMaxTime.Seconds())) @@ -673,6 +684,8 @@ func (m *Manager) fetchBatch(daHeight uint64) (da.ResultRetrieveBatch, error) { } func (m *Manager) produceBlock(ctx context.Context, allowEmpty bool) error { + m.produceBlockMutex.Lock() + defer m.produceBlockMutex.Unlock() var lastCommit *types.Commit var lastHeaderHash [32]byte var err error @@ -749,6 +762,16 @@ func (m *Manager) submitNextBatch(ctx context.Context) { startHeight := atomic.LoadUint64(&m.syncTarget) + 1 endHeight := uint64(m.lastState.LastBlockHeight) + isLastBlockEmpty, err := m.validateLastBlockInBatchIsEmpty(startHeight, endHeight) + if err != nil { + m.logger.Error("Failed to validate last block in batch is empty", "startHeight", startHeight, "endHeight", endHeight, "error", err) + return + } + if !isLastBlockEmpty { + m.logger.Info("Requesting for an empty block creation") + m.produceEmptyBlockCh <- true + } + // Create the batch nextBatch, err := m.createNextDABatch(startHeight, endHeight) if err != nil { @@ -771,6 +794,23 @@ func (m *Manager) submitNextBatch(ctx context.Context) { m.settlementClient.SubmitBatch(nextBatch, m.dalc.GetClientType(), &resultSubmitToDA) } +// Verify the last block in the batch is an empty block and that no ibc messages has accidentially passed through. +// This block may not be empty if another block has passed it in line. If that's the case our empty block request will +// be sent to the next batch. +func (m *Manager) validateLastBlockInBatchIsEmpty(startHeight uint64, endHeight uint64) (bool, error) { + m.logger.Debug("Verifying last block in batch is an empty block", "startHeight", startHeight, "endHeight", endHeight, "height") + lastBlock, err := m.store.LoadBlock(endHeight) + if err != nil { + m.logger.Error("Failed to load block", "height", endHeight, "error", err) + return false, err + } + if len(lastBlock.Data.Txs) != 0 { + m.logger.Info("Last block in batch is not an empty block", "startHeight", startHeight, "endHeight", endHeight, "height") + return false, nil + } + return true, nil +} + func (m *Manager) updateStateIndex(stateIndex uint64) error { atomic.StoreUint64(&m.lastState.SLStateIndex, stateIndex) _, err := m.store.UpdateState(m.lastState, nil) From a18f8c5606cdedf797671c7c8709d4e67b381531 Mon Sep 17 00:00:00 2001 From: Michael Tsitrin <114929630+mtsitrin@users.noreply.github.com> Date: Tue, 12 Sep 2023 10:11:24 +0300 Subject: [PATCH 2/7] chore: Block package refactor (#480) --- block/block.go | 178 ++++++++++++ block/manager.go | 614 ------------------------------------------ block/manager_test.go | 130 +-------- block/produce.go | 183 +++++++++++++ block/retriever.go | 101 +++++++ block/submit.go | 146 ++++++++++ block/synctarget.go | 56 ++++ block/testutil.go | 149 ++++++++++ 8 files changed, 814 insertions(+), 743 deletions(-) create mode 100644 block/block.go create mode 100644 block/produce.go create mode 100644 block/retriever.go create mode 100644 block/submit.go create mode 100644 block/synctarget.go create mode 100644 block/testutil.go diff --git a/block/block.go b/block/block.go new file mode 100644 index 000000000..2f4ec8167 --- /dev/null +++ b/block/block.go @@ -0,0 +1,178 @@ +package block + +import ( + "context" + + "cosmossdk.io/errors" + "github.com/dymensionxyz/dymint/p2p" + "github.com/dymensionxyz/dymint/types" + tmstate "github.com/tendermint/tendermint/proto/tendermint/state" + tmtypes "github.com/tendermint/tendermint/types" +) + +// applyBlock applies the block to the store and the abci app. +// steps: save block -> execute block with app -> update state -> commit block to app -> update store height and state hash. +// As the entire process can't be atomic we need to make sure the following condition apply before +// we're applying the block in the happy path: block height - 1 == abci app last block height. +// In case the following doesn't hold true, it means we crashed after the commit and before updating the store height. +// In that case we'll want to align the store with the app state and continue to the next block. +func (m *Manager) applyBlock(ctx context.Context, block *types.Block, commit *types.Commit, blockMetaData blockMetaData) error { + if block.Header.Height != m.store.Height()+1 { + // We crashed after the commit and before updating the store height. + return nil + } + + m.logger.Debug("Applying block", "height", block.Header.Height, "source", blockMetaData.source) + + // Check if alignment is needed due to incosistencies between the store and the app. + isAlignRequired, err := m.alignStoreWithApp(ctx, block) + if err != nil { + return err + } + if isAlignRequired { + m.logger.Debug("Aligned with app state required. Skipping to next block", "height", block.Header.Height) + return nil + } + // Start applying the block assuming no inconsistency was found. + _, err = m.store.SaveBlock(block, commit, nil) + if err != nil { + m.logger.Error("Failed to save block", "error", err) + return err + } + + responses, err := m.executeBlock(ctx, block, commit) + if err != nil { + m.logger.Error("Failed to execute block", "error", err) + return err + } + + newState, err := m.executor.UpdateStateFromResponses(responses, m.lastState, block) + if err != nil { + return err + } + + batch := m.store.NewBatch() + + batch, err = m.store.SaveBlockResponses(block.Header.Height, responses, batch) + if err != nil { + batch.Discard() + return err + } + + m.lastState = newState + batch, err = m.store.UpdateState(m.lastState, batch) + if err != nil { + batch.Discard() + return err + } + batch, err = m.store.SaveValidators(block.Header.Height, m.lastState.Validators, batch) + if err != nil { + batch.Discard() + return err + } + + err = batch.Commit() + if err != nil { + m.logger.Error("Failed to persist batch to disk", "error", err) + return err + } + + // Commit block to app + retainHeight, err := m.executor.Commit(ctx, &newState, block, responses) + if err != nil { + m.logger.Error("Failed to commit to the block", "error", err) + return err + } + + // Prune old heights, if requested by ABCI app. + if retainHeight > 0 { + pruned, err := m.pruneBlocks(retainHeight) + if err != nil { + m.logger.Error("failed to prune blocks", "retain_height", retainHeight, "err", err) + } else { + m.logger.Debug("pruned blocks", "pruned", pruned, "retain_height", retainHeight) + } + } + + // Update the state with the new app hash, last validators and store height from the commit. + // Every one of those, if happens before commit, prevents us from re-executing the block in case failed during commit. + newState.LastValidators = m.lastState.Validators.Copy() + newState.LastStoreHeight = block.Header.Height + newState.BaseHeight = m.store.Base() + + _, err = m.store.UpdateState(newState, nil) + if err != nil { + m.logger.Error("Failed to update state", "error", err) + return err + } + m.lastState = newState + + m.store.SetHeight(block.Header.Height) + + return nil +} + +// alignStoreWithApp is responsible for aligning the state of the store and the abci app if necessary. +func (m *Manager) alignStoreWithApp(ctx context.Context, block *types.Block) (bool, error) { + isRequired := false + // Validate incosistency in height wasn't caused by a crash and if so handle it. + proxyAppInfo, err := m.executor.GetAppInfo() + if err != nil { + return isRequired, errors.Wrap(err, "failed to get app info") + } + if uint64(proxyAppInfo.LastBlockHeight) != block.Header.Height { + return isRequired, nil + } + + isRequired = true + m.logger.Info("Skipping block application and only updating store height and state hash", "height", block.Header.Height) + // update the state with the hash, last store height and last validators. + m.lastState.AppHash = *(*[32]byte)(proxyAppInfo.LastBlockAppHash) + m.lastState.LastStoreHeight = block.Header.Height + m.lastState.LastValidators = m.lastState.Validators.Copy() + + resp, err := m.store.LoadBlockResponses(block.Header.Height) + if err != nil { + return isRequired, errors.Wrap(err, "failed to load block responses") + } + copy(m.lastState.LastResultsHash[:], tmtypes.NewResults(resp.DeliverTxs).Hash()) + + _, err = m.store.UpdateState(m.lastState, nil) + if err != nil { + return isRequired, errors.Wrap(err, "failed to update state") + } + m.store.SetHeight(block.Header.Height) + return isRequired, nil +} + +func (m *Manager) executeBlock(ctx context.Context, block *types.Block, commit *types.Commit) (*tmstate.ABCIResponses, error) { + // Currently we're assuming proposer is never nil as it's a pre-condition for + // dymint to start + proposer := m.settlementClient.GetProposer() + + if err := m.executor.Validate(m.lastState, block, commit, proposer); err != nil { + return &tmstate.ABCIResponses{}, err + } + + responses, err := m.executor.Execute(ctx, m.lastState, block) + if err != nil { + return &tmstate.ABCIResponses{}, err + } + + return responses, nil +} + +func (m *Manager) gossipBlock(ctx context.Context, block types.Block, commit types.Commit) error { + gossipedBlock := p2p.GossipedBlock{Block: block, Commit: commit} + gossipedBlockBytes, err := gossipedBlock.MarshalBinary() + if err != nil { + m.logger.Error("Failed to marshal block", "error", err) + return err + } + if err := m.p2pClient.GossipBlock(ctx, gossipedBlockBytes); err != nil { + m.logger.Error("Failed to gossip block", "error", err) + return err + } + return nil + +} diff --git a/block/manager.go b/block/manager.go index 1fbe512ab..6f2048d90 100644 --- a/block/manager.go +++ b/block/manager.go @@ -5,14 +5,11 @@ import ( "fmt" "sync" "sync/atomic" - "time" "code.cloudfoundry.org/go-diodes" - "cosmossdk.io/errors" "github.com/avast/retry-go/v4" cryptocodec "github.com/cosmos/cosmos-sdk/crypto/codec" - abciconv "github.com/dymensionxyz/dymint/conv/abci" "github.com/dymensionxyz/dymint/node/events" "github.com/dymensionxyz/dymint/p2p" "github.com/dymensionxyz/dymint/utils" @@ -21,7 +18,6 @@ import ( tmcrypto "github.com/tendermint/tendermint/crypto" "github.com/tendermint/tendermint/crypto/merkle" "github.com/tendermint/tendermint/libs/pubsub" - tmstate "github.com/tendermint/tendermint/proto/tendermint/state" "github.com/tendermint/tendermint/proxy" tmtypes "github.com/tendermint/tendermint/types" @@ -256,616 +252,6 @@ func (m *Manager) getLatestBatchFromSL(ctx context.Context) (*settlement.ResultR } -// waitForSync enforces the aggregator to be synced before it can produce blocks. -// It requires the retriveBlockLoop to be running. -func (m *Manager) waitForSync(ctx context.Context) error { - resultRetrieveBatch, err := m.getLatestBatchFromSL(ctx) - // Set the syncTarget according to the result - if err == settlement.ErrBatchNotFound { - // Since we requested the latest batch and got batch not found it means - // the SL still hasn't got any batches for this chain. - m.logger.Info("No batches for chain found in SL. Start writing first batch") - atomic.StoreUint64(&m.syncTarget, uint64(m.genesis.InitialHeight-1)) - return nil - } else if err != nil { - m.logger.Error("failed to retrieve batch from SL", "err", err) - return err - } else { - m.updateSyncParams(ctx, resultRetrieveBatch.EndHeight) - } - // Wait until isSynced is true and then call the PublishBlockLoop - m.isSyncedCond.L.Lock() - // Wait until we're synced and that we have got the latest batch (if we didn't, m.syncTarget == 0) - // before we start publishing blocks - for m.store.Height() < atomic.LoadUint64(&m.syncTarget) { - m.logger.Info("Waiting for sync", "current height", m.store.Height(), "syncTarget", atomic.LoadUint64(&m.syncTarget)) - m.isSyncedCond.Wait() - } - m.isSyncedCond.L.Unlock() - m.logger.Info("Synced, Starting to produce", "current height", m.store.Height(), "syncTarget", atomic.LoadUint64(&m.syncTarget)) - return nil -} - -func (m *Manager) SubmitLoop(ctx context.Context) { - ticker := time.NewTicker(m.conf.BatchSubmitMaxTime) - defer ticker.Stop() - - for { - select { - //Context canceled - case <-ctx.Done(): - return - //TODO: add the case of batch size (should be signaled from the the block production) - // case <- requiredByNumOfBlocks - case <-ticker.C: - // SyncTarget is the height of the last block in the last batch as seen by this node. - syncTarget := atomic.LoadUint64(&m.syncTarget) - height := m.store.Height() - //no new blocks produced yet - if (height - syncTarget) == 0 { - continue - } - - // Submit batch if we've reached the batch size and there isn't another batch currently in submission process. - if m.batchInProcess.Load() == true { - m.logger.Debug("Batch submission already in process, skipping submission") - continue - } - - m.batchInProcess.Store(true) - // We try and produce an empty block to make sure releavnt ibc messages will pass through during the batch submission: https://github.com/dymensionxyz/research/issues/173. - err := m.produceBlock(ctx, true) - if err != nil { - m.logger.Error("error while producing empty block", "error", err) - } - m.submitNextBatch(ctx) - } - } -} - -// ProduceBlockLoop is calling publishBlock in a loop as long as wer'e synced. -func (m *Manager) ProduceBlockLoop(ctx context.Context) { - atomic.StoreInt64(&m.lastSubmissionTime, time.Now().Unix()) - - // We want to wait until we are synced. After that, since there is no leader - // election yet, and leader are elected manually, we will not be out of sync until - // we are manually being replaced. - err := m.waitForSync(ctx) - if err != nil { - panic(errors.Wrap(err, "failed to wait for sync")) - } - - ticker := time.NewTicker(m.conf.BlockTime) - defer ticker.Stop() - - var tickerEmptyBlocksMaxTime *time.Ticker - var tickerEmptyBlocksMaxTimeCh <-chan time.Time - // Setup ticker for empty blocks if enabled - if m.conf.EmptyBlocksMaxTime > 0 { - tickerEmptyBlocksMaxTime = time.NewTicker(m.conf.EmptyBlocksMaxTime) - tickerEmptyBlocksMaxTimeCh = tickerEmptyBlocksMaxTime.C - defer tickerEmptyBlocksMaxTime.Stop() - } - - //Allow the initial block to be empty - produceEmptyBlock := true - for { - select { - //Context canceled - case <-ctx.Done(): - return - // If we got a request for an empty block produce it and don't wait for the ticker - case <-m.produceEmptyBlockCh: - produceEmptyBlock = true - //Empty blocks timeout - case <-tickerEmptyBlocksMaxTimeCh: - m.logger.Debug(fmt.Sprintf("No transactions for %.2f seconds, producing empty block", m.conf.EmptyBlocksMaxTime.Seconds())) - produceEmptyBlock = true - //Produce block - case <-ticker.C: - err := m.produceBlock(ctx, produceEmptyBlock) - if err == types.ErrSkippedEmptyBlock { - m.logger.Debug("Skipped empty block") - continue - } - if err != nil { - m.logger.Error("error while producing block", "error", err) - continue - } - //If empty blocks enabled, after block produced, reset the timeout timer - if tickerEmptyBlocksMaxTime != nil { - produceEmptyBlock = false - tickerEmptyBlocksMaxTime.Reset(m.conf.EmptyBlocksMaxTime) - } - - //Node's health check channel - case shouldProduceBlocks := <-m.shouldProduceBlocksCh: - for !shouldProduceBlocks { - m.logger.Info("Stopped block production") - shouldProduceBlocks = <-m.shouldProduceBlocksCh - } - m.logger.Info("Resumed Block production") - } - } -} - -// SyncTargetLoop is responsible for getting real time updates about batches submission. -// for non aggregator: updating the sync target which will be used by retrieveLoop to sync until this target. -// for aggregator: get notification that batch has been accepted so can send next batch. -func (m *Manager) SyncTargetLoop(ctx context.Context) { - m.logger.Info("Started sync target loop") - subscription, err := m.pubsub.Subscribe(ctx, "syncTargetLoop", settlement.EventQueryNewBatchAccepted) - if err != nil { - m.logger.Error("failed to subscribe to state update events") - panic(err) - } - // First time we start we want to get the latest batch from the SL - resultRetrieveBatch, err := m.getLatestBatchFromSL(ctx) - if err != nil { - m.logger.Error("failed to retrieve batch from SL", "err", err) - } else { - m.updateSyncParams(ctx, resultRetrieveBatch.EndHeight) - } - for { - select { - case <-ctx.Done(): - return - case event := <-subscription.Out(): - eventData := event.Data().(*settlement.EventDataNewBatchAccepted) - m.updateSyncParams(ctx, eventData.EndHeight) - // In case we are the aggregator and we've got an update, then we can stop blocking from - // the next batches to be published. For non-aggregators this is not needed. - // We only want to send the next once the previous has been published successfully. - // TODO(omritoptix): Once we have leader election, we can add a condition. - // Update batch accepted is only relevant for the aggregator - // TODO(omritoptix): Check if we are the aggregator - m.batchInProcess.Store(false) - case <-subscription.Cancelled(): - m.logger.Info("Subscription canceled") - } - } -} - -// updateSyncParams updates the sync target and state index if necessary -func (m *Manager) updateSyncParams(ctx context.Context, endHeight uint64) { - rollappHubHeightGauge.Set(float64(endHeight)) - m.logger.Info("Received new syncTarget", "syncTarget", endHeight) - atomic.StoreUint64(&m.syncTarget, endHeight) - atomic.StoreInt64(&m.lastSubmissionTime, time.Now().UnixNano()) - m.syncTargetDiode.Set(diodes.GenericDataType(&endHeight)) -} - -// RetriveLoop listens for new sync messages written to a ring buffer and in turn -// runs syncUntilTarget on the latest message in the ring buffer. -func (m *Manager) RetriveLoop(ctx context.Context) { - m.logger.Info("Started retrieve loop") - syncTargetpoller := diodes.NewPoller(m.syncTargetDiode) - for { - select { - case <-ctx.Done(): - return - default: - // Get only the latest sync target - syncTarget := syncTargetpoller.Next() - m.syncUntilTarget(ctx, *(*uint64)(syncTarget)) - // Check if after we sync we are synced or a new syncTarget was already set. - // If we are synced then signal all goroutines waiting on isSyncedCond. - if m.store.Height() >= atomic.LoadUint64(&m.syncTarget) { - m.logger.Info("Synced at height", "height", m.store.Height()) - m.isSyncedCond.L.Lock() - m.isSyncedCond.Signal() - m.isSyncedCond.L.Unlock() - } - } - } -} - -// syncUntilTarget syncs the block until the syncTarget is reached. -// It fetches the batches from the settlement, gets the DA height and gets -// the actual blocks from the DA. -func (m *Manager) syncUntilTarget(ctx context.Context, syncTarget uint64) { - currentHeight := m.store.Height() - for currentHeight < syncTarget { - m.logger.Info("Syncing until target", "current height", currentHeight, "syncTarget", syncTarget) - resultRetrieveBatch, err := m.settlementClient.RetrieveBatch(atomic.LoadUint64(&m.lastState.SLStateIndex) + 1) - if err != nil { - m.logger.Error("Failed to sync until target. error while retrieving batch", "error", err) - continue - } - err = m.processNextDABatch(ctx, resultRetrieveBatch.MetaData.DA.Height) - if err != nil { - m.logger.Error("Failed to sync until target. error while processing next DA batch", "error", err) - break - } - err = m.updateStateIndex(resultRetrieveBatch.StateIndex) - if err != nil { - return - } - currentHeight = m.store.Height() - } -} - -// applyBlock applies the block to the store and the abci app. -// steps: save block -> execute block with app -> update state -> commit block to app -> update store height and state hash. -// As the entire process can't be atomic we need to make sure the following condition apply before -// we're applying the block in the happy path: block height - 1 == abci app last block height. -// In case the following doesn't hold true, it means we crashed after the commit and before updating the store height. -// In that case we'll want to align the store with the app state and continue to the next block. -func (m *Manager) applyBlock(ctx context.Context, block *types.Block, commit *types.Commit, blockMetaData blockMetaData) error { - if block.Header.Height != m.store.Height()+1 { - // We crashed after the commit and before updating the store height. - return nil - } - - m.logger.Debug("Applying block", "height", block.Header.Height, "source", blockMetaData.source) - - // Check if alignment is needed due to incosistencies between the store and the app. - isAlignRequired, err := m.alignStoreWithApp(ctx, block) - if err != nil { - return err - } - if isAlignRequired { - m.logger.Debug("Aligned with app state required. Skipping to next block", "height", block.Header.Height) - return nil - } - // Start applying the block assuming no inconsistency was found. - _, err = m.store.SaveBlock(block, commit, nil) - if err != nil { - m.logger.Error("Failed to save block", "error", err) - return err - } - - responses, err := m.executeBlock(ctx, block, commit) - if err != nil { - m.logger.Error("Failed to execute block", "error", err) - return err - } - - newState, err := m.executor.UpdateStateFromResponses(responses, m.lastState, block) - if err != nil { - return err - } - - batch := m.store.NewBatch() - - batch, err = m.store.SaveBlockResponses(block.Header.Height, responses, batch) - if err != nil { - batch.Discard() - return err - } - - m.lastState = newState - batch, err = m.store.UpdateState(m.lastState, batch) - if err != nil { - batch.Discard() - return err - } - batch, err = m.store.SaveValidators(block.Header.Height, m.lastState.Validators, batch) - if err != nil { - batch.Discard() - return err - } - - err = batch.Commit() - if err != nil { - m.logger.Error("Failed to persist batch to disk", "error", err) - return err - } - - // Commit block to app - retainHeight, err := m.executor.Commit(ctx, &newState, block, responses) - if err != nil { - m.logger.Error("Failed to commit to the block", "error", err) - return err - } - - // Prune old heights, if requested by ABCI app. - if retainHeight > 0 { - pruned, err := m.pruneBlocks(retainHeight) - if err != nil { - m.logger.Error("failed to prune blocks", "retain_height", retainHeight, "err", err) - } else { - m.logger.Debug("pruned blocks", "pruned", pruned, "retain_height", retainHeight) - } - } - - // Update the state with the new app hash, last validators and store height from the commit. - // Every one of those, if happens before commit, prevents us from re-executing the block in case failed during commit. - newState.LastValidators = m.lastState.Validators.Copy() - newState.LastStoreHeight = block.Header.Height - newState.BaseHeight = m.store.Base() - - _, err = m.store.UpdateState(newState, nil) - if err != nil { - m.logger.Error("Failed to update state", "error", err) - return err - } - m.lastState = newState - - m.store.SetHeight(block.Header.Height) - - return nil -} - -// alignStoreWithApp is responsible for aligning the state of the store and the abci app if necessary. -func (m *Manager) alignStoreWithApp(ctx context.Context, block *types.Block) (bool, error) { - isRequired := false - // Validate incosistency in height wasn't caused by a crash and if so handle it. - proxyAppInfo, err := m.executor.GetAppInfo() - if err != nil { - return isRequired, errors.Wrap(err, "failed to get app info") - } - if uint64(proxyAppInfo.LastBlockHeight) != block.Header.Height { - return isRequired, nil - } - - isRequired = true - m.logger.Info("Skipping block application and only updating store height and state hash", "height", block.Header.Height) - // update the state with the hash, last store height and last validators. - m.lastState.AppHash = *(*[32]byte)(proxyAppInfo.LastBlockAppHash) - m.lastState.LastStoreHeight = block.Header.Height - m.lastState.LastValidators = m.lastState.Validators.Copy() - - resp, err := m.store.LoadBlockResponses(block.Header.Height) - if err != nil { - return isRequired, errors.Wrap(err, "failed to load block responses") - } - copy(m.lastState.LastResultsHash[:], tmtypes.NewResults(resp.DeliverTxs).Hash()) - - _, err = m.store.UpdateState(m.lastState, nil) - if err != nil { - return isRequired, errors.Wrap(err, "failed to update state") - } - m.store.SetHeight(block.Header.Height) - return isRequired, nil -} - -func (m *Manager) executeBlock(ctx context.Context, block *types.Block, commit *types.Commit) (*tmstate.ABCIResponses, error) { - // Currently we're assuming proposer is never nil as it's a pre-condition for - // dymint to start - proposer := m.settlementClient.GetProposer() - - if err := m.executor.Validate(m.lastState, block, commit, proposer); err != nil { - return &tmstate.ABCIResponses{}, err - } - - responses, err := m.executor.Execute(ctx, m.lastState, block) - if err != nil { - return &tmstate.ABCIResponses{}, err - } - - return responses, nil -} - -func (m *Manager) gossipBlock(ctx context.Context, block types.Block, commit types.Commit) error { - gossipedBlock := p2p.GossipedBlock{Block: block, Commit: commit} - gossipedBlockBytes, err := gossipedBlock.MarshalBinary() - if err != nil { - m.logger.Error("Failed to marshal block", "error", err) - return err - } - if err := m.p2pClient.GossipBlock(ctx, gossipedBlockBytes); err != nil { - m.logger.Error("Failed to gossip block", "error", err) - return err - } - return nil - -} - -func (m *Manager) processNextDABatch(ctx context.Context, daHeight uint64) error { - m.logger.Debug("trying to retrieve batch from DA", "daHeight", daHeight) - batchResp, err := m.fetchBatch(daHeight) - if err != nil { - m.logger.Error("failed to retrieve batch from DA", "daHeight", daHeight, "error", err) - return err - } - m.logger.Debug("retrieved batches", "n", len(batchResp.Batches), "daHeight", daHeight) - for _, batch := range batchResp.Batches { - for i, block := range batch.Blocks { - err := m.applyBlock(ctx, block, batch.Commits[i], blockMetaData{source: daBlock, daHeight: daHeight}) - if err != nil { - return err - } - } - } - return nil -} - -func (m *Manager) fetchBatch(daHeight uint64) (da.ResultRetrieveBatch, error) { - var err error - batchRes := m.retriever.RetrieveBatches(daHeight) - switch batchRes.Code { - case da.StatusError: - err = fmt.Errorf("failed to retrieve batch: %s", batchRes.Message) - case da.StatusTimeout: - err = fmt.Errorf("timeout during retrieve batch: %s", batchRes.Message) - } - return batchRes, err -} - -func (m *Manager) produceBlock(ctx context.Context, allowEmpty bool) error { - m.produceBlockMutex.Lock() - defer m.produceBlockMutex.Unlock() - var lastCommit *types.Commit - var lastHeaderHash [32]byte - var err error - height := m.store.Height() - newHeight := height + 1 - - // this is a special case, when first block is produced - there is no previous commit - if newHeight == uint64(m.genesis.InitialHeight) { - lastCommit = &types.Commit{Height: height, HeaderHash: [32]byte{}} - } else { - lastCommit, err = m.store.LoadCommit(height) - if err != nil { - return fmt.Errorf("error while loading last commit: %w", err) - } - lastBlock, err := m.store.LoadBlock(height) - if err != nil { - return fmt.Errorf("error while loading last block: %w", err) - } - lastHeaderHash = lastBlock.Header.Hash() - } - - var block *types.Block - // Check if there's an already stored block and commit at a newer height - // If there is use that instead of creating a new block - var commit *types.Commit - pendingBlock, err := m.store.LoadBlock(newHeight) - if err == nil { - m.logger.Info("Using pending block", "height", newHeight) - block = pendingBlock - commit, err = m.store.LoadCommit(newHeight) - if err != nil { - m.logger.Error("Loaded block but failed to load commit", "height", newHeight, "error", err) - return err - } - } else { - block = m.executor.CreateBlock(newHeight, lastCommit, lastHeaderHash, m.lastState) - if !allowEmpty && len(block.Data.Txs) == 0 { - return types.ErrSkippedEmptyBlock - } - - abciHeaderPb := abciconv.ToABCIHeaderPB(&block.Header) - abciHeaderBytes, err := abciHeaderPb.Marshal() - if err != nil { - return err - } - sign, err := m.proposerKey.Sign(abciHeaderBytes) - if err != nil { - return err - } - commit = &types.Commit{ - Height: block.Header.Height, - HeaderHash: block.Header.Hash(), - Signatures: []types.Signature{sign}, - } - - } - - // Gossip the block as soon as it is produced - if err := m.gossipBlock(ctx, *block, *commit); err != nil { - return err - } - - if err := m.applyBlock(ctx, block, commit, blockMetaData{source: producedBlock}); err != nil { - return err - } - - m.logger.Info("block created", "height", newHeight, "num_tx", len(block.Data.Txs)) - rollappHeightGauge.Set(float64(newHeight)) - return nil -} - -func (m *Manager) submitNextBatch(ctx context.Context) { - // Get the batch start and end height - startHeight := atomic.LoadUint64(&m.syncTarget) + 1 - endHeight := uint64(m.lastState.LastBlockHeight) - - isLastBlockEmpty, err := m.validateLastBlockInBatchIsEmpty(startHeight, endHeight) - if err != nil { - m.logger.Error("Failed to validate last block in batch is empty", "startHeight", startHeight, "endHeight", endHeight, "error", err) - return - } - if !isLastBlockEmpty { - m.logger.Info("Requesting for an empty block creation") - m.produceEmptyBlockCh <- true - } - - // Create the batch - nextBatch, err := m.createNextDABatch(startHeight, endHeight) - if err != nil { - m.logger.Error("Failed to create next batch", "startHeight", startHeight, "endHeight", endHeight, "error", err) - return - } - - actualEndHeight := nextBatch.EndHeight - - // Submit batch to the DA - m.logger.Info("Submitting next batch", "startHeight", startHeight, "endHeight", actualEndHeight, "size", nextBatch.ToProto().Size()) - resultSubmitToDA := m.dalc.SubmitBatch(nextBatch) - if resultSubmitToDA.Code != da.StatusSuccess { - panic("Failed to submit next batch to DA Layer") - } - - // Submit batch to SL - // TODO(omritoptix): Handle a case where the SL submission fails due to syncTarget out of sync with the latestHeight in the SL. - // In that case we'll want to update the syncTarget before returning. - m.settlementClient.SubmitBatch(nextBatch, m.dalc.GetClientType(), &resultSubmitToDA) -} - -// Verify the last block in the batch is an empty block and that no ibc messages has accidentially passed through. -// This block may not be empty if another block has passed it in line. If that's the case our empty block request will -// be sent to the next batch. -func (m *Manager) validateLastBlockInBatchIsEmpty(startHeight uint64, endHeight uint64) (bool, error) { - m.logger.Debug("Verifying last block in batch is an empty block", "startHeight", startHeight, "endHeight", endHeight, "height") - lastBlock, err := m.store.LoadBlock(endHeight) - if err != nil { - m.logger.Error("Failed to load block", "height", endHeight, "error", err) - return false, err - } - if len(lastBlock.Data.Txs) != 0 { - m.logger.Info("Last block in batch is not an empty block", "startHeight", startHeight, "endHeight", endHeight, "height") - return false, nil - } - return true, nil -} - -func (m *Manager) updateStateIndex(stateIndex uint64) error { - atomic.StoreUint64(&m.lastState.SLStateIndex, stateIndex) - _, err := m.store.UpdateState(m.lastState, nil) - if err != nil { - m.logger.Error("Failed to update state", "error", err) - return err - } - return nil -} - -func (m *Manager) createNextDABatch(startHeight uint64, endHeight uint64) (*types.Batch, error) { - var height uint64 - // Create the batch - batchSize := endHeight - startHeight + 1 - batch := &types.Batch{ - StartHeight: startHeight, - EndHeight: endHeight, - Blocks: make([]*types.Block, 0, batchSize), - Commits: make([]*types.Commit, 0, batchSize), - } - - // Populate the batch - for height = startHeight; height <= endHeight; height++ { - block, err := m.store.LoadBlock(height) - if err != nil { - m.logger.Error("Failed to load block", "height", height) - return nil, err - } - commit, err := m.store.LoadCommit(height) - if err != nil { - m.logger.Error("Failed to load commit", "height", height) - return nil, err - } - - batch.Blocks = append(batch.Blocks, block) - batch.Commits = append(batch.Commits, commit) - - //Check if the batch size is too big - totalSize := batch.ToProto().Size() - if totalSize > int(m.conf.BlockBatchMaxSizeBytes) { - // Nil out the last block and commit - batch.Blocks[len(batch.Blocks)-1] = nil - batch.Commits[len(batch.Commits)-1] = nil - - // Remove the last block and commit from the batch - batch.Blocks = batch.Blocks[:len(batch.Blocks)-1] - batch.Commits = batch.Commits[:len(batch.Commits)-1] - break - } - } - - batch.EndHeight = height - 1 - return batch, nil -} - // TODO(omritoptix): possible remove this method from the manager func updateInitChainState(s *types.State, res *abci.ResponseInitChain, validators []*tmtypes.Validator) { // If the app did not return an app hash, we keep the one set from the genesis doc in diff --git a/block/manager_test.go b/block/manager_test.go index 936b27b0a..83ff832ed 100644 --- a/block/manager_test.go +++ b/block/manager_test.go @@ -3,7 +3,6 @@ package block import ( "context" "crypto/rand" - "encoding/hex" "errors" "sync/atomic" "testing" @@ -13,8 +12,6 @@ import ( "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" - "github.com/dymensionxyz/dymint/log/test" - mempoolv1 "github.com/dymensionxyz/dymint/mempool/v1" "github.com/dymensionxyz/dymint/node/events" "github.com/dymensionxyz/dymint/p2p" "github.com/dymensionxyz/dymint/settlement" @@ -23,7 +20,6 @@ import ( "github.com/libp2p/go-libp2p/core/crypto" abci "github.com/tendermint/tendermint/abci/types" - tmcfg "github.com/tendermint/tendermint/config" "github.com/tendermint/tendermint/libs/log" "github.com/tendermint/tendermint/libs/pubsub" "github.com/tendermint/tendermint/proxy" @@ -31,16 +27,10 @@ import ( "github.com/dymensionxyz/dymint/config" "github.com/dymensionxyz/dymint/da" - mockda "github.com/dymensionxyz/dymint/da/mock" - nodemempool "github.com/dymensionxyz/dymint/node/mempool" slregistry "github.com/dymensionxyz/dymint/settlement/registry" "github.com/dymensionxyz/dymint/store" ) -const ( - defaultBatchSize = 5 - batchLimitBytes = 2000 -) const ( connectionRefusedErrorMessage = "connection refused" batchNotFoundErrorMessage = "batch not found" @@ -67,7 +57,7 @@ func TestInitialState(t *testing.T) { // Init p2p client privKey, _, _ := crypto.GenerateEd25519Key(rand.Reader) - p2pClient, err := p2p.NewClient(config.P2PConfig{}, privKey, "TestChain", test.NewLogger(t)) + p2pClient, err := p2p.NewClient(config.P2PConfig{}, privKey, "TestChain", logger) assert.NoError(err) assert.NotNil(p2pClient) @@ -470,121 +460,3 @@ func TestCreateNextDABatchWithBytesLimit(t *testing.T) { }) } } - -/* -------------------------------------------------------------------------- */ -/* utils */ -/* -------------------------------------------------------------------------- */ - -func getManager(conf config.BlockManagerConfig, settlementlc settlement.LayerI, dalc da.DataAvailabilityLayerClient, genesisHeight int64, storeInitialHeight int64, storeLastBlockHeight int64, proxyAppConns proxy.AppConns, mockStore store.Store) (*Manager, error) { - genesis := testutil.GenerateGenesis(genesisHeight) - // Change the LastBlockHeight to avoid calling InitChainSync within the manager - // And updating the state according to the genesis. - state := testutil.GenerateState(storeInitialHeight, storeLastBlockHeight) - var managerStore store.Store - if mockStore == nil { - managerStore = store.New(store.NewDefaultInMemoryKVStore()) - } else { - managerStore = mockStore - } - if _, err := managerStore.UpdateState(state, nil); err != nil { - return nil, err - } - - logger := log.TestingLogger() - pubsubServer := pubsub.NewServer() - pubsubServer.Start() - - // Init the settlement layer mock - if settlementlc == nil { - settlementlc = slregistry.GetClient(slregistry.Mock) - } - //TODO(omritoptix): Change the initialization. a bit dirty. - proposerKey, proposerPubKey, err := crypto.GenerateEd25519Key(rand.Reader) - if err != nil { - return nil, err - } - pubKeybytes, err := proposerPubKey.Raw() - if err != nil { - return nil, err - } - - err = initSettlementLayerMock(settlementlc, hex.EncodeToString(pubKeybytes), pubsubServer, logger) - if err != nil { - return nil, err - } - - if dalc == nil { - dalc = &mockda.DataAvailabilityLayerClient{} - } - initDALCMock(dalc, pubsubServer, logger) - - var proxyApp proxy.AppConns - if proxyAppConns == nil { - proxyApp = testutil.GetABCIProxyAppMock(logger.With("module", "proxy")) - if err := proxyApp.Start(); err != nil { - return nil, err - } - } else { - proxyApp = proxyAppConns - } - - mp := mempoolv1.NewTxMempool(logger, tmcfg.DefaultMempoolConfig(), proxyApp.Mempool(), 0) - mpIDs := nodemempool.NewMempoolIDs() - - // Init p2p client and validator - p2pKey, _, _ := crypto.GenerateEd25519Key(rand.Reader) - p2pClient, err := p2p.NewClient(config.P2PConfig{}, p2pKey, "TestChain", logger) - if err != nil { - return nil, err - } - p2pValidator := p2p.NewValidator(logger, pubsubServer) - p2pClient.SetTxValidator(p2pValidator.TxValidator(mp, mpIDs)) - p2pClient.SetBlockValidator(p2pValidator.BlockValidator()) - - if err = p2pClient.Start(context.Background()); err != nil { - return nil, err - } - - manager, err := NewManager(proposerKey, conf, genesis, managerStore, mp, proxyApp, dalc, settlementlc, nil, - pubsubServer, p2pClient, logger) - if err != nil { - return nil, err - } - return manager, nil -} - -// TODO(omritoptix): Possible move out to a generic testutil -func getMockDALC(logger log.Logger) da.DataAvailabilityLayerClient { - dalc := &mockda.DataAvailabilityLayerClient{} - initDALCMock(dalc, pubsub.NewServer(), logger) - return dalc -} - -// TODO(omritoptix): Possible move out to a generic testutil -func initDALCMock(dalc da.DataAvailabilityLayerClient, pubsubServer *pubsub.Server, logger log.Logger) { - _ = dalc.Init(nil, pubsubServer, store.NewDefaultInMemoryKVStore(), logger) - _ = dalc.Start() -} - -// TODO(omritoptix): Possible move out to a generic testutil -func initSettlementLayerMock(settlementlc settlement.LayerI, proposer string, pubsubServer *pubsub.Server, logger log.Logger) error { - err := settlementlc.Init(settlement.Config{ProposerPubKey: proposer}, pubsubServer, logger) - if err != nil { - return err - } - err = settlementlc.Start() - if err != nil { - return err - } - return nil -} - -func getManagerConfig() config.BlockManagerConfig { - return config.BlockManagerConfig{ - BlockTime: 100 * time.Millisecond, - BlockBatchSize: defaultBatchSize, - BlockBatchMaxSizeBytes: 1000, - BatchSubmitMaxTime: 30 * time.Minute, - NamespaceID: "0102030405060708", - } -} diff --git a/block/produce.go b/block/produce.go new file mode 100644 index 000000000..d07b0fde6 --- /dev/null +++ b/block/produce.go @@ -0,0 +1,183 @@ +package block + +import ( + "context" + "fmt" + "sync/atomic" + "time" + + "cosmossdk.io/errors" + abciconv "github.com/dymensionxyz/dymint/conv/abci" + "github.com/dymensionxyz/dymint/settlement" + "github.com/dymensionxyz/dymint/types" +) + +// waitForSync enforces the aggregator to be synced before it can produce blocks. +// It requires the retriveBlockLoop to be running. +func (m *Manager) waitForSync(ctx context.Context) error { + resultRetrieveBatch, err := m.getLatestBatchFromSL(ctx) + // Set the syncTarget according to the result + if err == settlement.ErrBatchNotFound { + // Since we requested the latest batch and got batch not found it means + // the SL still hasn't got any batches for this chain. + m.logger.Info("No batches for chain found in SL. Start writing first batch") + atomic.StoreUint64(&m.syncTarget, uint64(m.genesis.InitialHeight-1)) + return nil + } else if err != nil { + m.logger.Error("failed to retrieve batch from SL", "err", err) + return err + } else { + m.updateSyncParams(ctx, resultRetrieveBatch.EndHeight) + } + // Wait until isSynced is true and then call the PublishBlockLoop + m.isSyncedCond.L.Lock() + // Wait until we're synced and that we have got the latest batch (if we didn't, m.syncTarget == 0) + // before we start publishing blocks + for m.store.Height() < atomic.LoadUint64(&m.syncTarget) { + m.logger.Info("Waiting for sync", "current height", m.store.Height(), "syncTarget", atomic.LoadUint64(&m.syncTarget)) + m.isSyncedCond.Wait() + } + m.isSyncedCond.L.Unlock() + m.logger.Info("Synced, Starting to produce", "current height", m.store.Height(), "syncTarget", atomic.LoadUint64(&m.syncTarget)) + return nil +} + +// ProduceBlockLoop is calling publishBlock in a loop as long as wer'e synced. +func (m *Manager) ProduceBlockLoop(ctx context.Context) { + atomic.StoreInt64(&m.lastSubmissionTime, time.Now().Unix()) + + // We want to wait until we are synced. After that, since there is no leader + // election yet, and leader are elected manually, we will not be out of sync until + // we are manually being replaced. + err := m.waitForSync(ctx) + if err != nil { + panic(errors.Wrap(err, "failed to wait for sync")) + } + + ticker := time.NewTicker(m.conf.BlockTime) + defer ticker.Stop() + + var tickerEmptyBlocksMaxTime *time.Ticker + var tickerEmptyBlocksMaxTimeCh <-chan time.Time + // Setup ticker for empty blocks if enabled + if m.conf.EmptyBlocksMaxTime > 0 { + tickerEmptyBlocksMaxTime = time.NewTicker(m.conf.EmptyBlocksMaxTime) + tickerEmptyBlocksMaxTimeCh = tickerEmptyBlocksMaxTime.C + defer tickerEmptyBlocksMaxTime.Stop() + } + + //Allow the initial block to be empty + produceEmptyBlock := true + for { + select { + //Context canceled + case <-ctx.Done(): + return + // If we got a request for an empty block produce it and don't wait for the ticker + case <-m.produceEmptyBlockCh: + produceEmptyBlock = true + //Empty blocks timeout + case <-tickerEmptyBlocksMaxTimeCh: + m.logger.Debug(fmt.Sprintf("No transactions for %.2f seconds, producing empty block", m.conf.EmptyBlocksMaxTime.Seconds())) + produceEmptyBlock = true + //Produce block + case <-ticker.C: + err := m.produceBlock(ctx, produceEmptyBlock) + if err == types.ErrSkippedEmptyBlock { + m.logger.Debug("Skipped empty block") + continue + } + if err != nil { + m.logger.Error("error while producing block", "error", err) + continue + } + //If empty blocks enabled, after block produced, reset the timeout timer + if tickerEmptyBlocksMaxTime != nil { + produceEmptyBlock = false + tickerEmptyBlocksMaxTime.Reset(m.conf.EmptyBlocksMaxTime) + } + + //Node's health check channel + case shouldProduceBlocks := <-m.shouldProduceBlocksCh: + for !shouldProduceBlocks { + m.logger.Info("Stopped block production") + shouldProduceBlocks = <-m.shouldProduceBlocksCh + } + m.logger.Info("Resumed Block production") + } + } +} + +func (m *Manager) produceBlock(ctx context.Context, allowEmpty bool) error { + m.produceBlockMutex.Lock() + defer m.produceBlockMutex.Unlock() + var lastCommit *types.Commit + var lastHeaderHash [32]byte + var err error + height := m.store.Height() + newHeight := height + 1 + + // this is a special case, when first block is produced - there is no previous commit + if newHeight == uint64(m.genesis.InitialHeight) { + lastCommit = &types.Commit{Height: height, HeaderHash: [32]byte{}} + } else { + lastCommit, err = m.store.LoadCommit(height) + if err != nil { + return fmt.Errorf("error while loading last commit: %w", err) + } + lastBlock, err := m.store.LoadBlock(height) + if err != nil { + return fmt.Errorf("error while loading last block: %w", err) + } + lastHeaderHash = lastBlock.Header.Hash() + } + + var block *types.Block + // Check if there's an already stored block and commit at a newer height + // If there is use that instead of creating a new block + var commit *types.Commit + pendingBlock, err := m.store.LoadBlock(newHeight) + if err == nil { + m.logger.Info("Using pending block", "height", newHeight) + block = pendingBlock + commit, err = m.store.LoadCommit(newHeight) + if err != nil { + m.logger.Error("Loaded block but failed to load commit", "height", newHeight, "error", err) + return err + } + } else { + block = m.executor.CreateBlock(newHeight, lastCommit, lastHeaderHash, m.lastState) + if !allowEmpty && len(block.Data.Txs) == 0 { + return types.ErrSkippedEmptyBlock + } + + abciHeaderPb := abciconv.ToABCIHeaderPB(&block.Header) + abciHeaderBytes, err := abciHeaderPb.Marshal() + if err != nil { + return err + } + sign, err := m.proposerKey.Sign(abciHeaderBytes) + if err != nil { + return err + } + commit = &types.Commit{ + Height: block.Header.Height, + HeaderHash: block.Header.Hash(), + Signatures: []types.Signature{sign}, + } + + } + + // Gossip the block as soon as it is produced + if err := m.gossipBlock(ctx, *block, *commit); err != nil { + return err + } + + if err := m.applyBlock(ctx, block, commit, blockMetaData{source: producedBlock}); err != nil { + return err + } + + m.logger.Info("block created", "height", newHeight, "num_tx", len(block.Data.Txs)) + rollappHeightGauge.Set(float64(newHeight)) + return nil +} diff --git a/block/retriever.go b/block/retriever.go new file mode 100644 index 000000000..91f848241 --- /dev/null +++ b/block/retriever.go @@ -0,0 +1,101 @@ +package block + +import ( + "context" + "fmt" + "sync/atomic" + + "code.cloudfoundry.org/go-diodes" + "github.com/dymensionxyz/dymint/da" +) + +// RetriveLoop listens for new sync messages written to a ring buffer and in turn +// runs syncUntilTarget on the latest message in the ring buffer. +func (m *Manager) RetriveLoop(ctx context.Context) { + m.logger.Info("Started retrieve loop") + syncTargetpoller := diodes.NewPoller(m.syncTargetDiode) + for { + select { + case <-ctx.Done(): + return + default: + // Get only the latest sync target + syncTarget := syncTargetpoller.Next() + m.syncUntilTarget(ctx, *(*uint64)(syncTarget)) + // Check if after we sync we are synced or a new syncTarget was already set. + // If we are synced then signal all goroutines waiting on isSyncedCond. + if m.store.Height() >= atomic.LoadUint64(&m.syncTarget) { + m.logger.Info("Synced at height", "height", m.store.Height()) + m.isSyncedCond.L.Lock() + m.isSyncedCond.Signal() + m.isSyncedCond.L.Unlock() + } + } + } +} + +// syncUntilTarget syncs the block until the syncTarget is reached. +// It fetches the batches from the settlement, gets the DA height and gets +// the actual blocks from the DA. +func (m *Manager) syncUntilTarget(ctx context.Context, syncTarget uint64) { + currentHeight := m.store.Height() + for currentHeight < syncTarget { + m.logger.Info("Syncing until target", "current height", currentHeight, "syncTarget", syncTarget) + resultRetrieveBatch, err := m.settlementClient.RetrieveBatch(atomic.LoadUint64(&m.lastState.SLStateIndex) + 1) + if err != nil { + m.logger.Error("Failed to sync until target. error while retrieving batch", "error", err) + continue + } + err = m.processNextDABatch(ctx, resultRetrieveBatch.MetaData.DA.Height) + if err != nil { + m.logger.Error("Failed to sync until target. error while processing next DA batch", "error", err) + break + } + err = m.updateStateIndex(resultRetrieveBatch.StateIndex) + if err != nil { + return + } + currentHeight = m.store.Height() + } +} + +func (m *Manager) updateStateIndex(stateIndex uint64) error { + atomic.StoreUint64(&m.lastState.SLStateIndex, stateIndex) + _, err := m.store.UpdateState(m.lastState, nil) + if err != nil { + m.logger.Error("Failed to update state", "error", err) + return err + } + return nil +} + +func (m *Manager) processNextDABatch(ctx context.Context, daHeight uint64) error { + m.logger.Debug("trying to retrieve batch from DA", "daHeight", daHeight) + batchResp, err := m.fetchBatch(daHeight) + if err != nil { + m.logger.Error("failed to retrieve batch from DA", "daHeight", daHeight, "error", err) + return err + } + m.logger.Debug("retrieved batches", "n", len(batchResp.Batches), "daHeight", daHeight) + for _, batch := range batchResp.Batches { + for i, block := range batch.Blocks { + err := m.applyBlock(ctx, block, batch.Commits[i], blockMetaData{source: daBlock, daHeight: daHeight}) + if err != nil { + return err + } + } + } + return nil +} + +func (m *Manager) fetchBatch(daHeight uint64) (da.ResultRetrieveBatch, error) { + var err error + batchRes := m.retriever.RetrieveBatches(daHeight) + switch batchRes.Code { + case da.StatusError: + err = fmt.Errorf("failed to retrieve batch: %s", batchRes.Message) + case da.StatusTimeout: + err = fmt.Errorf("timeout during retrieve batch: %s", batchRes.Message) + } + return batchRes, err +} diff --git a/block/submit.go b/block/submit.go new file mode 100644 index 000000000..423ed19fe --- /dev/null +++ b/block/submit.go @@ -0,0 +1,146 @@ +package block + +import ( + "context" + "sync/atomic" + "time" + + "github.com/dymensionxyz/dymint/da" + "github.com/dymensionxyz/dymint/types" +) + +func (m *Manager) SubmitLoop(ctx context.Context) { + ticker := time.NewTicker(m.conf.BatchSubmitMaxTime) + defer ticker.Stop() + + for { + select { + //Context canceled + case <-ctx.Done(): + return + //TODO: add the case of batch size (should be signaled from the the block production) + // case <- requiredByNumOfBlocks + case <-ticker.C: + // SyncTarget is the height of the last block in the last batch as seen by this node. + syncTarget := atomic.LoadUint64(&m.syncTarget) + height := m.store.Height() + //no new blocks produced yet + if (height - syncTarget) == 0 { + continue + } + + // Submit batch if we've reached the batch size and there isn't another batch currently in submission process. + if m.batchInProcess.Load() == true { + m.logger.Debug("Batch submission already in process, skipping submission") + continue + } + + m.batchInProcess.Store(true) + // We try and produce an empty block to make sure releavnt ibc messages will pass through during the batch submission: https://github.com/dymensionxyz/research/issues/173. + err := m.produceBlock(ctx, true) + if err != nil { + m.logger.Error("error while producing empty block", "error", err) + } + m.submitNextBatch(ctx) + } + } +} + +func (m *Manager) submitNextBatch(ctx context.Context) { + // Get the batch start and end height + startHeight := atomic.LoadUint64(&m.syncTarget) + 1 + endHeight := uint64(m.lastState.LastBlockHeight) + + isLastBlockEmpty, err := m.validateLastBlockInBatchIsEmpty(startHeight, endHeight) + if err != nil { + m.logger.Error("Failed to validate last block in batch is empty", "startHeight", startHeight, "endHeight", endHeight, "error", err) + return + } + if !isLastBlockEmpty { + m.logger.Info("Requesting for an empty block creation") + m.produceEmptyBlockCh <- true + } + + // Create the batch + nextBatch, err := m.createNextDABatch(startHeight, endHeight) + if err != nil { + m.logger.Error("Failed to create next batch", "startHeight", startHeight, "endHeight", endHeight, "error", err) + return + } + + actualEndHeight := nextBatch.EndHeight + + // Submit batch to the DA + m.logger.Info("Submitting next batch", "startHeight", startHeight, "endHeight", actualEndHeight, "size", nextBatch.ToProto().Size()) + resultSubmitToDA := m.dalc.SubmitBatch(nextBatch) + if resultSubmitToDA.Code != da.StatusSuccess { + panic("Failed to submit next batch to DA Layer") + } + + // Submit batch to SL + // TODO(omritoptix): Handle a case where the SL submission fails due to syncTarget out of sync with the latestHeight in the SL. + // In that case we'll want to update the syncTarget before returning. + m.settlementClient.SubmitBatch(nextBatch, m.dalc.GetClientType(), &resultSubmitToDA) +} + +func (m *Manager) createNextDABatch(startHeight uint64, endHeight uint64) (*types.Batch, error) { + var height uint64 + // Create the batch + batchSize := endHeight - startHeight + 1 + batch := &types.Batch{ + StartHeight: startHeight, + EndHeight: endHeight, + Blocks: make([]*types.Block, 0, batchSize), + Commits: make([]*types.Commit, 0, batchSize), + } + + // Populate the batch + for height = startHeight; height <= endHeight; height++ { + block, err := m.store.LoadBlock(height) + if err != nil { + m.logger.Error("Failed to load block", "height", height) + return nil, err + } + commit, err := m.store.LoadCommit(height) + if err != nil { + m.logger.Error("Failed to load commit", "height", height) + return nil, err + } + + batch.Blocks = append(batch.Blocks, block) + batch.Commits = append(batch.Commits, commit) + + //Check if the batch size is too big + totalSize := batch.ToProto().Size() + if totalSize > int(m.conf.BlockBatchMaxSizeBytes) { + // Nil out the last block and commit + batch.Blocks[len(batch.Blocks)-1] = nil + batch.Commits[len(batch.Commits)-1] = nil + + // Remove the last block and commit from the batch + batch.Blocks = batch.Blocks[:len(batch.Blocks)-1] + batch.Commits = batch.Commits[:len(batch.Commits)-1] + break + } + } + + batch.EndHeight = height - 1 + return batch, nil +} + +// Verify the last block in the batch is an empty block and that no ibc messages has accidentially passed through. +// This block may not be empty if another block has passed it in line. If that's the case our empty block request will +// be sent to the next batch. +func (m *Manager) validateLastBlockInBatchIsEmpty(startHeight uint64, endHeight uint64) (bool, error) { + m.logger.Debug("Verifying last block in batch is an empty block", "startHeight", startHeight, "endHeight", endHeight, "height") + lastBlock, err := m.store.LoadBlock(endHeight) + if err != nil { + m.logger.Error("Failed to load block", "height", endHeight, "error", err) + return false, err + } + if len(lastBlock.Data.Txs) != 0 { + m.logger.Info("Last block in batch is not an empty block", "startHeight", startHeight, "endHeight", endHeight, "height") + return false, nil + } + return true, nil +} diff --git a/block/synctarget.go b/block/synctarget.go new file mode 100644 index 000000000..dfccf3fd5 --- /dev/null +++ b/block/synctarget.go @@ -0,0 +1,56 @@ +package block + +import ( + "context" + "sync/atomic" + "time" + + "code.cloudfoundry.org/go-diodes" + "github.com/dymensionxyz/dymint/settlement" +) + +// SyncTargetLoop is responsible for getting real time updates about batches submission. +// for non aggregator: updating the sync target which will be used by retrieveLoop to sync until this target. +// for aggregator: get notification that batch has been accepted so can send next batch. +func (m *Manager) SyncTargetLoop(ctx context.Context) { + m.logger.Info("Started sync target loop") + subscription, err := m.pubsub.Subscribe(ctx, "syncTargetLoop", settlement.EventQueryNewBatchAccepted) + if err != nil { + m.logger.Error("failed to subscribe to state update events") + panic(err) + } + // First time we start we want to get the latest batch from the SL + resultRetrieveBatch, err := m.getLatestBatchFromSL(ctx) + if err != nil { + m.logger.Error("failed to retrieve batch from SL", "err", err) + } else { + m.updateSyncParams(ctx, resultRetrieveBatch.EndHeight) + } + for { + select { + case <-ctx.Done(): + return + case event := <-subscription.Out(): + eventData := event.Data().(*settlement.EventDataNewBatchAccepted) + m.updateSyncParams(ctx, eventData.EndHeight) + // In case we are the aggregator and we've got an update, then we can stop blocking from + // the next batches to be published. For non-aggregators this is not needed. + // We only want to send the next once the previous has been published successfully. + // TODO(omritoptix): Once we have leader election, we can add a condition. + // Update batch accepted is only relevant for the aggregator + // TODO(omritoptix): Check if we are the aggregator + m.batchInProcess.Store(false) + case <-subscription.Cancelled(): + m.logger.Info("Subscription canceled") + } + } +} + +// updateSyncParams updates the sync target and state index if necessary +func (m *Manager) updateSyncParams(ctx context.Context, endHeight uint64) { + rollappHubHeightGauge.Set(float64(endHeight)) + m.logger.Info("Received new syncTarget", "syncTarget", endHeight) + atomic.StoreUint64(&m.syncTarget, endHeight) + atomic.StoreInt64(&m.lastSubmissionTime, time.Now().UnixNano()) + m.syncTargetDiode.Set(diodes.GenericDataType(&endHeight)) +} diff --git a/block/testutil.go b/block/testutil.go new file mode 100644 index 000000000..992ab75c8 --- /dev/null +++ b/block/testutil.go @@ -0,0 +1,149 @@ +package block + +import ( + "context" + "crypto/rand" + "encoding/hex" + "time" + + "github.com/dymensionxyz/dymint/p2p" + "github.com/dymensionxyz/dymint/settlement" + "github.com/dymensionxyz/dymint/testutil" + "github.com/libp2p/go-libp2p/core/crypto" + + "github.com/tendermint/tendermint/libs/log" + "github.com/tendermint/tendermint/libs/pubsub" + "github.com/tendermint/tendermint/proxy" + + "github.com/dymensionxyz/dymint/config" + "github.com/dymensionxyz/dymint/da" + mockda "github.com/dymensionxyz/dymint/da/mock" + mempoolv1 "github.com/dymensionxyz/dymint/mempool/v1" + nodemempool "github.com/dymensionxyz/dymint/node/mempool" + slregistry "github.com/dymensionxyz/dymint/settlement/registry" + "github.com/dymensionxyz/dymint/store" + tmcfg "github.com/tendermint/tendermint/config" +) + +const ( + defaultBatchSize = 5 + batchLimitBytes = 2000 +) + +/* -------------------------------------------------------------------------- */ +/* utils */ +/* -------------------------------------------------------------------------- */ + +func getManager(conf config.BlockManagerConfig, settlementlc settlement.LayerI, dalc da.DataAvailabilityLayerClient, genesisHeight int64, storeInitialHeight int64, storeLastBlockHeight int64, proxyAppConns proxy.AppConns, mockStore store.Store) (*Manager, error) { + genesis := testutil.GenerateGenesis(genesisHeight) + // Change the LastBlockHeight to avoid calling InitChainSync within the manager + // And updating the state according to the genesis. + state := testutil.GenerateState(storeInitialHeight, storeLastBlockHeight) + var managerStore store.Store + if mockStore == nil { + managerStore = store.New(store.NewDefaultInMemoryKVStore()) + } else { + managerStore = mockStore + } + if _, err := managerStore.UpdateState(state, nil); err != nil { + return nil, err + } + + logger := log.TestingLogger() + pubsubServer := pubsub.NewServer() + pubsubServer.Start() + + // Init the settlement layer mock + if settlementlc == nil { + settlementlc = slregistry.GetClient(slregistry.Mock) + } + //TODO(omritoptix): Change the initialization. a bit dirty. + proposerKey, proposerPubKey, err := crypto.GenerateEd25519Key(rand.Reader) + if err != nil { + return nil, err + } + pubKeybytes, err := proposerPubKey.Raw() + if err != nil { + return nil, err + } + + err = initSettlementLayerMock(settlementlc, hex.EncodeToString(pubKeybytes), pubsubServer, logger) + if err != nil { + return nil, err + } + + if dalc == nil { + dalc = &mockda.DataAvailabilityLayerClient{} + } + initDALCMock(dalc, pubsubServer, logger) + + var proxyApp proxy.AppConns + if proxyAppConns == nil { + proxyApp = testutil.GetABCIProxyAppMock(logger.With("module", "proxy")) + if err := proxyApp.Start(); err != nil { + return nil, err + } + } else { + proxyApp = proxyAppConns + } + + mp := mempoolv1.NewTxMempool(logger, tmcfg.DefaultMempoolConfig(), proxyApp.Mempool(), 0) + mpIDs := nodemempool.NewMempoolIDs() + + // Init p2p client and validator + p2pKey, _, _ := crypto.GenerateEd25519Key(rand.Reader) + p2pClient, err := p2p.NewClient(config.P2PConfig{}, p2pKey, "TestChain", logger) + if err != nil { + return nil, err + } + p2pValidator := p2p.NewValidator(logger, pubsubServer) + p2pClient.SetTxValidator(p2pValidator.TxValidator(mp, mpIDs)) + p2pClient.SetBlockValidator(p2pValidator.BlockValidator()) + + if err = p2pClient.Start(context.Background()); err != nil { + return nil, err + } + + manager, err := NewManager(proposerKey, conf, genesis, managerStore, mp, proxyApp, dalc, settlementlc, nil, + pubsubServer, p2pClient, logger) + if err != nil { + return nil, err + } + return manager, nil +} + +// TODO(omritoptix): Possible move out to a generic testutil +func getMockDALC(logger log.Logger) da.DataAvailabilityLayerClient { + dalc := &mockda.DataAvailabilityLayerClient{} + initDALCMock(dalc, pubsub.NewServer(), logger) + return dalc +} + +// TODO(omritoptix): Possible move out to a generic testutil +func initDALCMock(dalc da.DataAvailabilityLayerClient, pubsubServer *pubsub.Server, logger log.Logger) { + _ = dalc.Init(nil, pubsubServer, store.NewDefaultInMemoryKVStore(), logger) + _ = dalc.Start() +} + +// TODO(omritoptix): Possible move out to a generic testutil +func initSettlementLayerMock(settlementlc settlement.LayerI, proposer string, pubsubServer *pubsub.Server, logger log.Logger) error { + err := settlementlc.Init(settlement.Config{ProposerPubKey: proposer}, pubsubServer, logger) + if err != nil { + return err + } + err = settlementlc.Start() + if err != nil { + return err + } + return nil +} + +func getManagerConfig() config.BlockManagerConfig { + return config.BlockManagerConfig{ + BlockTime: 100 * time.Millisecond, + BlockBatchSize: defaultBatchSize, + BlockBatchMaxSizeBytes: 1000, + BatchSubmitMaxTime: 30 * time.Minute, + NamespaceID: "0102030405060708", + } +} From 5b5dcdb35fe8e1c19f9e5476d5b8e953951f84c1 Mon Sep 17 00:00:00 2001 From: Itay Date: Thu, 21 Sep 2023 11:55:08 +0300 Subject: [PATCH 3/7] fix: Display actual version in RPC status (#488) --- Makefile | 5 +++-- config/defaults.go | 2 -- rpc/client/client.go | 8 ++++---- version/version.go | 3 +++ 4 files changed, 10 insertions(+), 8 deletions(-) create mode 100644 version/version.go diff --git a/Makefile b/Makefile index 58fdb824a..724a1d25e 100644 --- a/Makefile +++ b/Makefile @@ -8,9 +8,10 @@ COMMIT_HASH := $(shell git rev-parse --short HEAD) LD_FLAGS = -X github.com/dymensionxyz/dymint/version.DymintGitCommitHash=$(COMMIT_HASH) BUILD_FLAGS = -mod=readonly -ldflags "$(LD_FLAGS)" CGO_ENABLED ?= 0 +VERSION ?= $(shell git describe --tags --always) + +LD_FLAGS = -X github.com/dymensionxyz/dymint/version.BuildVersion=$(VERSION) -# allow users to pass additional flags via the conventional LDFLAGS variable -LD_FLAGS += $(LDFLAGS) # Process Docker environment varible TARGETPLATFORM # in order to build binary with correspondent ARCH diff --git a/config/defaults.go b/config/defaults.go index 36e92c337..7eeb7e587 100644 --- a/config/defaults.go +++ b/config/defaults.go @@ -10,8 +10,6 @@ import ( const ( // DefaultListenAddress is a default listen address for P2P client. DefaultListenAddress = "/ip4/0.0.0.0/tcp/7676" - // Version is a default dymint version for P2P client. - Version = "0.2.2" DefaultHomeDir = "sequencer_keys" DefaultChainID = "dymint-testnet" diff --git a/rpc/client/client.go b/rpc/client/client.go index 28dae2c06..d3d2fe93a 100644 --- a/rpc/client/client.go +++ b/rpc/client/client.go @@ -3,6 +3,7 @@ package client import ( "context" "errors" + "github.com/dymensionxyz/dymint/version" "fmt" "sort" @@ -10,7 +11,6 @@ import ( sdkerrors "github.com/cosmos/cosmos-sdk/types/errors" - rconfig "github.com/dymensionxyz/dymint/config" abciconv "github.com/dymensionxyz/dymint/conv/abci" "github.com/dymensionxyz/dymint/mempool" "github.com/dymensionxyz/dymint/node" @@ -26,7 +26,7 @@ import ( rpcclient "github.com/tendermint/tendermint/rpc/client" ctypes "github.com/tendermint/tendermint/rpc/core/types" "github.com/tendermint/tendermint/types" - "github.com/tendermint/tendermint/version" + tm_version "github.com/tendermint/tendermint/version" ) const ( @@ -718,7 +718,7 @@ func (c *Client) Status(ctx context.Context) (*ctypes.ResultStatus, error) { return nil, fmt.Errorf("failed to load the last saved state: %w", err) } defaultProtocolVersion := p2p.NewProtocolVersion( - version.P2PProtocol, + tm_version.P2PProtocol, state.Version.Consensus.Block, state.Version.Consensus.App, ) @@ -732,7 +732,7 @@ func (c *Client) Status(ctx context.Context) (*ctypes.ResultStatus, error) { DefaultNodeID: id, ListenAddr: addr, Network: network, - Version: rconfig.Version, + Version: version.BuildVersion, Channels: []byte{0x1}, Moniker: config.DefaultBaseConfig().Moniker, Other: p2p.DefaultNodeInfoOther{ diff --git a/version/version.go b/version/version.go new file mode 100644 index 000000000..2cdc4204a --- /dev/null +++ b/version/version.go @@ -0,0 +1,3 @@ +package version + +var BuildVersion = "" From 7408a950821cd609f942d6920a66791a31ffc7cb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 28 Sep 2023 10:49:09 +0300 Subject: [PATCH 4/7] build(deps): bump actions/checkout from 3 to 4 (#478) Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/lint.yml | 4 ++-- .github/workflows/test.yml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 3b824e4f7..2b96387f7 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -15,7 +15,7 @@ jobs: GOPRIVATE: "github.com/dymensionxyz/*" GH_ACCESS_TOKEN: "${{ secrets.GH_ACCESS_TOKEN }}" steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - uses: actions/setup-go@v4 with: go-version: '1.19' @@ -46,7 +46,7 @@ jobs: markdownlint: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: markdownlint-cli uses: nosborn/github-action-markdown-cli@v3.3.0 with: diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index e2d0b25b5..62ab78230 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -14,7 +14,7 @@ jobs: GOPRIVATE: "github.com/dymensionxyz/*" GH_ACCESS_TOKEN: "${{ secrets.GH_ACCESS_TOKEN }}" steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Set up Go uses: actions/setup-go@v4 From 17e862236c346365b44709860b0dadd6aa0de22b Mon Sep 17 00:00:00 2001 From: Michael Tsitrin <114929630+mtsitrin@users.noreply.github.com> Date: Thu, 28 Sep 2023 21:40:48 +0300 Subject: [PATCH 5/7] chore: removed logging of events due to log bloat (#490) --- block/produce.go | 2 +- block/testutil.go | 6 ++++-- rpc/client/client.go | 3 ++- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/block/produce.go b/block/produce.go index d07b0fde6..dc567f2b0 100644 --- a/block/produce.go +++ b/block/produce.go @@ -84,7 +84,7 @@ func (m *Manager) ProduceBlockLoop(ctx context.Context) { case <-ticker.C: err := m.produceBlock(ctx, produceEmptyBlock) if err == types.ErrSkippedEmptyBlock { - m.logger.Debug("Skipped empty block") + // m.logger.Debug("Skipped empty block") continue } if err != nil { diff --git a/block/testutil.go b/block/testutil.go index 992ab75c8..b493e7dd9 100644 --- a/block/testutil.go +++ b/block/testutil.go @@ -51,8 +51,10 @@ func getManager(conf config.BlockManagerConfig, settlementlc settlement.LayerI, logger := log.TestingLogger() pubsubServer := pubsub.NewServer() - pubsubServer.Start() - + err := pubsubServer.Start() + if err != nil { + return nil, err + } // Init the settlement layer mock if settlementlc == nil { settlementlc = slregistry.GetClient(slregistry.Mock) diff --git a/rpc/client/client.go b/rpc/client/client.go index d3d2fe93a..ac8da2a7b 100644 --- a/rpc/client/client.go +++ b/rpc/client/client.go @@ -3,6 +3,7 @@ package client import ( "context" "errors" + "github.com/dymensionxyz/dymint/version" "fmt" @@ -88,7 +89,7 @@ func (c *Client) ABCIQueryWithOptions(ctx context.Context, path string, data tmb if err != nil { return nil, err } - c.Logger.Debug("ABCIQuery", "path", path, "data", data, "result", resQuery) + c.Logger.Debug("ABCIQuery", "path", path, "height", resQuery.Height) return &ctypes.ResultABCIQuery{Response: *resQuery}, nil } From 9e596df7c9c82af21d0e0246c2d1e6d7fd8fb102 Mon Sep 17 00:00:00 2001 From: Michael Tsitrin <114929630+mtsitrin@users.noreply.github.com> Date: Sun, 1 Oct 2023 10:29:23 +0300 Subject: [PATCH 6/7] chore: added missing return statement when subscription cancled (#491) --- block/synctarget.go | 3 ++- settlement/base.go | 2 +- utils/events.go | 3 ++- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/block/synctarget.go b/block/synctarget.go index dfccf3fd5..a7f81b457 100644 --- a/block/synctarget.go +++ b/block/synctarget.go @@ -41,7 +41,8 @@ func (m *Manager) SyncTargetLoop(ctx context.Context) { // TODO(omritoptix): Check if we are the aggregator m.batchInProcess.Store(false) case <-subscription.Cancelled(): - m.logger.Info("Subscription canceled") + m.logger.Info("syncTargetLoop subscription canceled") + return } } } diff --git a/settlement/base.go b/settlement/base.go index b35af7a05..c6dc4b5bc 100644 --- a/settlement/base.go +++ b/settlement/base.go @@ -179,7 +179,7 @@ func (b *BaseLayerClient) stateUpdatesHandler(ready chan bool) { utils.SubmitEventOrPanic(b.ctx, b.pubsub, newBatchEventData, map[string][]string{EventTypeKey: {EventNewBatchAccepted}}) case <-subscription.Cancelled(): - b.logger.Info("subscription canceled") + b.logger.Info("stateUpdatesHandler subscription canceled") return case <-b.ctx.Done(): b.logger.Info("Context done. Exiting state update handler") diff --git a/utils/events.go b/utils/events.go index 2a1953091..89a053173 100644 --- a/utils/events.go +++ b/utils/events.go @@ -22,7 +22,8 @@ func SubscribeAndHandleEvents(ctx context.Context, pubsubServer *pubsub.Server, case event := <-subscription.Out(): callback(event) case <-subscription.Cancelled(): - logger.Info("Subscription canceled") + logger.Info(clientID + " subscription canceled") + return } } } From b02334757183a21dddf41d97cc4547f30b073721 Mon Sep 17 00:00:00 2001 From: Itay Date: Mon, 2 Oct 2023 10:38:56 +0300 Subject: [PATCH 7/7] chore: Update cosmosclient (#495) Co-authored-by: Michael Tsitrin --- go.mod | 29 ++++++++++------ go.sum | 105 +++++++++++++++++++++++++++++++++++++++++---------------- 2 files changed, 94 insertions(+), 40 deletions(-) diff --git a/go.mod b/go.mod index 9e86f40bb..c0df06742 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,7 @@ require ( github.com/celestiaorg/go-cnc v0.4.2 github.com/centrifuge/go-substrate-rpc-client/v4 v4.0.12 github.com/dgraph-io/badger/v3 v3.2103.3 - github.com/dymensionxyz/cosmosclient v0.4.0-beta + github.com/dymensionxyz/cosmosclient v0.4.1-beta github.com/dymensionxyz/dymension v0.2.0-beta.0.20230607115558-745644a96ea6 github.com/go-kit/kit v0.12.0 github.com/gofrs/uuid v4.3.0+incompatible @@ -27,7 +27,7 @@ require ( github.com/prometheus/client_golang v1.14.0 github.com/rs/cors v1.8.3 github.com/spf13/cobra v1.6.1 - github.com/spf13/viper v1.14.0 + github.com/spf13/viper v1.15.0 github.com/stretchr/testify v1.8.4 github.com/tendermint/tendermint v0.34.28 go.uber.org/multierr v1.8.0 @@ -41,12 +41,15 @@ require ( cosmossdk.io/math v1.0.0-rc.0 // indirect github.com/99designs/go-keychain v0.0.0-20191008050251-8e49817e8af4 // indirect github.com/Microsoft/go-winio v0.6.1 // indirect - github.com/StackExchange/wmi v1.2.1 // indirect github.com/Workiva/go-datastructures v1.0.53 // indirect github.com/blang/semver v3.5.1+incompatible // indirect + github.com/btcsuite/btcd v0.22.2 // indirect github.com/btcsuite/btcd/btcec/v2 v2.3.2 // indirect + github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 // indirect + github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce // indirect github.com/cometbft/cometbft-db v0.7.0 // indirect - github.com/cosmos/cosmos-proto v1.0.0-beta.2 // indirect + github.com/cosmos/cosmos-proto v1.0.0-beta.3 // indirect + github.com/cosmos/gogoproto v1.4.8 // indirect github.com/creachadair/taskgroup v0.3.2 // indirect github.com/deckarep/golang-set v1.8.0 // indirect github.com/decred/base58 v1.0.4 // indirect @@ -54,11 +57,12 @@ require ( github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0 // indirect github.com/emirpasic/gods v1.18.1 // indirect github.com/ethereum/go-ethereum v1.12.0 // indirect + github.com/evmos/evmos/v12 v12.1.6 // indirect github.com/ghodss/yaml v1.0.0 // indirect - github.com/go-ole/go-ole v1.2.6 // indirect github.com/go-playground/validator/v10 v10.4.1 // indirect github.com/go-stack/stack v1.8.1 // indirect github.com/golang/mock v1.6.0 // indirect + github.com/google/go-cmp v0.5.9 // indirect github.com/google/pprof v0.0.0-20221203041831-ce31453925ec // indirect github.com/hashicorp/go-uuid v1.0.1 // indirect github.com/hashicorp/golang-lru/v2 v2.0.1 // indirect @@ -67,7 +71,7 @@ require ( github.com/lib/pq v1.10.7 // indirect github.com/libp2p/go-yamux/v4 v4.0.0 // indirect github.com/minio/highwayhash v1.0.2 // indirect - github.com/onsi/ginkgo/v2 v2.5.1 // indirect + github.com/onsi/ginkgo/v2 v2.9.0 // indirect github.com/pierrec/xxHash v0.1.5 // indirect github.com/quic-go/qpack v0.4.0 // indirect github.com/quic-go/qtls-go1-19 v0.2.1 // indirect @@ -79,7 +83,11 @@ require ( github.com/sirupsen/logrus v1.9.3 // indirect github.com/tecbot/gorocksdb v0.0.0-20191217155057-f0fad39f321c // indirect github.com/tidwall/btree v1.5.0 // indirect - github.com/tklauser/go-sysconf v0.3.10 // indirect + github.com/tidwall/gjson v1.14.4 // indirect + github.com/tidwall/match v1.1.1 // indirect + github.com/tidwall/pretty v1.2.0 // indirect + github.com/tidwall/sjson v1.2.5 // indirect + github.com/tyler-smith/go-bip39 v1.1.0 // indirect github.com/vedhavyas/go-subkey v1.0.3 // indirect github.com/zondax/ledger-go v0.14.1 // indirect go.uber.org/dig v1.15.0 // indirect @@ -172,7 +180,7 @@ require ( github.com/libp2p/go-nat v0.1.0 // indirect github.com/libp2p/go-netroute v0.2.1 // indirect github.com/libp2p/go-reuseport v0.2.0 // indirect - github.com/magiconair/properties v1.8.6 // indirect + github.com/magiconair/properties v1.8.7 // indirect github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd // indirect github.com/mattn/go-isatty v0.0.18 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect @@ -196,7 +204,6 @@ require ( github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417 // indirect github.com/opentracing/opentracing-go v1.2.0 // indirect github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 // indirect - github.com/pelletier/go-toml v1.9.5 // indirect github.com/pelletier/go-toml/v2 v2.0.7 // indirect github.com/petermattis/goid v0.0.0-20230317030725-371a4b8eda08 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect @@ -207,12 +214,12 @@ require ( github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect github.com/sasha-s/go-deadlock v0.3.1 // indirect github.com/spaolacci/murmur3 v1.1.0 // indirect - github.com/spf13/afero v1.9.2 // indirect + github.com/spf13/afero v1.9.3 // indirect github.com/spf13/cast v1.5.0 // indirect github.com/spf13/jwalterweatherman v1.1.0 // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/stretchr/objx v0.5.0 // indirect - github.com/subosito/gotenv v1.4.1 // indirect + github.com/subosito/gotenv v1.4.2 // indirect github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d // indirect github.com/tendermint/go-amino v0.16.0 // indirect github.com/tendermint/tm-db v0.6.7 // indirect diff --git a/go.sum b/go.sum index ee242f69e..8657a471a 100644 --- a/go.sum +++ b/go.sum @@ -66,17 +66,19 @@ github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym github.com/ChainSafe/go-schnorrkel v1.0.0 h1:3aDA67lAykLaG1y3AOjs88dMxC88PgUuHRrLeDnvGIM= github.com/ChainSafe/go-schnorrkel v1.0.0/go.mod h1:dpzHYVxLZcp8pjlV+O+UR8K0Hp/z7vcchBSbMBEhCw4= github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= +github.com/DataDog/zstd v1.5.2 h1:vUG4lAyuPCXO0TLbXvPv7EB7cNK1QV/luu55UHLrrn8= github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 h1:TngWCqHvy9oXAN6lEVMRuU21PR1EtLVZJmdB18Gu3Rw= github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/StackExchange/wmi v1.2.1 h1:VIkavFPXSjcnS+O8yTq7NI32k0R5Aj+v39y29VYDOSA= -github.com/StackExchange/wmi v1.2.1/go.mod h1:rcmrprowKIVzvc+NUiLncP2uuArMWLCbu9SBzvHz7e8= +github.com/VictoriaMetrics/fastcache v1.6.0 h1:C/3Oi3EiBCqufydp1neRZkqcwmEiuRT9c3fqvvgKm5o= github.com/VividCortex/gohistogram v1.0.0 h1:6+hBz+qvs0JOrrNhhmR7lFxo5sINxBCGXrdtl/UvroE= github.com/Workiva/go-datastructures v1.0.53 h1:J6Y/52yX10Xc5JjXmGtWoSSxs3mZnGSaq37xZZh7Yig= github.com/Workiva/go-datastructures v1.0.53/go.mod h1:1yZL+zfsztete+ePzZz/Zb1/t5BnDuE2Ya2MMGhzP6A= github.com/adlio/schema v1.3.3 h1:oBJn8I02PyTB466pZO1UZEn1TV5XLlifBSyMrmHl/1I= +github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= @@ -90,7 +92,7 @@ github.com/availproject/go-substrate-rpc-client/v4 v4.0.12-avail-1.4.0-rc1-5e286 github.com/availproject/go-substrate-rpc-client/v4 v4.0.12-avail-1.4.0-rc1-5e286e3/go.mod h1:5g1oM4Zu3BOaLpsKQ+O8PAv2kNuq+kPcA1VzFbsSqxE= github.com/avast/retry-go/v4 v4.5.0 h1:QoRAZZ90cj5oni2Lsgl2GW8mNTnUCnmpx/iKpwVisHg= github.com/avast/retry-go/v4 v4.5.0/go.mod h1:7hLEXp0oku2Nir2xBAsg0PTphp9z71bN5Aq1fboC3+I= -github.com/aws/aws-sdk-go v1.40.45 h1:QN1nsY27ssD/JmW4s83qmSb+uL6DG4GmCDzjmJB4xUI= +github.com/aws/aws-sdk-go v1.44.122 h1:p6mw01WBaNpbdP2xrisz5tIkcNwzj/HysobNoaAHjgo= github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A= github.com/benbjohnson/clock v1.3.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= @@ -104,12 +106,23 @@ github.com/bgentry/speakeasy v0.1.1-0.20220910012023-760eaf8b6816/go.mod h1:+zsy github.com/blang/semver v3.5.1+incompatible h1:cQNTCjp13qL8KC3Nbxr/y2Bqb63oX6wdnnjpJbkM4JQ= github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBTaaSFSlLx/70C2HPIMNZpVV8+vt/A+FMnYP11g= -github.com/btcsuite/btcd v0.22.1 h1:CnwP9LM/M9xuRrGSCGeMVs9iv09uMqwsVX7EeIpgV2c= +github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= +github.com/btcsuite/btcd v0.22.2 h1:vBZ+lGGd1XubpOWO67ITJpAEsICWhA0YzqkcpkgNBfo= +github.com/btcsuite/btcd v0.22.2/go.mod h1:wqgTSL29+50LRkmOVknEdmt8ZojIzhuWvgu/iptuN7Y= github.com/btcsuite/btcd/btcec/v2 v2.3.2 h1:5n0X6hX0Zk+6omWcihdYvdAlGf2DfasC0GMf7DClJ3U= github.com/btcsuite/btcd/btcec/v2 v2.3.2/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04= github.com/btcsuite/btcd/btcutil v1.1.2 h1:XLMbX8JQEiwMcYft2EGi8zPUkoa0abKIU6/BJSRsjzQ= github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 h1:q0rUy8C/TYNBQS1+CGKw68tLOFYSNEs0TFnxxnS9+4U= +github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1/go.mod h1:7SFka0XMvUgj3hfZtydOrQY2mwhPclbT2snogU7SQQc= +github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= +github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce h1:YtWJF7RHm2pYCvA5t0RPmAaLUhREsKuKd+SLhxFbFeQ= +github.com/btcsuite/btcutil v1.0.3-0.20201208143702-a53e38424cce/go.mod h1:0DVlHczLPewLcPGEIeUEzfOJhqGPQ0mJJRDBtD307+o= +github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= +github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVaaLLH7j4eDXPRvw78tMflu7Ie2bzYOH4Y8rRKBY= +github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= +github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= +github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= github.com/buger/jsonparser v0.0.0-20181115193947-bf1c66bbce23/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s= github.com/celestiaorg/go-cnc v0.4.2 h1:7ixf3tevMB7Lvz2mbyRG0ZOK+8qoPm7wNhdgpi8VreU= github.com/celestiaorg/go-cnc v0.4.2/go.mod h1:zYzvHudSd1iNPuHBMyvZ1YvWou5aT9JXgtch9Tkaf70= @@ -134,6 +147,10 @@ github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGX github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cockroachdb/apd/v2 v2.0.2 h1:weh8u7Cneje73dDh+2tEVLUvyBc89iwepWCD8b8034E= +github.com/cockroachdb/errors v1.9.1 h1:yFVvsI0VxmRShfawbt/laCIDy/mtTqqnvoNgiy5bEV8= +github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b h1:r6VH0faHjZeQy818SGhaone5OnYfxFR/+AzdY3sf5aE= +github.com/cockroachdb/pebble v0.0.0-20230209160836-829675f94811 h1:ytcWPaNPhNoGMWEhDvS3zToKcDpRsLuRolQJBVGdozk= +github.com/cockroachdb/redact v1.1.3 h1:AKZds10rFSIj7qADf0g46UixK8NNLwWTNdCIGS5wfSQ= github.com/coinbase/rosetta-sdk-go v0.7.9 h1:lqllBjMnazTjIqYrOGv8h8jxjg9+hJazIGZr9ZvoCcA= github.com/cometbft/cometbft v0.34.28 h1:gwryf55P1SWMUP4nOXpRVI2D0yPoYEzN+IBqmRBOsDc= github.com/cometbft/cometbft v0.34.28/go.mod h1:L9shMfbkZ8B+7JlwANEr+NZbBcn+hBpwdbeYvA5rLCw= @@ -154,17 +171,20 @@ github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8 github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/cosmos/btcutil v1.0.5 h1:t+ZFcX77LpKtDBhjucvnOH8C2l2ioGsBNEQ3jef8xFk= github.com/cosmos/btcutil v1.0.5/go.mod h1:IyB7iuqZMJlthe2tkIFL33xPyzbFYP0XVdS8P5lUPis= -github.com/cosmos/cosmos-proto v1.0.0-beta.2 h1:X3OKvWgK9Gsejo0F1qs5l8Qn6xJV/AzgIWR2wZ8Nua8= -github.com/cosmos/cosmos-proto v1.0.0-beta.2/go.mod h1:+XRCLJ14pr5HFEHIUcn51IKXD1Fy3rkEQqt4WqmN4V0= +github.com/cosmos/cosmos-proto v1.0.0-beta.3 h1:VitvZ1lPORTVxkmF2fAp3IiA61xVwArQYKXTdEcpW6o= +github.com/cosmos/cosmos-proto v1.0.0-beta.3/go.mod h1:t8IASdLaAq+bbHbjq4p960BvcTqtwuAxid3b/2rOD6I= github.com/cosmos/cosmos-sdk v0.46.13 h1:LhL6WDBadczqBuCW0t5BHUzGQR3vbujdOYOfU0ORt+o= github.com/cosmos/cosmos-sdk v0.46.13/go.mod h1:EfY521ATNEla8eJ6oJuZBdgP5+p360s7InnRqX+TWdM= github.com/cosmos/go-bip39 v0.0.0-20180819234021-555e2067c45d/go.mod h1:tSxLoYXyBmiFeKpvmq4dzayMdCjCnu8uqmCysIGBT2Y= github.com/cosmos/go-bip39 v1.0.0 h1:pcomnQdrdH22njcAatO0yWojsUnCO3y2tNoV1cb6hHY= github.com/cosmos/go-bip39 v1.0.0/go.mod h1:RNJv0H/pOIVgxw6KS7QeX2a0Uo0aKUlfhZ4xuwvCdJw= +github.com/cosmos/gogoproto v1.4.8 h1:BrHKc6WFZt8+jRV71vKSQE+JrfF+JAnzrKo2VP7wIZ4= +github.com/cosmos/gogoproto v1.4.8/go.mod h1:hnb0DIEWTv+wdNzNcqus5xCQXq5+CXauq1FJuurRfVY= github.com/cosmos/gorocksdb v1.2.0 h1:d0l3jJG8M4hBouIZq0mDUHZ+zjOx044J3nGRskwTb4Y= github.com/cosmos/gorocksdb v1.2.0/go.mod h1:aaKvKItm514hKfNJpUJXnnOWeBnk2GL4+Qw9NHizILw= github.com/cosmos/iavl v0.19.6 h1:XY78yEeNPrEYyNCKlqr9chrwoeSDJ0bV2VjocTk//OU= github.com/cosmos/iavl v0.19.6/go.mod h1:X9PKD3J0iFxdmgNLa7b2LYWdsGd90ToV5cAONApkEPw= +github.com/cosmos/ibc-go/v6 v6.1.1 h1:oqqMNyjj6SLQF8rvgCaDGwfdITEIsbhs8F77/8xvRIo= github.com/cosmos/ledger-cosmos-go v0.12.2 h1:/XYaBlE2BJxtvpkHiBm97gFGSGmYGKunKyF3nNqAXZA= github.com/cosmos/ledger-cosmos-go v0.12.2/go.mod h1:ZcqYgnfNJ6lAXe4HPtWgarNEY+B74i+2/8MhZw4ziiI= github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= @@ -176,6 +196,7 @@ github.com/creachadair/taskgroup v0.3.2/go.mod h1:wieWwecHVzsidg2CsUnFinW1faVN4+ github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/danieljoos/wincred v1.1.2 h1:QLdCxFs1/Yl4zduvBdcHB8goaYk9RARS2SgLLRuAyr0= github.com/danieljoos/wincred v1.1.2/go.mod h1:GijpziifJoIBfYh+S7BbkdUTU4LfM+QnGqR5Vl2tAx0= +github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -201,17 +222,19 @@ github.com/dgraph-io/ristretto v0.1.1/go.mod h1:S1GPSBCYCIhmVNfcth17y2zZtQT6wzkz github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 h1:fAjc9m62+UWV/WAFKLNi6ZS0675eEUC9y3AlwSbQu1Y= github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= +github.com/dlclark/regexp2 v1.7.0 h1:7lJfhqlPssTb1WQx4yvTHN0uElPEv52sbaECrAQxjAo= github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= +github.com/dop251/goja v0.0.0-20230122112309-96b1610dd4f7 h1:kgvzE5wLsLa7XKfV85VZl40QXaMCaeFtHpPwJ8fhotY= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v1.0.1-0.20200219035652-afde56e7acac h1:opbrjaN/L8gg6Xh5D04Tem+8xVcz6ajZlGCs49mQgyg= github.com/dustin/go-humanize v1.0.1-0.20200219035652-afde56e7acac/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dvsekhvalnov/jose2go v1.5.0 h1:3j8ya4Z4kMCwT5nXIKFSV84YS+HdqSSO0VsTQxaLAeM= github.com/dvsekhvalnov/jose2go v1.5.0/go.mod h1:QsHjhyTlD/lAVqn/NSbVZmSCGeDehTB/mPZadG+mhXU= -github.com/dymensionxyz/cosmosclient v0.4.0-beta h1:IWyEEdvJ60n/v/DGNelD0n23lS6ED/5rsQJBClgIfhA= -github.com/dymensionxyz/cosmosclient v0.4.0-beta/go.mod h1:3y64ecWDzhnd0sSYZfaL4QpwgK0b0j6LFLVRGdygg+o= +github.com/dymensionxyz/cosmosclient v0.4.1-beta h1:/wEFVPl7v2i+0ZcqUNKn3+xMi9jFKd+KMBQpnjXlCDg= +github.com/dymensionxyz/cosmosclient v0.4.1-beta/go.mod h1:GQQu3ITEjWfi5ULR2B6X2i2YZNennY1yzcT5qdL4MGI= github.com/dymensionxyz/dymension v0.2.0-beta.0.20230607115558-745644a96ea6 h1:dnriGXmMdYEiF/8lMrj+PDlN1vyQc6zgs/ZHL67eoyI= github.com/dymensionxyz/dymension v0.2.0-beta.0.20230607115558-745644a96ea6/go.mod h1:rDkVuF+DxBDi5tTgVHFk1D2xpqf8bOccs6aB1wTOvP0= github.com/dymensionxyz/rpc v1.3.1 h1:7EXWIobaBes5zldRvTIg7TmNsEKjicrWA/OjCc0NaGs= @@ -229,6 +252,8 @@ github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.m github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/ethereum/go-ethereum v1.12.0 h1:bdnhLPtqETd4m3mS8BGMNvBTf36bO5bx/hxE2zljOa0= github.com/ethereum/go-ethereum v1.12.0/go.mod h1:/oo2X/dZLJjf2mJ6YT9wcWxa4nNJDBKDBU6sFIpx1Gs= +github.com/evmos/evmos/v12 v12.1.6 h1:lctgak6afgegbLgv6B28705OOkKclFwIL9KHE++IDQQ= +github.com/evmos/evmos/v12 v12.1.6/go.mod h1:k4JmDA9a4ZXtjdBmxgTqGwFNeF9pY6Ub1KTFdGTQuxI= github.com/facebookgo/ensure v0.0.0-20200202191622-63f1cf65ac4c h1:8ISkoahWXwZR41ois5lSJBSVw4D0OV19Ht/JSTzvSv0= github.com/facebookgo/stack v0.0.0-20160209184415-751773369052 h1:JWuenKqqX8nojtoVVWjGfOF9635RETekkoH6Cc9SX0A= github.com/facebookgo/subset v0.0.0-20200203212716-c811ad88dec4 h1:7HZCaLC5+BZpmbhCOZJ293Lz68O7PYrF2EzeiFMwCLk= @@ -246,6 +271,8 @@ github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4 github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU= github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= +github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff h1:tY80oXqGNY4FhTFhk+o9oFHGINQ/+vhlm8HFzi6znCI= +github.com/getsentry/sentry-go v0.18.0 h1:MtBW5H9QgdcJabtZcuJG80BMOwaBpkRDZkxRkNC1sN0= github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= @@ -268,9 +295,7 @@ github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V github.com/go-logfmt/logfmt v0.5.1 h1:otpy5pqBCBZ1ng9RQ0dPu4PN7ba75Y/aA+UpowDyNVA= github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0= -github.com/go-ole/go-ole v1.2.5/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= -github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q= github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8= @@ -281,6 +306,7 @@ github.com/go-playground/validator/v10 v10.4.1 h1:pH2c5ADXtd66mxoE0Zm9SUhxE20r7a github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4= github.com/go-resty/resty/v2 v2.7.0 h1:me+K9p3uhSmXtrBZ4k9jcEAfJmuC8IivWHwaLZwPrFY= github.com/go-resty/resty/v2 v2.7.0/go.mod h1:9PWDzw47qPphMRFfhsyk0NnSgvluHcljSMVIq3w7q0I= +github.com/go-sourcemap/sourcemap v2.1.3+incompatible h1:W1iEw64niKVGogNgBN3ePyLFfuisuzeidWPMPWmECqU= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-stack/stack v1.8.1 h1:ntEHSVwIt7PNXNpgPmVfMrNhLtgjlmnZha2kOpuRiDw= github.com/go-stack/stack v1.8.1/go.mod h1:dcoOX6HbPZSZptuspn9bctJ+N/CnF5gGygcUP3XYfe4= @@ -298,6 +324,7 @@ github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5x github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= +github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw= github.com/gofrs/uuid v4.3.0+incompatible h1:CaSVZxm5B+7o45rtab4jC2G37WGYX1zQfuU2i6DSvnc= github.com/gofrs/uuid v4.3.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/gogo/gateway v1.1.0 h1:u0SuhL9+Il+UbjM9VIE3ntfRujKbvVpFvNB4HbjeVQ0= @@ -361,6 +388,7 @@ github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ= github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI= @@ -426,7 +454,7 @@ github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ= -github.com/hashicorp/go-getter v1.6.1 h1:NASsgP4q6tL94WH6nJxKWj8As2H/2kop/bB1d8JMyRY= +github.com/hashicorp/go-getter v1.7.0 h1:bzrYP+qu/gMrL1au7/aDvkoOVGUJpeKBgbqRHACAFDY= github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= github.com/hashicorp/go-immutable-radix v1.3.1 h1:DKHmCUm2hRBK510BaiZlwvpD40f8bJFeZnpfm2KLowc= github.com/hashicorp/go-immutable-radix v1.3.1/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= @@ -448,6 +476,7 @@ github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/hdevalence/ed25519consensus v0.0.0-20220222234857-c00d1f31bab3 h1:aSVUgRRRtOrZOC1fYmY9gV0e9z/Iu+xNVSASWjsuyGU= github.com/hdevalence/ed25519consensus v0.0.0-20220222234857-c00d1f31bab3/go.mod h1:5PC6ZNPde8bBqU/ewGZig35+UIZtw9Ytxez8/q5ZyFE= +github.com/holiman/bloomfilter/v2 v2.0.3 h1:73e0e/V0tCydx14a0SCYS/EWCxgwLZ18CZcZKVu0fao= github.com/holiman/uint256 v1.2.2-0.20230321075855-87b91420868c h1:DZfsyhDK1hnSS5lH8l+JggqzEleHteTYfutAiVlSUM8= github.com/holiman/uint256 v1.2.2-0.20230321075855-87b91420868c/go.mod h1:SC8Ryt4n+UBbPbIBKaG9zbbDlp4jOru9xFZmPzLUTxw= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= @@ -491,9 +520,11 @@ github.com/jbenet/go-temp-err-catcher v0.1.0/go.mod h1:0kJRvmDZXNMIiJirNPEYfhpPw github.com/jbenet/goprocess v0.1.4 h1:DRGOFReOMqqDNXwW70QkacFW0YN9QnwLV0Vqk+3oU0o= github.com/jbenet/goprocess v0.1.4/go.mod h1:5yspPrukOVuOLORacaBi858NqyClJPQxYZlqdZVfqY4= github.com/jellevandenhooff/dkim v0.0.0-20150330215556-f50fe3d243e1/go.mod h1:E0B/fFc00Y+Rasa88328GlI/XbtyysCtTHZS8h7IrBU= +github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= github.com/jmhodges/levigo v1.0.0 h1:q5EC36kV79HWeTBWsod3mG11EgStG3qArTKcvlksN1U= github.com/jmhodges/levigo v1.0.0/go.mod h1:Q6Qx+uH3RAqyK4rFQroq9RL7mdkABMcfhEI+nNuzMJQ= +github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= @@ -504,6 +535,7 @@ github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfV github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= github.com/klauspost/compress v1.10.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.12.3/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= github.com/klauspost/compress v1.16.0 h1:iULayQNOReoYUe+1qtKOqw9CwJv3aNQu8ivo7lw1HU4= @@ -527,6 +559,7 @@ github.com/kr/pty v1.1.3/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y= github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= github.com/lib/pq v1.10.7 h1:p7ZhMD+KsSRozJr34udlUrhboJwWAgCg34+/ZZNvZZw= @@ -566,8 +599,8 @@ github.com/libp2p/go-yamux/v4 v4.0.0 h1:+Y80dV2Yx/kv7Y7JKu0LECyVdMXm1VUoko+VQ9rB github.com/libp2p/go-yamux/v4 v4.0.0/go.mod h1:NWjl8ZTLOGlozrXSOZ/HlfG++39iKNnM5wwmtQP1YB4= github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= -github.com/magiconair/properties v1.8.6 h1:5ibWZ6iY0NctNGWo87LalDlEZ6R41TqbbDamhfG/Qzo= -github.com/magiconair/properties v1.8.6/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= +github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= +github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/manifoldco/promptui v0.9.0 h1:3V4HzJk1TtXW1MTZMP7mdlwbBpIinw3HztaIlYthEiA= github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd h1:br0buuQ854V8u83wA0rVZ8ttrq5CpaPZdvrK0LP2lOk= @@ -577,6 +610,7 @@ github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Ky github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/mattn/go-isatty v0.0.18 h1:DOKFKCQ7FNG2L1rbrmstDN4QVRdS89Nkh85u68Uwp98= github.com/mattn/go-isatty v0.0.18/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-runewidth v0.0.10 h1:CoZ3S2P7pvtP45xOtBw+/mDL2z0RKI576gSkzRRpdGg= 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= github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= @@ -584,6 +618,7 @@ github.com/microcosm-cc/bluemonday v1.0.1/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00v github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI= github.com/miekg/dns v1.1.50 h1:DQUfb9uc6smULcREF09Uc+/Gd46YWqJd5DbpPE9xkcA= github.com/miekg/dns v1.1.50/go.mod h1:e3IlAVfNqAllflbibAZEWOXOQ+Ynzk/dDozDxY7XnME= +github.com/miguelmota/go-ethereum-hdwallet v0.1.1 h1:zdXGlHao7idpCBjEGTXThVAtMKs+IxAgivZ75xqkWK0= github.com/mikioh/tcp v0.0.0-20190314235350-803a9b46060c h1:bzE/A84HN25pxAuk9Eej1Kz9OUelF97nAc82bDquQI8= github.com/mikioh/tcp v0.0.0-20190314235350-803a9b46060c/go.mod h1:0SQS9kMwD2VsyFEB++InYyBJroV/FRmBgcydeSUcJms= github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b h1:z78hV3sbSMAUoyUMM0I83AUIT6Hu17AWfgjzIbtrYFc= @@ -657,22 +692,25 @@ github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLA github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= +github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= -github.com/onsi/ginkgo/v2 v2.5.1 h1:auzK7OI497k6x4OvWq+TKAcpcSAlod0doAH72oIN0Jw= -github.com/onsi/ginkgo/v2 v2.5.1/go.mod h1:63DOGlLAH8+REH8jUGdL3YpCpu7JODesutUjdENfUAc= +github.com/onsi/ginkgo/v2 v2.9.0 h1:Tugw2BKlNHTMfG+CheOITkYvk4LAh6MFOvikhGVnhE8= +github.com/onsi/ginkgo/v2 v2.9.0/go.mod h1:4xkjoL/tZv4SMWeww56BU5kAt19mVB47gTWxmrTcxyk= +github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro= -github.com/onsi/gomega v1.24.1 h1:KORJXNNTzJXzu4ScJWssJfJMnJ+2QJqhoQSRwNlze9E= +github.com/onsi/gomega v1.27.2 h1:SKU0CXeKE/WVgIV1T61kSa3+IRE8Ekrv9rdXDwwTqnY= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/image-spec v1.1.0-rc2 h1:2zx/Stx4Wc5pIPDvIxHXvXtQFW/7XWJGmnM7r3wg034= -github.com/opencontainers/runc v1.1.3 h1:vIXrkId+0/J2Ymu2m7VjGvbSlAId9XNRPhn2p4b+d8w= +github.com/opencontainers/runc v1.1.4 h1:nRCz/8sKg6K6jgYAFLDlXzPeITBZJyX28DBVhWD+5dg= github.com/opencontainers/runtime-spec v1.0.2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417 h1:3snG66yBm59tKhhSPQrQ/0bCrv1LQbKt40LnUPiUxdc= github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= @@ -686,8 +724,6 @@ github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144T github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 h1:onHthvaw9LFnH4t2DcNVpwGmV9E1BkGknEliJkfwQj0= github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58/go.mod h1:DXv8WO4yhMYhSNPKjeNKa5WY9YCIEBRbNzFFPJbWO6Y= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= -github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8= -github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/pelletier/go-toml/v2 v2.0.7 h1:muncTPStnKRos5dpVKULv2FVd4bMOhNePj9CjgDb8Us= github.com/pelletier/go-toml/v2 v2.0.7/go.mod h1:eumQOmlWiOPt5WriQQqoM5y18pDHwha2N+QD+EUNTek= github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5/go.mod h1:jvVRKCrJTQWu0XVbaOlby/2lO20uSCHEMzzplHXte1o= @@ -746,6 +782,7 @@ github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqn github.com/regen-network/cosmos-proto v0.3.1 h1:rV7iM4SSFAagvy8RiyhiACbWEGotmqzywPxOvwMdxcg= github.com/regen-network/protobuf v1.3.2-alpha.regen.4 h1:c9jEnU+xm6vqyrQe3M94UFWqiXxRIKKnqBOh2EACmBE= github.com/regen-network/protobuf v1.3.2-alpha.regen.4/go.mod h1:/J8/bR1T/NXyIdQDLUaq15LjNE83nRzkyrLAMcPewig= +github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= 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= github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= @@ -802,8 +839,8 @@ github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasO github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI= github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= -github.com/spf13/afero v1.9.2 h1:j49Hj62F0n+DaZ1dDCvhABaPNSGNkt32oRFxI33IEMw= -github.com/spf13/afero v1.9.2/go.mod h1:iUV7ddyEEZPO5gA3zD4fJt6iStLlL+Lg4m2cihcDf8Y= +github.com/spf13/afero v1.9.3 h1:41FoI0fD7OR7mGcKE/aOiLkGreyf8ifIOQmJANWogMk= +github.com/spf13/afero v1.9.3/go.mod h1:iUV7ddyEEZPO5gA3zD4fJt6iStLlL+Lg4m2cihcDf8Y= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cast v1.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w= github.com/spf13/cast v1.5.0/go.mod h1:SpXXQ5YoyJw6s3/6cMTQuxvgRl3PCJiyaX9p6b155UU= @@ -817,8 +854,9 @@ github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnIn github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= -github.com/spf13/viper v1.14.0 h1:Rg7d3Lo706X9tHsJMUjdiwMpHB7W8WnSVOssIY+JElU= -github.com/spf13/viper v1.14.0/go.mod h1:WT//axPky3FdvXHzGw33dNdXXXfFQqmEalje+egj8As= +github.com/spf13/viper v1.15.0 h1:js3yy885G8xwJa6iOISGFwd+qlUo5AvyXb7CiihdtiU= +github.com/spf13/viper v1.15.0/go.mod h1:fFcTBJxvhhzSJiZy8n+PeW6t8l+KeT/uTARa0jHOQLA= +github.com/status-im/keycard-go v0.2.0 h1:QDLFswOQu1r5jsycloeQh3bVU8n/NatHHaZobtDnDzA= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= @@ -836,8 +874,8 @@ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -github.com/subosito/gotenv v1.4.1 h1:jyEFiXpy21Wm81FBN71l9VoMMV8H8jG+qIK3GCpY6Qs= -github.com/subosito/gotenv v1.4.1/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0= +github.com/subosito/gotenv v1.4.2 h1:X1TuBLAMDFbaTAChgCBLu3DU3UPyELpnF2jjJ2cz/S8= +github.com/subosito/gotenv v1.4.2/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0= github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d h1:vfofYNRScrDdvS342BElfbETmL1Aiz3i2t0zfRj16Hs= github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d/go.mod h1:RRCYJbIwD5jmqPI9XoAFR0OcDxqUctll6zUj/+B4S48= github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA= @@ -849,19 +887,28 @@ github.com/tendermint/tm-db v0.6.7 h1:fE00Cbl0jayAoqlExN6oyQJ7fR/ZtoVOmvPJ//+shu github.com/tendermint/tm-db v0.6.7/go.mod h1:byQDzFkZV1syXr/ReXS808NxA2xvyuuVgXOJ/088L6I= github.com/tidwall/btree v1.5.0 h1:iV0yVY/frd7r6qGBXfEYs7DH0gTDgrKTrDjS7xt/IyQ= github.com/tidwall/btree v1.5.0/go.mod h1:LGm8L/DZjPLmeWGjv5kFrY8dL4uVhMmzmmLYmsObdKE= +github.com/tidwall/gjson v1.14.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= +github.com/tidwall/gjson v1.14.4 h1:uo0p8EbA09J7RQaflQ1aBRffTR7xedD2bcIVSYxLnkM= +github.com/tidwall/gjson v1.14.4/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= +github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA= +github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= +github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs= +github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= +github.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY= +github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28= github.com/tinylib/msgp v1.1.5/go.mod h1:eQsjooMTnV42mHu917E26IogZ2930nFyBQdofk10Udg= github.com/tklauser/go-sysconf v0.3.10 h1:IJ1AZGZRWbY8T5Vfk04D9WOA5WSejdflXxP03OUqALw= -github.com/tklauser/go-sysconf v0.3.10/go.mod h1:C8XykCvCb+Gn0oNCWPIlcb0RuglQTYaQ2hGm7jmxEFk= github.com/tklauser/numcpus v0.4.0 h1:E53Dm1HjH1/R2/aoCtXtPgzmElmn51aOkhCFSuZq//o= -github.com/tklauser/numcpus v0.4.0/go.mod h1:1+UI3pD8NW14VMwdgJNJ1ESk2UnwhAnz5hMwiKKqXCQ= github.com/ttacon/chalk v0.0.0-20160626202418-22c06c80ed31/go.mod h1:onvgF043R+lC5RZ8IT9rBXDaEDnpnw/Cl+HFiw+v/7Q= github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= +github.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8= +github.com/tyler-smith/go-bip39 v1.1.0/go.mod h1:gUYDtqQw1JS3ZJ8UWVcGTGqqr6YIN3CWg+kkNaLt55U= github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo= github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs= github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= -github.com/ulikunitz/xz v0.5.8 h1:ERv8V6GKqVi23rgu5cj9pVfVzJbOqAY2Ntl88O6c2nQ= +github.com/ulikunitz/xz v0.5.10 h1:t92gobL9l3HE202wg3rlk19F6X+JOxl9BBrCCMYEYd8= github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/vedhavyas/go-subkey v1.0.3 h1:iKR33BB/akKmcR2PMlXPBeeODjWLM90EL98OrOGs8CA= github.com/vedhavyas/go-subkey v1.0.3/go.mod h1:CloUaFQSSTdWnINfBRFjVMkWXZANW+nd8+TI5jYcl6Y= @@ -917,6 +964,7 @@ go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60= go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg= go4.org v0.0.0-20180809161055-417644f6feb5/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE= golang.org/x/build v0.0.0-20190111050920-041ab4dc3f9d/go.mod h1:OWs+y06UdEOHN4y+MfF/py+xQ/tYqIWW03b70/CG9Rw= +golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= @@ -927,6 +975,7 @@ golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200115085410-6d4e4cb37c7d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200602180216-279210d13fed/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= @@ -1072,7 +1121,6 @@ golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1114,7 +1162,6 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210819135213-f52c844e1c1c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/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=