stake

package
v0.1.4-beta Latest Latest
Warning

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

Go to latest
Published: Feb 28, 2019 License: GPL-3.0 Imports: 28 Imported by: 15

Documentation

Overview

nolint

Index

Constants

View Source
const (
	ByteTxDeclareCandidacy             = 0x55
	ByteTxUpdateCandidacy              = 0x56
	ByteTxWithdrawCandidacy            = 0x57
	ByteTxVerifyCandidacy              = 0x58
	ByteTxActivateCandidacy            = 0x59
	ByteTxDelegate                     = 0x60
	ByteTxWithdraw                     = 0x61
	ByteTxSetCompRate                  = 0x62
	ByteTxUpdateCandidacyAccount       = 0x63
	ByteTxAcceptCandidacyAccountUpdate = 0x64
	ByteTxDeactivateCandidacy          = 0x65
	TypeTxDeclareCandidacy             = "stake/declareCandidacy"
	TypeTxUpdateCandidacy              = "stake/updateCandidacy"
	TypeTxVerifyCandidacy              = "stake/verifyCandidacy"
	TypeTxWithdrawCandidacy            = "stake/withdrawCandidacy"
	TypeTxActivateCandidacy            = "stake/activateCandidacy"
	TypeTxDeactivateCandidacy          = "stake/deactivateCandidacy"
	TypeTxDelegate                     = "stake/delegate"
	TypeTxWithdraw                     = "stake/withdraw"
	TypeTxSetCompRate                  = "stake/setCompRate"
	TypeTxUpdateCandidacyAccount       = "stake/updateCandidacyAccount"
	TypeTxAcceptCandidacyAccountUpdate = "stake/acceptCandidacyAccountUpdate"
)

register the tx type with its validation logic make sure to use the name of the handler as the prefix in the tx type, so it gets routed properly

Variables

This section is empty.

Functions

func AccumulateDelegationsAverageStakingDate

func AccumulateDelegationsAverageStakingDate() error

func CheckTx

func CheckTx(ctx types.Context, store state.SimpleDB, tx sdk.Tx) (res sdk.CheckResult, err error)

CheckTx checks if the tx is properly structured

func DeliverTx

func DeliverTx(ctx types.Context, store state.SimpleDB, tx sdk.Tx, hash []byte) (res sdk.DeliverResult, err error)

DeliverTx executes the tx if valid

func ErrAddressAlreadyDeclared

func ErrAddressAlreadyDeclared() error

func ErrBadAmount

func ErrBadAmount() error

func ErrBadCompRate

func ErrBadCompRate() error

func ErrBadRequest

func ErrBadRequest() error

func ErrBadValidatorAddr

func ErrBadValidatorAddr() error

func ErrCandidateAlreadyActivated

func ErrCandidateAlreadyActivated() error

func ErrCandidateAlreadyDeactivated

func ErrCandidateAlreadyDeactivated() error

func ErrCandidateExistsAddr

func ErrCandidateExistsAddr() error

func ErrCandidateHasPendingUnstakeRequests

func ErrCandidateHasPendingUnstakeRequests() error

func ErrCandidateWithdrawalDisallowed

func ErrCandidateWithdrawalDisallowed() error

func ErrDelegationNotExists

func ErrDelegationNotExists() error

func ErrInsufficientFunds

func ErrInsufficientFunds() error

func ErrInvalidCubeSignature

func ErrInvalidCubeSignature() error

func ErrInvalidWithdrawalAmount

func ErrInvalidWithdrawalAmount() error

func ErrMissingSignature

func ErrMissingSignature() error

func ErrPubKeyAleadyDeclared

func ErrPubKeyAleadyDeclared() error

func ErrReachMaxAmount

func ErrReachMaxAmount() error

func ErrVerificationDisallowed

func ErrVerificationDisallowed() error

func GetCandidateDailyStakeMaxValue

func GetCandidateDailyStakeMaxValue(candidateId int64, startBlockHeight int64) (res int64)

func GetCandidatesTotalShares

func GetCandidatesTotalShares() (res sdk.Int)

func GetNumOfDelegatorsByCandidate

func GetNumOfDelegatorsByCandidate(candidateId int64) int64

func HandlePendingUnstakeRequests

func HandlePendingUnstakeRequests(height int64) error

