manager

package
v0.3.3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 14, 2019 License: MIT Imports: 24 Imported by: 0

Documentation

Index

Constants

View Source
const WaitHeightTolerance = uint32(1)

Variables

This section is empty.

Functions

Types

type AbnormalRecovering

type AbnormalRecovering interface {
	CollectConsensusStatus(height uint32, status *dmsg.ConsensusStatus) error
	RecoverFromConsensusStatus(status *dmsg.ConsensusStatus) error
}

type Consensus

type Consensus struct {
	// contains filtered or unexported fields
}

func NewConsensus

func NewConsensus(manager *DPOSManager, tolerance time.Duration,
	viewListener ViewListener) *Consensus

func (*Consensus) ChangeView

func (c *Consensus) ChangeView()

func (*Consensus) CollectConsensusStatus added in v0.3.0

func (c *Consensus) CollectConsensusStatus(status *msg.ConsensusStatus) error

func (*Consensus) GetOnDutyArbitrator

func (c *Consensus) GetOnDutyArbitrator() []byte

func (*Consensus) GetViewOffset

func (c *Consensus) GetViewOffset() uint32

func (*Consensus) IsArbitratorOnDuty

func (c *Consensus) IsArbitratorOnDuty(arbitrator []byte) bool

func (*Consensus) IsOnDuty

func (c *Consensus) IsOnDuty() bool

func (*Consensus) IsReady

func (c *Consensus) IsReady() bool

func (*Consensus) IsRunning

func (c *Consensus) IsRunning() bool

func (*Consensus) ProcessBlock

func (c *Consensus) ProcessBlock(b *types.Block)

func (*Consensus) RecoverFromConsensusStatus added in v0.3.0

func (c *Consensus) RecoverFromConsensusStatus(status *msg.ConsensusStatus) error

func (*Consensus) SetOnDuty

func (c *Consensus) SetOnDuty(onDuty bool)

func (*Consensus) SetReady

func (c *Consensus) SetReady()

func (*Consensus) SetRunning

func (c *Consensus) SetRunning()

func (*Consensus) StartConsensus

func (c *Consensus) StartConsensus(b *types.Block)

func (*Consensus) TryChangeView

func (c *Consensus) TryChangeView() bool

type ConsensusBlockCache

type ConsensusBlockCache struct {
	ConsensusBlocks    map[common.Uint256]*types.Block
	ConsensusBlockList []common.Uint256

	Listener ConsensusBlockCacheListener
}

func (*ConsensusBlockCache) AddValue

func (c *ConsensusBlockCache) AddValue(key common.Uint256, value *types.Block)

func (*ConsensusBlockCache) GetFirstArrivedBlockHash

func (c *ConsensusBlockCache) GetFirstArrivedBlockHash() (common.Uint256, bool)

func (*ConsensusBlockCache) Reset

func (c *ConsensusBlockCache) Reset(block *types.Block)

func (*ConsensusBlockCache) TryGetValue

func (c *ConsensusBlockCache) TryGetValue(key common.Uint256) (*types.Block, bool)

type ConsensusBlockCacheListener

type ConsensusBlockCacheListener interface {
	OnBlockAdded(b *types.Block)
}

type DPOSEventConditionHandler added in v0.3.0

type DPOSEventConditionHandler interface {
	TryStartNewConsensus(b *types.Block) bool

	ChangeView(firstBlockHash *common.Uint256)

	ProcessProposal(id peer.PID, p *payload.DPOSProposal) (handled bool)
	ProcessAcceptVote(id peer.PID, p *payload.DPOSProposalVote) (succeed bool, finished bool)
	ProcessRejectVote(id peer.PID, p *payload.DPOSProposalVote) (succeed bool, finished bool)
}

type DPOSHandlerConfig added in v0.3.0

type DPOSHandlerConfig struct {
	Network     DPOSNetwork
	Manager     *DPOSManager
	Monitor     *log.EventMonitor
	Arbitrators state.Arbitrators
	TimeSource  dtime.MedianTimeSource
}

type DPOSHandlerSwitch added in v0.3.0

type DPOSHandlerSwitch struct {
	// contains filtered or unexported fields
}

func NewHandler

func NewHandler(cfg DPOSHandlerConfig) *DPOSHandlerSwitch