func NewAwardDistributor

func NewAwardDistributor(store state.SimpleDB, height int64, validators, backupValidators Validators, logger log.Logger) *awardDistributor

func NewTxAcceptCandidacyAccountUpdate

func NewTxAcceptCandidacyAccountUpdate(accountUpdateRequestId int64) sdk.Tx

func NewTxActivateCandidacy

func NewTxActivateCandidacy() sdk.Tx

func NewTxDeactivateCandidacy

func NewTxDeactivateCandidacy() sdk.Tx

func NewTxDeclareCandidacy

func NewTxDeclareCandidacy(pubKey types.PubKey, maxAmount string, compRate sdk.Rat, description Description) sdk.Tx

func NewTxDelegate

func NewTxDelegate(validatorAddress common.Address, amount, cubeBatch, sig string) sdk.Tx

func NewTxSetCompRate

func NewTxSetCompRate(delegatorAddress common.Address, compRate sdk.Rat) sdk.Tx

func NewTxUpdateCandidacy

func NewTxUpdateCandidacy(pubKey types.PubKey, maxAmount string, compRate sdk.Rat, description Description) sdk.Tx

func NewTxUpdateCandidacyAccount

func NewTxUpdateCandidacyAccount(newCandidateAddress common.Address) sdk.Tx

func NewTxVerifyCandidacy

func NewTxVerifyCandidacy(candidateAddress common.Address, verified bool) sdk.Tx

func NewTxWithdraw

func NewTxWithdraw(validatorAddress common.Address, amount string) sdk.Tx

func NewTxWithdrawCandidacy

func NewTxWithdrawCandidacy() sdk.Tx

func RecordCandidateDailyStakes

func RecordCandidateDailyStakes(blockHeight int64) error

func RemoveDelegation

func RemoveDelegation(id int64)

func RemoveExpiredCandidateDailyStakes

func RemoveExpiredCandidateDailyStakes(blockHeight int64)

func RemoveValidator

func RemoveValidator(pubKey types.PubKey) (err error)

func ResetDeliverSqlTx

func ResetDeliverSqlTx()

func SaveAbsentValidators

func SaveAbsentValidators(store state.SimpleDB, absentValidators *AbsentValidators)

func SaveCandidate

func SaveCandidate(candidate *Candidate)

func SaveCandidateDailyStake

func SaveCandidateDailyStake(cds *CandidateDailyStake)

func SaveDelegation

func SaveDelegation(d *Delegation)

func SetDeliverSqlTx

func SetDeliverSqlTx(tx *sql.Tx)

func SetGenesisValidator

func SetGenesisValidator(val types.GenesisValidator, store state.SimpleDB) error

func SlashAbsentValidator

func SlashAbsentValidator(pubKey types.PubKey, absence *Absence, blockTime, blockHeight int64) (err error)

func SlashBadProposer

func SlashBadProposer(pubKey types.PubKey, blockTime, blockHeight int64) (err error)

func SlashByzantineValidator

func SlashByzantineValidator(pubKey types.PubKey, blockTime, blockHeight int64) (err error)

func UpdateDelegation

func UpdateDelegation(d *Delegation)

func UpdateValidatorSet

func UpdateValidatorSet(store state.SimpleDB, blockHeight int64) (change []abci.Validator, err error)

UpdateValidatorSet - Updates the voting power for the candidate set and returns the subset of validators which have changed for Tendermint

func VerifyCubeSignature

func VerifyCubeSignature(address common.Address, nonce uint64, cubeBatch string, sig string) error

Types

type Absence

type Absence struct {
	Count           int16
	LastBlockHeight int64
}

func (*Absence) Accumulate

func (a *Absence) Accumulate()

func (Absence) GetCount

func (a Absence) GetCount() int16

func (Absence) String

func (a Absence) String() string

type AbsentValidators

type AbsentValidators struct {
	Validators map[string]*Absence
}

func LoadAbsentValidators

func LoadAbsentValidators(store state.SimpleDB) *AbsentValidators

func (AbsentValidators) Add

func (av AbsentValidators) Add(pk types.PubKey, height int64)

func (AbsentValidators) Clear

func (av AbsentValidators) Clear(currentBlockHeight int64)

func (AbsentValidators) Contains

func (av AbsentValidators) Contains(pk types.PubKey) bool