func (*DPOSHandlerSwitch) AddListeners added in v0.3.0

func (h *DPOSHandlerSwitch) AddListeners(listeners ...log.EventListener)

func (*DPOSHandlerSwitch) ChangeView added in v0.3.0

func (h *DPOSHandlerSwitch) ChangeView(firstBlockHash *common.Uint256)

func (*DPOSHandlerSwitch) FinishConsensus added in v0.3.0

func (h *DPOSHandlerSwitch) FinishConsensus()

func (*DPOSHandlerSwitch) HelpToRecoverAbnormal added in v0.3.0

func (h *DPOSHandlerSwitch) HelpToRecoverAbnormal(id peer.PID, height uint32)

func (*DPOSHandlerSwitch) Initialize added in v0.3.0

func (h *DPOSHandlerSwitch) Initialize(dispatcher *ProposalDispatcher,
	consensus *Consensus)

func (*DPOSHandlerSwitch) IsAbnormal added in v0.3.0

func (h *DPOSHandlerSwitch) IsAbnormal() bool

func (*DPOSHandlerSwitch) OnViewChanged added in v0.3.0

func (h *DPOSHandlerSwitch) OnViewChanged(isOnDuty bool)

func (*DPOSHandlerSwitch) ProcessAcceptVote added in v0.3.0

func (h *DPOSHandlerSwitch) ProcessAcceptVote(id peer.PID, p *payload.DPOSProposalVote) (bool, bool)

func (*DPOSHandlerSwitch) ProcessProposal added in v0.3.0

func (h *DPOSHandlerSwitch) ProcessProposal(id peer.PID, p *payload.DPOSProposal) (handled bool)

func (*DPOSHandlerSwitch) ProcessRejectVote added in v0.3.0

func (h *DPOSHandlerSwitch) ProcessRejectVote(id peer.PID, p *payload.DPOSProposalVote) (bool, bool)

func (*DPOSHandlerSwitch) RecoverAbnormal added in v0.3.0

func (h *DPOSHandlerSwitch) RecoverAbnormal(status *msg.ConsensusStatus)

func (*DPOSHandlerSwitch) RequestAbnormalRecovering added in v0.3.0

func (h *DPOSHandlerSwitch) RequestAbnormalRecovering()

func (*DPOSHandlerSwitch) ResponseGetBlocks added in v0.3.0

func (h *DPOSHandlerSwitch) ResponseGetBlocks(id peer.PID, startBlockHeight, endBlockHeight uint32)

func (*DPOSHandlerSwitch) SwitchTo added in v0.3.0

func (h *DPOSHandlerSwitch) SwitchTo(onDuty bool)

func (*DPOSHandlerSwitch) TryStartNewConsensus added in v0.3.0

func (h *DPOSHandlerSwitch) TryStartNewConsensus(b *types.Block) bool

type DPOSManager added in v0.3.0

type DPOSManager struct {
	// contains filtered or unexported fields
}

func NewManager

func NewManager(cfg DPOSManagerConfig) *DPOSManager

func (*DPOSManager) AppendBlock added in v0.3.0

func (d *DPOSManager) AppendBlock(block *types.Block)

func (*DPOSManager) AppendConfirm added in v0.3.0

func (d *DPOSManager) AppendConfirm(confirm *payload.Confirm) (bool, bool, error)

func (*DPOSManager) AppendToTxnPool added in v0.3.0

func (d *DPOSManager) AppendToTxnPool(txn *types.Transaction) error

func (*DPOSManager) Broadcast added in v0.3.0

func (d *DPOSManager) Broadcast(msg p2p.Message)

func (*DPOSManager) ChangeConsensus added in v0.3.0

func (d *DPOSManager) ChangeConsensus(onDuty bool)

func (*DPOSManager) ConfirmBlock added in v0.3.0

func (d *DPOSManager) ConfirmBlock()

func (*DPOSManager) DoRecover added in v0.3.2

func (d *DPOSManager) DoRecover()

func (*DPOSManager) GetArbitrators added in v0.3.0

func (d *DPOSManager) GetArbitrators() state.Arbitrators

func (*DPOSManager) GetBlockCache added in v0.3.0

func (d *DPOSManager) GetBlockCache() *ConsensusBlockCache

func (*DPOSManager) GetPublicKey added in v0.3.0

func (d *DPOSManager) GetPublicKey() []byte