func (AbsentValidators) Remove

func (av AbsentValidators) Remove(pk types.PubKey)

type AwardInfo

type AwardInfo struct {
	Address common.Address `json:"address"`
	State   string         `json:"state"`
	Amount  string         `json:"amount"`
}

type AwardInfos

type AwardInfos []AwardInfo

type Candidate

type Candidate struct {
	Id                    int64        `json:"id"`
	PubKey                types.PubKey `json:"pub_key"`                 // Pubkey of candidate
	OwnerAddress          string       `json:"owner_address"`           // Sender of BondTx - UnbondTx returns here
	Shares                string       `json:"shares"`                  // Total number of delegated shares to this candidate, equivalent to coins held in bond account
	VotingPower           int64        `json:"voting_power"`            // Voting power which is used to calculate rewards
	TendermintVotingPower int64        `json:"tendermint_voting_power"` // Tendermint Voting power which is used by tendermint
	PendingVotingPower    int64        `json:"pending_voting_power"`
	MaxShares             string       `json:"max_shares"`
	CompRate              sdk.Rat      `json:"comp_rate"`
	CreatedAt             int64        `json:"created_at"`
	Description           Description  `json:"description"`
	Verified              string       `json:"verified"`
	Active                string       `json:"active"`
	BlockHeight           int64        `json:"block_height"`
	Rank                  int64        `json:"rank"`
	State                 string       `json:"state"`
	NumOfDelegators       int64        `json:"num_of_delegators"`
}

Candidate defines the total Amount of bond shares and their exchange rate to coins. Accumulation of interest is modelled as an in increase in the exchange rate, and slashing as a decrease. When coins are delegated to this candidate, the candidate is credited with a DelegatorBond whose number of bond shares is based on the Amount of coins delegated divided by the current exchange rate. Voting power can be calculated as total bonds multiplied by exchange rate. NOTE if the Owner.Empty() == true then this is a candidate who has revoked candidacy

func GetCandidateByAddress

func GetCandidateByAddress(address common.Address) *Candidate

func GetCandidateById

func GetCandidateById(id int64) *Candidate

func GetCandidateByPubKey

func GetCandidateByPubKey(pubKey types.PubKey) *Candidate

func QueryCandidateByAddress

func QueryCandidateByAddress(address common.Address) *Candidate

func QueryCandidateById

func QueryCandidateById(id int64) *Candidate

func (*Candidate) AddShares

func (c *Candidate) AddShares(value sdk.Int) (res sdk.Int)

func (*Candidate) CalcVotingPower

func (c *Candidate) CalcVotingPower(blockHeight int64) (res int64)

func (*Candidate) Hash

func (c *Candidate) Hash() []byte

func (Candidate) IsActive

func (c Candidate) IsActive() bool

func (*Candidate) ParseMaxShares

func (c *Candidate) ParseMaxShares() sdk.Int

func (*Candidate) ParseShares

func (c *Candidate) ParseShares() sdk.Int

func (*Candidate) SelfStakingAmount

func (c *Candidate) SelfStakingAmount(ssr sdk.Rat) (res sdk.Int)

func (*Candidate) Validator

func (c *Candidate) Validator() Validator

Validator returns a copy of the Candidate as a Validator. Should only be called when the Candidate qualifies as a validator.

type CandidateAccountUpdateRequest

type CandidateAccountUpdateRequest struct {
	Id                  int64          `json:"id"`
	CandidateId         int64          `json:"candidate_id"`
	FromAddress         common.Address `json:"from_address"`
	ToAddress           common.Address `json:"to_address"`
	CreatedBlockHeight  int64          `json:"created_block_height"`
	AcceptedBlockHeight int64          `json:"accepted_block_height"`
	State               string         `json:"state"`
}

func (*CandidateAccountUpdateRequest) Hash

func (c *CandidateAccountUpdateRequest) Hash() []byte

type CandidateDailyStake

type CandidateDailyStake struct {
	Id          int64  `json:"id"`
	Amount      string `json:"amount"`
	BlockHeight int64  `json:"block_height"`
	CandidateId int64  `json:"candidate_id"`
}

func (*CandidateDailyStake) Hash

func (c *CandidateDailyStake) Hash() []byte

type Candidates

type Candidates []*Candidate

func GetActiveCandidates

func GetActiveCandidates() (candidates Candidates)

func GetBackupValidators

func GetBackupValidators() (candidates Candidates)

func GetCandidates

func GetCandidates() (candidates Candidates)

func QueryCandidates

func QueryCandidates() (candidates Candidates)

func (Candidates) Len

func (cs Candidates) Len() int

nolint - sort interface functions

func (Candidates) Less

func (cs Candidates) Less(i, j int) bool

func (Candidates) Sort

func (cs Candidates) Sort()

Sort - Sort the array of bonded values

func (Candidates) Swap

func (cs Candidates) Swap(i, j int)

func (Candidates) Validators

func (cs Candidates) Validators() Validators

Validators - get the most recent updated validator set from the Candidates. These bonds are already sorted by VotingPower from the UpdateVotingPower function which is the only function which is to modify the VotingPower

type CubePubKey

type CubePubKey struct {
	CubeBatch string `json:"cube_batch"`
	PubKey    string `json:"pub_key"`
}

type DelegateHistory

type DelegateHistory struct {
	Id               int64          `json:"id"`
	DelegatorAddress common.Address `json:"delegator_address"`
	Amount           sdk.Int        `json:"amount"`
	OpCode           string         `json:"op_code"`
	BlockHeight      int64          `json:"block_height"`
	CandidateId      int64          `json:"candidate_id"`
}

func (*DelegateHistory) Hash

func (d *DelegateHistory) Hash() []byte

type Delegation

type Delegation struct {
	Id                    int64          `json:"id"`
	DelegatorAddress      common.Address `json:"delegator_address"`
	PubKey                types.PubKey   `json:"pub_key"`
	ValidatorAddress      string         `json:"validator_address"`
	DelegateAmount        string         `json:"delegate_amount"`
	AwardAmount           string         `json:"award_amount"`
	WithdrawAmount        string         `json:"withdraw_amount"`
	PendingWithdrawAmount string         `json:"pending_withdraw_amount"`
	SlashAmount           string         `json:"slash_amount"`
	CompRate              sdk.Rat        `json:"comp_rate"`
	VotingPower           int64          `json:"voting_power"`
	CreatedAt             int64          `json:"created_at"`
	State                 string         `json:"state"`
	BlockHeight           int64          `json:"block_height"`
	AverageStakingDate    int64          `json:"average_staking_date"`
	CandidateId           int64          `json:"candidate_id"`
}

func GetDelegation

func GetDelegation(delegatorAddress common.Address, candidateId int64) *Delegation

func GetDelegations

func GetDelegations(state string) (delegations []*Delegation)

func GetDelegationsByCandidate

func GetDelegationsByCandidate(candidateId int64, state string) (delegations []*Delegation)

func QueryDelegationsByAddress

func QueryDelegationsByAddress(delegatorAddress common.Address) (delegations []*Delegation)

func (*Delegation) AccumulateAverageStakingDate

func (d *Delegation) AccumulateAverageStakingDate()

func (*Delegation) AddAwardAmount

func (d *Delegation) AddAwardAmount(value sdk.Int) (res sdk.Int)

func (*Delegation) AddDelegateAmount

func (d *Delegation) AddDelegateAmount(value sdk.Int) (res sdk.Int)

func (*Delegation) AddPendingWithdrawAmount

func (d *Delegation) AddPendingWithdrawAmount(value sdk.Int) (res sdk.Int)

func (*Delegation) AddSlashAmount

func (d *Delegation) AddSlashAmount(value sdk.Int) (res sdk.Int)

func (*Delegation) AddWithdrawAmount

func (d *Delegation) AddWithdrawAmount(value sdk.Int) (res sdk.Int)

func (*Delegation) CalcVotingPower

func (d *Delegation) CalcVotingPower(sharesPercentage sdk.Rat, blockHeight int64) int64

func (*Delegation) Hash

func (d *Delegation) Hash() []byte

func (*Delegation) ParseAwardAmount

func (d *Delegation) ParseAwardAmount() sdk.Int

func (*Delegation) ParseDelegateAmount

func (d *Delegation) ParseDelegateAmount() sdk.Int

func (*Delegation) ParsePendingWithdrawAmount

func (d *Delegation) ParsePendingWithdrawAmount() sdk.Int