func (*DPOSManager) Initialize added in v0.3.0

func (d *DPOSManager) Initialize(handler *DPOSHandlerSwitch,
	dispatcher *ProposalDispatcher, consensus *Consensus, network DPOSNetwork,
	illegalMonitor *IllegalBehaviorMonitor, blockPool *mempool.BlockPool,
	txPool *mempool.TxPool, broadcast func(message p2p.Message))

func (*DPOSManager) OnBadNetwork added in v0.3.0

func (d *DPOSManager) OnBadNetwork()

func (*DPOSManager) OnBlock added in v0.3.0

func (d *DPOSManager) OnBlock(id dpeer.PID, block *types.Block)

func (*DPOSManager) OnBlockReceived added in v0.3.0

func (d *DPOSManager) OnBlockReceived(b *types.Block, confirmed bool)

func (*DPOSManager) OnChangeView added in v0.3.0

func (d *DPOSManager) OnChangeView()

func (*DPOSManager) OnConfirmReceived added in v0.3.0

func (d *DPOSManager) OnConfirmReceived(p *payload.Confirm)

func (*DPOSManager) OnGetBlock added in v0.3.0

func (d *DPOSManager) OnGetBlock(id dpeer.PID, blockHash common.Uint256)

func (*DPOSManager) OnGetBlocks added in v0.3.0

func (d *DPOSManager) OnGetBlocks(id dpeer.PID, startBlockHeight, endBlockHeight uint32)

func (*DPOSManager) OnIllegalBlocksTxReceived added in v0.3.0

func (d *DPOSManager) OnIllegalBlocksTxReceived(i *payload.DPOSIllegalBlocks)

func (*DPOSManager) OnIllegalProposalReceived added in v0.3.0

func (d *DPOSManager) OnIllegalProposalReceived(id dpeer.PID, proposals *payload.DPOSIllegalProposals)

func (*DPOSManager) OnIllegalVotesReceived added in v0.3.0

func (d *DPOSManager) OnIllegalVotesReceived(id dpeer.PID, votes *payload.DPOSIllegalVotes)

func (*DPOSManager) OnInactiveArbitratorsAccepted added in v0.3.2

func (d *DPOSManager) OnInactiveArbitratorsAccepted(p *payload.InactiveArbitrators)

func (*DPOSManager) OnInactiveArbitratorsReceived added in v0.3.0

func (d *DPOSManager) OnInactiveArbitratorsReceived(id dpeer.PID,
	tx *types.Transaction)

func (*DPOSManager) OnInv added in v0.3.0

func (d *DPOSManager) OnInv(id dpeer.PID, blockHash common.Uint256)

func (*DPOSManager) OnPing added in v0.3.0

func (d *DPOSManager) OnPing(id dpeer.PID, height uint32)

func (*DPOSManager) OnPong added in v0.3.0

func (d *DPOSManager) OnPong(id dpeer.PID, height uint32)

func (*DPOSManager) OnProposalReceived added in v0.3.0

func (d *DPOSManager) OnProposalReceived(id dpeer.PID, p *payload.DPOSProposal)

func (*DPOSManager) OnRecover added in v0.3.2

func (d *DPOSManager) OnRecover()

func (*DPOSManager) OnRecoverTimeout added in v0.3.2

func (d *DPOSManager) OnRecoverTimeout()

func (*DPOSManager) OnRequestConsensus added in v0.3.0

func (d *DPOSManager) OnRequestConsensus(id dpeer.PID, height uint32)

func (*DPOSManager) OnRequestProposal added in v0.3.0

func (d *DPOSManager) OnRequestProposal(id dpeer.PID, hash common.Uint256)

func (*DPOSManager) OnResponseBlocks added in v0.3.0

func (d *DPOSManager) OnResponseBlocks(id dpeer.PID, blockConfirms []*types.DposBlock)

func (*DPOSManager) OnResponseConsensus added in v0.3.0

func (d *DPOSManager) OnResponseConsensus(id dpeer.PID, status *dmsg.ConsensusStatus)

func (*DPOSManager) OnResponseInactiveArbitratorsReceived added in v0.3.0

func (d *DPOSManager) OnResponseInactiveArbitratorsReceived(
	txHash *common.Uint256, signers []byte, signs []byte)

func (*DPOSManager) OnSidechainIllegalEvidenceReceived added in v0.3.0

func (d *DPOSManager) OnSidechainIllegalEvidenceReceived(s *payload.SidechainIllegalData)

func (*DPOSManager) OnVoteAccepted added in v0.3.0

func (d *DPOSManager) OnVoteAccepted(id dpeer.PID, p *payload.DPOSProposalVote)

func (*DPOSManager) OnVoteRejected added in v0.3.0

func (d *DPOSManager) OnVoteRejected(id dpeer.PID, p *payload.DPOSProposalVote)

func (*DPOSManager) ProcessHigherBlock added in v0.3.0

func (d *DPOSManager) ProcessHigherBlock(b *types.Block)

type DPOSManagerConfig added in v0.3.0

type DPOSManagerConfig struct {
	PublicKey   []byte
	Arbitrators state.Arbitrators
	ChainParams *config.Params
	TimeSource  dtime.MedianTimeSource
	Server      elanet.Server
}

type DPOSNetwork added in v0.3.0

type DPOSNetwork interface {
	Initialize(dnConfig DPOSNetworkConfig)

	Start()
	Stop() error

	SendMessageToPeer(id dpeer.PID, msg p2p.Message) error
	BroadcastMessage(msg p2p.Message)

	UpdatePeers(peers []dpeer.PID)
	GetActivePeers() []dp2p.Peer
	RecoverTimeout()
}

type DPOSNetworkConfig added in v0.3.0

type DPOSNetworkConfig struct {
	ProposalDispatcher *ProposalDispatcher
	Store              store.IDposStore
	PublicKey          []byte
	AnnounceAddr       func()
}

type DPOSNormalHandler added in v0.3.0

type DPOSNormalHandler struct {
	*DPOSHandlerSwitch
}

func (*DPOSNormalHandler) ChangeView added in v0.3.0

func (h *DPOSNormalHandler) ChangeView(firstBlockHash *common.Uint256)

func (*DPOSNormalHandler) ProcessAcceptVote added in v0.3.0

func (h *DPOSNormalHandler) ProcessAcceptVote(id peer.PID, p *payload.DPOSProposalVote) (succeed bool, finished bool)

func (*DPOSNormalHandler) ProcessProposal added in v0.3.0

func (h *DPOSNormalHandler) ProcessProposal(id peer.PID, p *payload.DPOSProposal) (handled bool)

func (*DPOSNormalHandler) ProcessRejectVote added in v0.3.0

func (h *DPOSNormalHandler) ProcessRejectVote(id peer.PID, p *payload.DPOSProposalVote) (succeed bool, finished bool)

func (*DPOSNormalHandler) TryStartNewConsensus added in v0.3.0

func (h *DPOSNormalHandler) TryStartNewConsensus(b *types.Block) bool

type DPOSOnDutyHandler added in v0.3.0

type DPOSOnDutyHandler struct {
	*DPOSHandlerSwitch
}

func (*DPOSOnDutyHandler) ChangeView added in v0.3.0

func (h *DPOSOnDutyHandler) ChangeView(firstBlockHash *common.Uint256)

func (*DPOSOnDutyHandler) ProcessAcceptVote added in v0.3.0

func (h *DPOSOnDutyHandler) ProcessAcceptVote(id peer.PID, p *payload.DPOSProposalVote) (succeed bool, finished bool)

func (*DPOSOnDutyHandler) ProcessProposal added in v0.3.0

func (h *DPOSOnDutyHandler) ProcessProposal(id peer.PID, p *payload.DPOSProposal) (handled bool)

func (*DPOSOnDutyHandler) ProcessRejectVote added in v0.3.0

func (h *DPOSOnDutyHandler) ProcessRejectVote(id peer.PID, p *payload.DPOSProposalVote) (succeed bool, finished bool)

func (*DPOSOnDutyHandler) TryStartNewConsensus added in v0.3.0

func (h *DPOSOnDutyHandler) TryStartNewConsensus(b *types.Block) bool

type IllegalBehaviorMonitor

type IllegalBehaviorMonitor struct {
	// contains filtered or unexported fields
}

func (*IllegalBehaviorMonitor) AddEvidence added in v0.3.0

func (i *IllegalBehaviorMonitor) AddEvidence(evidence payload.DPOSIllegalData)