func (*Delegation) ParseSlashAmount

func (d *Delegation) ParseSlashAmount() sdk.Int

func (*Delegation) ParseWithdrawAmount

func (d *Delegation) ParseWithdrawAmount() sdk.Int

func (*Delegation) ReduceAverageStakingDate

func (d *Delegation) ReduceAverageStakingDate(withdrawAmount sdk.Int)

func (*Delegation) ResetVotingPower

func (d *Delegation) ResetVotingPower()

func (*Delegation) Shares

func (d *Delegation) Shares() (res sdk.Int)

type Description

type Description struct {
	Name     string `json:"name"`
	Website  string `json:"website"`
	Location string `json:"location"`
	Email    string `json:"email"`
	Profile  string `json:"profile"`
}

type Slash

type Slash struct {
	Id          int64   `json:"id"`
	SlashRatio  sdk.Rat `json:"slash_ratio"`
	SlashAmount sdk.Int `json:"slash_amount"`
	Reason      string  `json:"reason"`
	CreatedAt   int64   `json:"created_at"`
	BlockHeight int64   `json:"block_height"`
	CandidateId int64   `json:"candidate_id"`
}

func (*Slash) Hash

func (s *Slash) Hash() []byte

type SqlTxWrapper

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

func (*SqlTxWrapper) Commit

func (wrapper *SqlTxWrapper) Commit()

func (*SqlTxWrapper) Rollback

func (wrapper *SqlTxWrapper) Rollback()

type TxAcceptCandidacyAccountUpdate

type TxAcceptCandidacyAccountUpdate struct {
	AccountUpdateRequestId int64 `json:"account_update_request_id"`
}

func (TxAcceptCandidacyAccountUpdate) ValidateBasic

func (tx TxAcceptCandidacyAccountUpdate) ValidateBasic() error

func (TxAcceptCandidacyAccountUpdate) Wrap

Wrap - Wrap a Tx as a Travis Tx

type TxActivateCandidacy

type TxActivateCandidacy struct{}

func (TxActivateCandidacy) ValidateBasic

func (tx TxActivateCandidacy) ValidateBasic() error

ValidateBasic - Check for non-empty candidate, and valid coins

func (TxActivateCandidacy) Wrap

func (tx TxActivateCandidacy) Wrap() sdk.Tx

Wrap - Wrap a Tx as a Basecoin Tx

type TxDeactivateCandidacy

type TxDeactivateCandidacy struct{}

func (TxDeactivateCandidacy) ValidateBasic

func (tx TxDeactivateCandidacy) ValidateBasic() error

ValidateBasic - Check for non-empty candidate, and valid coins

func (TxDeactivateCandidacy) Wrap

func (tx TxDeactivateCandidacy) Wrap() sdk.Tx

Wrap - Wrap a Tx as a Basecoin Tx

type TxDeclareCandidacy

type TxDeclareCandidacy struct {
	PubKey      string      `json:"pub_key"`
	MaxAmount   string      `json:"max_amount"`
	CompRate    sdk.Rat     `json:"comp_rate"`
	Description Description `json:"description"`
}

func (TxDeclareCandidacy) SelfStakingAmount

func (tx TxDeclareCandidacy) SelfStakingAmount(ssr sdk.Rat) (res sdk.Int)

func (TxDeclareCandidacy) ValidateBasic

func (tx TxDeclareCandidacy) ValidateBasic() error

func (TxDeclareCandidacy) Wrap

func (tx TxDeclareCandidacy) Wrap() sdk.Tx

type TxDelegate

type TxDelegate struct {
	ValidatorAddress common.Address `json:"validator_address"`
	Amount           string         `json:"amount"`
	CubeBatch        string         `json:"cube_batch"`
	Sig              string         `json:"sig"`
}

TxDelegate - struct for bonding or unbonding transactions

func (TxDelegate) ValidateBasic

func (tx TxDelegate) ValidateBasic() error

func (TxDelegate) Wrap

func (tx TxDelegate) Wrap() sdk.Tx

Wrap - Wrap a Tx as a Travis Tx

type TxSetCompRate

type TxSetCompRate struct {
	DelegatorAddress common.Address `json:"delegator_address"`
	CompRate         sdk.Rat        `json:"comp_rate"`
}

func (TxSetCompRate) ValidateBasic