func (*IllegalBehaviorMonitor) AddProposal

func (i *IllegalBehaviorMonitor) AddProposal(proposal *payload.DPOSProposal)

func (*IllegalBehaviorMonitor) CleanByBlock added in v0.3.2

func (i *IllegalBehaviorMonitor) CleanByBlock(b *types.Block)

func (*IllegalBehaviorMonitor) IsBlockValid

func (i *IllegalBehaviorMonitor) IsBlockValid(block *types.Block) bool

func (*IllegalBehaviorMonitor) IsLegalProposal

func (*IllegalBehaviorMonitor) IsLegalVote

func (*IllegalBehaviorMonitor) ProcessIllegalProposal

func (i *IllegalBehaviorMonitor) ProcessIllegalProposal(
	first, second *payload.DPOSProposal)

func (*IllegalBehaviorMonitor) ProcessIllegalVote

func (i *IllegalBehaviorMonitor) ProcessIllegalVote(
	first, second *payload.DPOSProposalVote)

func (*IllegalBehaviorMonitor) Reset

func (i *IllegalBehaviorMonitor) Reset(changeView bool)

func (*IllegalBehaviorMonitor) SendSidechainIllegalEvidenceTransaction added in v0.3.0

func (i *IllegalBehaviorMonitor) SendSidechainIllegalEvidenceTransaction(
	evidence *payload.SidechainIllegalData)

func (*IllegalBehaviorMonitor) SetInactiveArbitratorsTxHash added in v0.3.0

func (i *IllegalBehaviorMonitor) SetInactiveArbitratorsTxHash(
	hash common.Uint256)

type NetworkEventListener

type NetworkEventListener interface {
	StatusSyncEventListener

	OnProposalReceived(id dpeer.PID, p *payload.DPOSProposal)
	OnVoteAccepted(id dpeer.PID, p *payload.DPOSProposalVote)
	OnVoteRejected(id dpeer.PID, p *payload.DPOSProposalVote)

	OnChangeView()
	OnBadNetwork()
	OnRecover()
	OnRecoverTimeout()

	OnBlockReceived(b *types.Block, confirmed bool)
	OnConfirmReceived(p *payload.Confirm)
	OnIllegalBlocksTxReceived(i *payload.DPOSIllegalBlocks)
	OnSidechainIllegalEvidenceReceived(s *payload.SidechainIllegalData)
	OnInactiveArbitratorsReceived(id dpeer.PID, tx *types.Transaction)
	OnResponseInactiveArbitratorsReceived(txHash *common.Uint256,
		Signer []byte, Sign []byte)
	OnInactiveArbitratorsAccepted(p *payload.InactiveArbitrators)
}

type ProposalDispatcher

type ProposalDispatcher struct {
	// contains filtered or unexported fields
}

func (*ProposalDispatcher) AddPendingVote

func (p *ProposalDispatcher) AddPendingVote(v *payload.DPOSProposalVote)

func (*ProposalDispatcher) AppendConfirm added in v0.3.2

func (p *ProposalDispatcher) AppendConfirm()

func (*ProposalDispatcher) CleanProposals

func (p *ProposalDispatcher) CleanProposals(changeView bool)

func (*ProposalDispatcher) CollectConsensusStatus added in v0.3.0

func (p *ProposalDispatcher) CollectConsensusStatus(status *dmsg.ConsensusStatus) error

func (*ProposalDispatcher) CreateInactiveArbitrators added in v0.3.0

func (p *ProposalDispatcher) CreateInactiveArbitrators() (
	*types.Transaction, error)

func (*ProposalDispatcher) FinishConsensus

func (p *ProposalDispatcher) FinishConsensus()

func (*ProposalDispatcher) FinishProposal

func (p *ProposalDispatcher) FinishProposal() bool

func (*ProposalDispatcher) GetProcessingBlock

func (p *ProposalDispatcher) GetProcessingBlock() *types.Block

func (*ProposalDispatcher) GetProcessingProposal

func (p *ProposalDispatcher) GetProcessingProposal() *payload.DPOSProposal

func (*ProposalDispatcher) IsCRCBadNetWork added in v0.3.2

func (p *ProposalDispatcher) IsCRCBadNetWork() bool

func (*ProposalDispatcher) IsViewChangedTimeOut added in v0.3.0