func (tx TxSetCompRate) ValidateBasic() error

func (TxSetCompRate) Wrap

func (tx TxSetCompRate) Wrap() sdk.Tx

Wrap - Wrap a Tx as a Travis Tx

type TxUpdateCandidacy

type TxUpdateCandidacy struct {
	PubKey      string      `json:"pub_key"`
	MaxAmount   string      `json:"max_amount"`
	CompRate    sdk.Rat     `json:"comp_rate"`
	Description Description `json:"description"`
}

func (TxUpdateCandidacy) ValidateBasic

func (tx TxUpdateCandidacy) ValidateBasic() error

func (TxUpdateCandidacy) Wrap

func (tx TxUpdateCandidacy) Wrap() sdk.Tx

type TxUpdateCandidacyAccount

type TxUpdateCandidacyAccount struct {
	NewCandidateAddress common.Address `json:"new_candidate_account"`
}

func (TxUpdateCandidacyAccount) ValidateBasic

func (tx TxUpdateCandidacyAccount) ValidateBasic() error

func (TxUpdateCandidacyAccount) Wrap

func (tx TxUpdateCandidacyAccount) Wrap() sdk.Tx

Wrap - Wrap a Tx as a Travis Tx

type TxVerifyCandidacy

type TxVerifyCandidacy struct {
	CandidateAddress common.Address `json:"candidate_address"`
	Verified         bool           `json:"verified"`
}

func (TxVerifyCandidacy) ValidateBasic

func (tx TxVerifyCandidacy) ValidateBasic() error

ValidateBasic - Check for non-empty candidate, and valid coins

func (TxVerifyCandidacy) Wrap

func (tx TxVerifyCandidacy) Wrap() sdk.Tx

Wrap - Wrap a Tx as a Basecoin Tx

type TxWithdraw

type TxWithdraw struct {
	ValidatorAddress common.Address `json:"validator_address"`
	Amount           string         `json:"amount"`
}

func (TxWithdraw) ValidateBasic

func (tx TxWithdraw) ValidateBasic() error

func (TxWithdraw) Wrap

func (tx TxWithdraw) Wrap() sdk.Tx

Wrap - Wrap a Tx as a Travis Tx

type TxWithdrawCandidacy

type TxWithdrawCandidacy struct{}

func (TxWithdrawCandidacy) ValidateBasic

func (tx TxWithdrawCandidacy) ValidateBasic() error

ValidateBasic - Check for non-empty candidate, and valid coins

func (TxWithdrawCandidacy) Wrap

func (tx TxWithdrawCandidacy) Wrap() sdk.Tx

Wrap - Wrap a Tx as a Basecoin Tx

type UnstakeRequest

type UnstakeRequest struct {
	Id                   int64          `json:"id"`
	DelegatorAddress     common.Address `json:"delegator_address"`
	InitiatedBlockHeight int64          `json:"initiated_block_height"`
	PerformedBlockHeight int64          `json:"performed_block_height"`
	Amount               string         `json:"amount"`
	State                string         `json:"state"`
	CandidateId          int64          `json:"candidate_id"`
}

func GetUnstakeRequests

func GetUnstakeRequests(height int64) (reqs []*UnstakeRequest)

func GetUnstakeRequestsByDelegator

func GetUnstakeRequestsByDelegator(delegatorAddress common.Address) []*UnstakeRequest

func (*UnstakeRequest) Hash

func (r *UnstakeRequest) Hash() []byte

type Validator

type Validator Candidate

Validator is one of the top Candidates

func (Validator) ABCIValidator

func (v Validator) ABCIValidator() abci.Validator

ABCIValidator - Get the validator from a bond value

type Validators

type Validators []Validator

Validators - list of Validators

func (Validators) Contains

func (vs Validators) Contains(pk types.PubKey) bool

func (Validators) Deactivate

func (vs Validators) Deactivate()

Deactivate the validators

func (Validators) Len

func (vs Validators) Len() int

nolint - sort interface functions

func (Validators) Less

func (vs Validators) Less(i, j int) bool

func (Validators) Remove

func (vs Validators) Remove(i int) Validators

func (Validators) Sort

func (vs Validators) Sort()

Sort - Sort validators by pubkey

func (Validators) Swap

func (vs Validators) Swap(i, j int)

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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