func (p *ProposalDispatcher) IsViewChangedTimeOut() bool

func (*ProposalDispatcher) OnBlockAdded added in v0.3.0

func (p *ProposalDispatcher) OnBlockAdded(b *types.Block)

func (*ProposalDispatcher) OnIllegalBlocksTxReceived added in v0.3.2

func (p *ProposalDispatcher) OnIllegalBlocksTxReceived(i *payload.DPOSIllegalBlocks)

func (*ProposalDispatcher) OnInactiveArbitratorsReceived added in v0.3.0

func (p *ProposalDispatcher) OnInactiveArbitratorsReceived(id peer.PID,
	tx *types.Transaction)

func (*ProposalDispatcher) OnResponseInactiveArbitratorsReceived added in v0.3.0

func (p *ProposalDispatcher) OnResponseInactiveArbitratorsReceived(
	txHash *common.Uint256, signer []byte, sign []byte)

func (*ProposalDispatcher) ProcessProposal

func (p *ProposalDispatcher) ProcessProposal(id peer.PID, d *payload.DPOSProposal,
	force bool) (needRecord bool, handled bool)

func (*ProposalDispatcher) ProcessVote

func (p *ProposalDispatcher) ProcessVote(v *payload.DPOSProposalVote,
	accept bool) (succeed bool, finished bool)

func (*ProposalDispatcher) RecoverFromConsensusStatus added in v0.3.0

func (p *ProposalDispatcher) RecoverFromConsensusStatus(status *dmsg.ConsensusStatus) error

func (*ProposalDispatcher) RequestAbnormalRecovering

func (p *ProposalDispatcher) RequestAbnormalRecovering()

func (*ProposalDispatcher) ResetByCurrentView added in v0.3.2

func (p *ProposalDispatcher) ResetByCurrentView()

func (*ProposalDispatcher) StartProposal

func (p *ProposalDispatcher) StartProposal(b *types.Block)

func (*ProposalDispatcher) TryStartSpeculatingProposal

func (p *ProposalDispatcher) TryStartSpeculatingProposal(b *types.Block)

func (*ProposalDispatcher) UpdatePrecociousProposals added in v0.3.2

func (p *ProposalDispatcher) UpdatePrecociousProposals()

type ProposalDispatcherConfig added in v0.3.0

type ProposalDispatcherConfig struct {
	store.EventStoreAnalyzerConfig
	EventMonitor *log.EventMonitor
	Consensus    *Consensus
	Network      DPOSNetwork
	Manager      *DPOSManager
	Account      account.Account
	ChainParams  *config.Params
	TimeSource   dtime.MedianTimeSource
}

type StatusSyncEventListener

type StatusSyncEventListener interface {
	OnPing(id dpeer.PID, height uint32)
	OnPong(id dpeer.PID, height uint32)
	OnBlock(id dpeer.PID, block *types.Block)
	OnInv(id dpeer.PID, blockHash common.Uint256)
	OnGetBlock(id dpeer.PID, blockHash common.Uint256)
	OnGetBlocks(id dpeer.PID, startBlockHeight, endBlockHeight uint32)
	OnResponseBlocks(id dpeer.PID, blockConfirms []*types.DposBlock)
	OnRequestConsensus(id dpeer.PID, height uint32)
	OnResponseConsensus(id dpeer.PID, status *dmsg.ConsensusStatus)
	OnRequestProposal(id dpeer.PID, hash common.Uint256)
	OnIllegalProposalReceived(id dpeer.PID, proposals *payload.DPOSIllegalProposals)
	OnIllegalVotesReceived(id dpeer.PID, votes *payload.DPOSIllegalVotes)
}

type ViewChangesCountDown added in v0.3.0

type ViewChangesCountDown struct {
	// contains filtered or unexported fields
}

func (*ViewChangesCountDown) IsTimeOut added in v0.3.0

func (c *ViewChangesCountDown) IsTimeOut() bool

func (*ViewChangesCountDown) Reset added in v0.3.0

func (c *ViewChangesCountDown) Reset(start uint32)

func (*ViewChangesCountDown) SetEliminated added in v0.3.0

func (c *ViewChangesCountDown) SetEliminated(hash common.Uint256) bool

type ViewListener

type ViewListener interface {
	OnViewChanged(isOnDuty bool)
}

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL