utils

package
v0.9.1 Latest Latest
Warning

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

Go to latest
Published: Jun 13, 2018 License: LGPL-3.0 Imports: 37 Imported by: 39

Documentation

Index

Constants

View Source
const (
	DEFAULT_COMPRESS_TYPE         = COMPRESS_TYPE_ZLIB
	EXPORT_BLOCK_METADATA_LEN     = 256
	EXPORT_BLOCK_METADATA_VERSION = 1
)
View Source
const (
	VERSION_TRANSACTION    = byte(0)
	VERSION_CONTRACT_ONT   = byte(0)
	VERSION_CONTRACT_ONG   = byte(0)
	CONTRACT_TRANSFER      = "transfer"
	CONTRACT_TRANSFER_FROM = "transferFrom"
	CONTRACT_APPROVE       = "approve"

	ASSET_ONT = "ont"
	ASSET_ONG = "ong"
)
View Source
const (
	PARAMS_SPLIT          = ","
	PARAM_TYPE_SPLIT      = ":"
	PARAM_TYPE_ARRAY      = "array"
	PARAM_TYPE_BYTE_ARRAY = "bytearray"
	PARAM_TYPE_STRING     = "string"
	PARAM_TYPE_INTEGER    = "int"
	PARAM_TYPE_BOOLEAN    = "bool"
	PARAM_LEFT_BRACKET    = "["
	PARAM_RIGHT_BRACKET   = "]"
)
View Source
const (
	PRECISION_ONG = 9
	PRECISION_ONT = 0
)
View Source
const (
	COMPRESS_TYPE_ZLIB = iota
)
View Source
const (
	DEFAULT_EXPORT_FILE = "./blocks.dat"
)
View Source
const JSON_RPC_VERSION = "2.0"

JsonRpc version

Variables

View Source
var (
	//Ontology setting
	ConfigFlag = cli.StringFlag{
		Name:  "config",
		Usage: "Use `<filename>` as the genesis config file. Using Polaris config with VBFT consensus as default, if not set config flag.",
	}
	LogLevelFlag = cli.UintFlag{
		Name:  "loglevel",
		Usage: "Set the log level to `<level>` (0~6). 0:Debug 1:Info 2:Warn 3:Error 4:Fatal 5:Trace 6:MaxLevel",
		Value: config.DEFAULT_LOG_LEVEL,
	}
	DisableEventLogFlag = cli.BoolFlag{
		Name:  "disableeventlog",
		Usage: "If set disableeventlog flag, will not record event log output by smart contract",
	}
	WalletFileFlag = cli.StringFlag{
		Name:  "wallet,w",
		Value: config.DEFAULT_WALLET_FILE_NAME,
		Usage: "Use `<filename>` as the wallet",
	}
	ImportEnableFlag = cli.BoolFlag{
		Name:  "import",
		Usage: "Import blocks for file",
	}
	ImportFileFlag = cli.StringFlag{
		Name:  "importfile",
		Usage: "Path of import file",
		Value: DEFAULT_EXPORT_FILE,
	}
	ImportHeightFlag = cli.UintFlag{
		Name:  "importheight",
		Usage: "Import target block height, if not specified, import all of blocks in files",
	}
	DataDirFlag = cli.StringFlag{
		Name:  "datadir",
		Usage: "Using dir `<path>` to save block data",
		Value: config.DEFAULT_DATA_DIR,
	}

	//Consensus setting
	DisableConsensusFlag = cli.BoolFlag{
		Name:  "disableconsensus",
		Usage: "If set disableconsensus, will not start consensus module",
	}
	MaxTxInBlockFlag = cli.IntFlag{
		Name:  "maxtxinblock",
		Usage: "Max transaction number in block",
		Value: config.DEFAULT_MAX_TX_IN_BLOCK,
	}
	GasLimitFlag = cli.Uint64Flag{
		Name:  "gaslimit",
		Usage: "The gas limit required by the transaction pool for a new transaction",
		Value: config.DEFAULT_GAS_LIMIT,
	}
	GasPriceFlag = cli.Uint64Flag{
		Name:  "gasprice",
		Usage: "The gas price enforced by the transaction pool for a new transaction",
		Value: config.DEFAULT_GAS_PRICE,
	}

	//Test Mode setting
	EnableTestModeFlag = cli.BoolFlag{
		Name:  "testmode",
		Usage: "Runin test mode will start solo consensus. If enable testmode flag, ontology will ignore the consensus type config in genesis",
	}
	TestModeGenBlockTimeFlag = cli.UintFlag{
		Name:  "testmodegenblocktime",
		Usage: "Interval of generate block in test mode, unit(s)",
		Value: config.DEFAULT_GEN_BLOCK_TIME,
	}

	//P2P setting
	NetworkIdFlag = cli.UintFlag{
		Name:  "networkid",
		Usage: "P2P network id",
		Value: config.DEFAULT_NET_MAGIC,
	}
	NodePortFlag = cli.UintFlag{
		Name:  "nodeport",
		Usage: "P2P node listening port",
		Value: config.DEFAULT_NODE_PORT,
	}
	DualPortSupportFlag = cli.BoolFlag{
		Name:  "dualport",
		Usage: "Enable dual port support. Means p2p node port difference with consensus port",
	}
	ConsensusPortFlag = cli.UintFlag{
		Name:  "consensusport",
		Usage: "Consensus listening port",
		Value: config.DEFAULT_CONSENSUS_PORT,
	}

	// RPC settings
	RPCDisabledFlag = cli.BoolFlag{
		Name:  "disablerpc",
		Usage: "Disable Json rpc server",
	}
	RPCPortFlag = cli.UintFlag{
		Name:  "rpcport",
		Usage: "Json rpc server listening port",
		Value: config.DEFAULT_RPC_PORT,
	}
	RPCLocalEnableFlag = cli.BoolFlag{
		Name:  "localrpc",
		Usage: "Enable local rpc server",
	}
	RPCLocalProtFlag = cli.UintFlag{
		Name:  "rpclocalport",
		Usage: "Json rpc local server listening port",
		Value: config.DEFAULT_RPC_LOCAL_PORT,
	}

	//Websocket setting
	WsEnabledFlag = cli.BoolFlag{
		Name:  "ws",
		Usage: "Enable websocket server",
	}
	WsPortFlag = cli.UintFlag{
		Name:  "wsport",
		Usage: "Ws server listening port",
		Value: config.DEFAULT_WS_PORT,
	}

	//Restful setting
	RestfulEnableFlag = cli.BoolFlag{
		Name:  "rest",
		Usage: "Enable restful api server",
	}
	RestfulPortFlag = cli.UintFlag{
		Name:  "restport",
		Usage: "Restful server listening port",
		Value: config.DEFAULT_REST_PORT,
	}

	//Account setting
	AccountPassFlag = cli.StringFlag{
		Name:   "password,p",
		Hidden: true,
		Usage:  "Specifies `<password>` for the account",
	}
	AccountAddressFlag = cli.StringFlag{
		Name:  "account,a",
		Usage: "Address of account. Address can be `<address>` in base58 code , label or index. if not specific, will use default account",
	}
	AccountDefaultFlag = cli.BoolFlag{
		Name:  "default,d",
		Usage: "Use default settings (equal to '-t ecdsa -b 256 -s SHA256withECDSA')",
	}
	AccountTypeFlag = cli.StringFlag{
		Name:  "type,t",
		Usage: "Specifies the `<key-type>` by signature algorithm.",
	}
	AccountKeylenFlag = cli.StringFlag{
		Name:  "bit-length,b",
		Usage: "Specifies the `<bit-length>` of key",
	}
	AccountSigSchemeFlag = cli.StringFlag{
		Name:  "signature-scheme,s",
		Usage: "Specifies the signature scheme `<scheme>`",
	}
	AccountSetDefaultFlag = cli.BoolFlag{
		Name:  "as-default,d",
		Usage: "Set the specified account to default",
	}
	AccountQuantityFlag = cli.UintFlag{
		Name:  "number,n",
		Value: 1,
		Usage: "Specifies the `<quantity>` of account to create.",
	}
	AccountSourceFileFlag = cli.StringFlag{
		Name:  "source,s",
		Usage: "Use `<filename>` as the source wallet file to import",
	}
	AccountLabelFlag = cli.StringFlag{
		Name:  "label,l",
		Usage: "Use `<label>` for the account",
	}
	AccountKeyFlag = cli.StringFlag{
		Name:  "key,k",
		Usage: "Use `<private key(hex encoding)>` of the account",
	}
	AccountVerboseFlag = cli.BoolFlag{
		Name:  "verbose,v",
		Usage: "Display accounts with details",
	}
	AccountChangePasswdFlag = cli.BoolFlag{
		Name:  "changepasswd",
		Usage: "Change account password",
	}
	AccountLowSecurityFlag = cli.BoolFlag{
		Name:  "low-security",
		Usage: "Change account to low protection strength for low performance devices",
	}
	AccountWIFFlag = cli.BoolFlag{
		Name:  "wif",
		Usage: "Import WIF keys from the source file specified by --source option",
	}

	//SmartContract setting
	ContractAddrFlag = cli.StringFlag{
		Name:  "address",
		Usage: "Contract address",
	}
	ContractStorageFlag = cli.BoolFlag{
		Name:  "needstore",
		Usage: "Is need use store in contract",
	}
	ContractCodeFileFlag = cli.StringFlag{
		Name:  "code",
		Usage: "File path of contract code `<path>`",
	}
	ContractNameFlag = cli.StringFlag{
		Name:  "name",
		Usage: "Specifies contract name to `<name>`",
	}
	ContractVersionFlag = cli.IntFlag{
		Name:  "version",
		Usage: "Specifies contract version to `<ver>`",
	}
	ContractAuthorFlag = cli.StringFlag{
		Name:  "author",
		Usage: "Set `<address>` as the contract owner",
		Value: "",
	}
	ContractEmailFlag = cli.StringFlag{
		Name:  "email",
		Usage: "Set `<email>` owner's email address",
		Value: "",
	}
	ContractDescFlag = cli.StringFlag{
		Name:  "desc",
		Usage: "Set `<text>` as the description of the contract",
		Value: "",
	}
	ContractParamsFlag = cli.StringFlag{
		Name:  "params",
		Usage: "Invoke contract parameters list. use comma ',' to split params, and must add type prefix to params. Param type support bytearray(hexstring), string, integer, boolean,For example: string:foo,int:0,bool:true; If parameter is an object array, enclose array with '[]'. For example:  string:foo,[int:0,bool:true]",
	}
	ContractPrepareInvokeFlag = cli.BoolFlag{
		Name:  "prepare,p",
		Usage: "Prepare invoke contract without commit to ledger",
	}
	ContranctReturnTypeFlag = cli.StringFlag{
		Name:  "return",
		Usage: "Return type of contract.Return type support bytearray(hexstring), string, integer, boolean. If return type is object array, enclose array with '[]'. For example [string,int,bool,string]. Only prepare invoke need this flag.",
	}

	//information cmd settings
	BlockHashInfoFlag = cli.StringFlag{
		Name:  "hash",
		Usage: "Get block info by block hash",
	}
	BlockHeightInfoFlag = cli.UintFlag{
		Name:  "height",
		Usage: "Get block info by block height",
	}

	//Transfer setting
	TransactionAssetFlag = cli.StringFlag{
		Name:  "asset",
		Usage: "Asset to transfer `<ont|ong>`",
		Value: ASSET_ONT,
	}
	TransactionFromFlag = cli.StringFlag{
		Name:  "from",
		Usage: "`<address>` which sends the asset. address also can be index, label",
	}
	TransactionToFlag = cli.StringFlag{
		Name:  "to",
		Usage: "`<address>` which receives the asset",
	}
	TransactionAmountFlag = cli.StringFlag{
		Name:  "amount",
		Usage: "Specifies `<amount>` as the transferred amount",
	}
	TransactionHashFlag = cli.StringFlag{
		Name:  "hash",
		Usage: "Transaction <hash>",
	}
	TransactionGasPriceFlag = cli.Uint64Flag{
		Name:  "gasprice",
		Usage: "Gas price of transaction",
		Value: 0,
	}
	TransactionGasLimitFlag = cli.Uint64Flag{
		Name:  "gaslimit",
		Usage: "Gas limit of tansaction",
		Value: neovm.TRANSACTION_GAS,
	}

	//Asset setting
	ApproveAssetFromFlag = cli.StringFlag{
		Name:  "from",
		Usage: "Approve from address",
	}
	ApproveAssetToFlag = cli.StringFlag{
		Name:  "to",
		Usage: "Approve to address",
	}
	ApproveAssetFlag = cli.StringFlag{
		Name:  "asset",
		Usage: "Approve asset <ont|ong>",
		Value: "ont",
	}
	ApproveAmountFlag = cli.StringFlag{
		Name:  "amount",
		Usage: "Approve amount",
	}
	TransferFromAmountFlag = cli.StringFlag{
		Name:  "amount",
		Usage: "Transfer from amount",
	}
	TransferFromSenderFlag = cli.StringFlag{
		Name:  "sender",
		Usage: "Sender of transfer from transaction, if empty sender is to address",
	}

	//Cli setting
	CliEnableRpcFlag = cli.BoolFlag{
		Name:  "clirpc",
		Usage: "Enable cli rpc",
	}
	CliRpcPortFlag = cli.UintFlag{
		Name:  "cliport",
		Usage: "Cli rpc port",
		Value: config.DEFAULT_CLI_RPC_PORT,
	}

	//Export setting
	ExportFileFlag = cli.StringFlag{
		Name:  "file",
		Usage: "Path of export file",
		Value: DEFAULT_EXPORT_FILE,
	}
	ExportHeightFlag = cli.UintFlag{
		Name:  "height",
		Usage: "End block height to export, if height equal 0, mean export all block in current DB",
		Value: 0,
	}
	ExportSpeedFlag = cli.StringFlag{
		Name:  "speed",
		Usage: "Export block speed, <h|m|l>",
		Value: "m",
	}

	NonOptionFlag = cli.StringFlag{
		Name:  "option",
		Usage: "this command does not need option, please run directly",
	}
)

Functions

func Approve

func Approve(gasPrice, gasLimit uint64, signer *account.Account, asset, from, to string, amount uint64) (string, error)

func ApproveTx

func ApproveTx(gasPrice, gasLimit uint64, asset string, from, to string, amount uint64) (*types.Transaction, error)

func BuildWasmVMInvokeCode

func BuildWasmVMInvokeCode(smartcodeAddress common.Address, methodName string, paramType wasmvm.ParamType, version byte, params []interface{}) ([]byte, error)

BuildWasmVMInvokeCode return wasn vm invoke code

func CompressBlockData

func CompressBlockData(data []byte, compressType byte) ([]byte, error)

func DecompressBlockData

func DecompressBlockData(data []byte, compressType byte) ([]byte, error)

func DeployContract

func DeployContract(
	gasPrice,
	gasLimit uint64,
	signer *account.Account,
	needStorage bool,
	code,
	cname,
	cversion,
	cauthor,
	cemail,
	cdesc string) (string, error)

func FormatAssetAmount

func FormatAssetAmount(amount uint64, precision byte) string

FormatAssetAmount return asset amount multiplied by math.Pow10(precision) to raw float string For example 1000000000123456789 => 1000000000.123456789

func FormatOng

func FormatOng(amount uint64) string

func FormatOnt

func FormatOnt(amount uint64) string

func GetAllowance

func GetAllowance(asset, from, to string) (string, error)

func GetBalance

func GetBalance(address string) (*httpcom.BalanceOfRsp, error)

Return balance of address in base58 code

func GetBlock

func GetBlock(hashOrHeight interface{}) ([]byte, error)

func GetBlockCount

func GetBlockCount() (uint32, error)

func GetBlockData

func GetBlockData(hashOrHeight interface{}) ([]byte, error)

func GetFlagName

func GetFlagName(flag cli.Flag) string

GetFlagName deal with short flag, and return the flag name whether flag name have short name

func GetRawTransaction

func GetRawTransaction(txHash string) ([]byte, error)

func GetSmartContractEvent

func GetSmartContractEvent(txHash string) (*rpccommon.ExecuteNotify, error)

GetSmartContractEvent return smart contract event execute by invoke transaction by hex string code

func GetSmartContractEventInfo

func GetSmartContractEventInfo(txHash string) ([]byte, error)

func ImportBlocks

func ImportBlocks(importFile string, targetHeight uint32) error

func InvokeNativeContract

func InvokeNativeContract(
	gasPrice,
	gasLimit uint64,
	signer *account.Account,
	contractAddress common.Address,
	version byte,
	method string,
	params []interface{},
) (string, error)

func InvokeNeoVMContract

func InvokeNeoVMContract(
	gasPrice,
	gasLimit uint64,
	signer *account.Account,
	smartcodeAddress common.Address,
	params []interface{}) (string, error)

Invoke neo vm smart contract. if isPreExec is true, the invoke will not really execute

func InvokeSmartContract

func InvokeSmartContract(signer *account.Account, tx *types.Transaction) (string, error)

InvokeSmartContract is low level method to invoke contact.

func InvokeWasmVMContract

func InvokeWasmVMContract(
	gasPrice,
	gasLimit uint64,
	siger *account.Account,
	cversion byte,
	contractAddress common.Address,
	method string,
	paramType wasmvm.ParamType,
	params []interface{}) (string, error)

Invoke wasm smart contract methodName is wasm contract action name paramType is Json or Raw format version should be greater than 0 (0 is reserved for test)

func NewDeployCodeTransaction

func NewDeployCodeTransaction(gasPrice, gasLimit uint64, code []byte, needStorage bool,
	cname, cversion, cauthor, cemail, cdesc string) *types.Transaction

NewDeployCodeTransaction return a smart contract deploy transaction instance

func NewNativeInvokeTransaction

func NewNativeInvokeTransaction(gasPrice, gasLimit uint64, contractAddr common.Address, version byte, params []interface{}, funcAbi *abi.NativeContractFunctionAbi) (*types.Transaction, error)

func ParseAssetAmount

func ParseAssetAmount(rawAmount string, precision byte) uint64

ParseAssetAmount return raw float string to uint64 multiplied by math.Pow10(precision) For example 1000000000.123456789 => 1000000000123456789

func ParseNativeFuncParam

func ParseNativeFuncParam(builder *neovm.ParamsBuilder, funName string, params []interface{}, paramsAbi []*abi.NativeContractParamAbi) error

func ParseNativeParamAddress

func ParseNativeParamAddress(builder *neovm.ParamsBuilder, param string) error

func ParseNativeParamArray

func ParseNativeParamArray(builder *neovm.ParamsBuilder, param interface{}, arrayAbi *abi.NativeContractParamAbi) error

func ParseNativeParamBool

func ParseNativeParamBool(builder *neovm.ParamsBuilder, param string) error

func ParseNativeParamByte

func ParseNativeParamByte(builder *neovm.ParamsBuilder, param string) error

func ParseNativeParamByteArray

func ParseNativeParamByteArray(builder *neovm.ParamsBuilder, param string) error

func ParseNativeParamInteger

func ParseNativeParamInteger(builder *neovm.ParamsBuilder, param string) error

func ParseNativeParamString

func ParseNativeParamString(builder *neovm.ParamsBuilder, param string) error

func ParseNativeParamStruct

func ParseNativeParamStruct(builder *neovm.ParamsBuilder, param interface{}, structAbi *abi.NativeContractParamAbi) error

func ParseNativeParamUint256

func ParseNativeParamUint256(builder *neovm.ParamsBuilder, param string) error

func ParseNativeParams

func ParseNativeParams(builder *neovm.ParamsBuilder, params []interface{}, paramsAbi []*abi.NativeContractParamAbi) error

func ParseNeoVMContractReturnTypeBool

func ParseNeoVMContractReturnTypeBool(hexStr string) (bool, error)

ParseNeoVMContractReturnTypeBool return bool value of smart contract execute code.

func ParseNeoVMContractReturnTypeByteArray

func ParseNeoVMContractReturnTypeByteArray(hexStr string) (string, error)

ParseNeoVMContractReturnTypeByteArray return []byte value of smart contract execute code.

func ParseNeoVMContractReturnTypeInteger

func ParseNeoVMContractReturnTypeInteger(hexStr string) (int64, error)

ParseNeoVMContractReturnTypeInteger return integer value of smart contract execute code.

func ParseNeoVMContractReturnTypeString

func ParseNeoVMContractReturnTypeString(hexStr string) (string, error)

ParseNeoVMContractReturnTypeString return string value of smart contract execute code.

func ParseNeoVMInvokeParams

func ParseNeoVMInvokeParams(rawParams []interface{}) ([]interface{}, error)

ParseNeoVMInvokeParams parse params to []interface, rawParams is array of NeoVMInvokeParam

func ParseOng

func ParseOng(rawAmount string) uint64

func ParseOnt

func ParseOnt(rawAmount string) uint64

func ParseParams

func ParseParams(rawParamStr string) ([]interface{}, error)

ParseParams return interface{} array of encode params item. A param item compose of type and value, type can be: bytearray, string, int, bool Param type and param value split with ":", such as int:10 Param array can be express with "[]", such [int:10,string:foo], param array can be nested, such as [int:10,[int:12,bool:true]] A raw params example: string:foo,[int:0,[bool:true,string:bar],bool:false]

func ParseReturnValue

func ParseReturnValue(rawValue interface{}, rawReturnTypeStr string) ([]interface{}, error)

ParseReturnValue return the value of rawReturnTypeStr type. Return type can be: bytearray, string, int, bool. Types can be split with "," each other, such as int,string,bool Type array can be express with "[]", such [int,string], param array can be nested, such as [int,[int,bool]]

func PrepareInvokeCodeNeoVMContract

func PrepareInvokeCodeNeoVMContract(code []byte) (*cstates.PreExecResult, error)

func PrepareInvokeNativeContract

func PrepareInvokeNativeContract(
	contractAddress common.Address,
	version byte,
	method string,
	params []interface{}) (*cstates.PreExecResult, error)

func PrepareInvokeNeoVMContract

func PrepareInvokeNeoVMContract(
	contractAddress common.Address,
	params []interface{},
) (*cstates.PreExecResult, error)

func SendRawTransaction

func SendRawTransaction(tx *types.Transaction) (string, error)

SendRawTransaction send a transaction to ontology network, and return hash of the transaction

func Sign

func Sign(data []byte, signer *account.Account) ([]byte, error)

Sign sign return the signature to the data of private key

func SignTransaction

func SignTransaction(signer *account.Account, tx *types.Transaction) error

func Transfer

func Transfer(gasPrice, gasLimit uint64, signer *account.Account, asset, from, to string, amount uint64) (string, error)

Transfer ont|ong from account to another account

func TransferFrom

func TransferFrom(gasPrice, gasLimit uint64, signer *account.Account, asset, sender, from, to string, amount uint64) (string, error)

func TransferFromTx

func TransferFromTx(gasPrice, gasLimit uint64, asset, sender, from, to string, amount uint64) (*types.Transaction, error)

func TransferTx

func TransferTx(gasPrice, gasLimit uint64, asset, from, to string, amount uint64) (*types.Transaction, error)

func ZLibCompress

func ZLibCompress(data []byte) ([]byte, error)

func ZLibDecompress

func ZLibDecompress(data []byte) ([]byte, error)

Types

type ExportBlockMetadata

type ExportBlockMetadata struct {
	Version      byte
	CompressType byte
	BlockHeight  uint32
}

func NewExportBlockMetadata

func NewExportBlockMetadata() *ExportBlockMetadata

func (*ExportBlockMetadata) Deserialize

func (this *ExportBlockMetadata) Deserialize(r io.Reader) error

func (*ExportBlockMetadata) Serialize

func (this *ExportBlockMetadata) Serialize(w io.Writer) error

type JsonRpcRequest

type JsonRpcRequest struct {
	Version string        `json:"jsonrpc"`
	Id      string        `json:"id"`
	Method  string        `json:"method"`
	Params  []interface{} `json:"params"`
}

JsonRpcRequest object in rpc

type JsonRpcResponse

type JsonRpcResponse struct {
	Error  int64           `json:"error"`
	Desc   string          `json:"desc"`
	Result json.RawMessage `json:"result"`
}

JsonRpcResponse object response for JsonRpcRequest

type NeoVMInvokeParam

type NeoVMInvokeParam struct {
	Type  string
	Value interface{} //string or []*NeoVMInvokeParam
}

NeoVMInvokeParam use to express the param to invoke neovm contract. Type can be of array, bytearray, string, int and bool If type is one of bytearray, string, int and bool, value must be a string If Type is array, value must be []*NeoVMInvokeParam Example:

[]interface{}{
	&NeoVMInvokeParam{
		Type:  "string",
		Value: "foo",
	},
	&NeoVMInvokeParam{
		Type: "array",
		Value: []interface{}{
			&NeoVMInvokeParam{
				Type:  "int",
				Value: "0",
			},
			&NeoVMInvokeParam{
				Type:  "bool",
				Value: "true",
			},
		},
	},
}

Jump to

Keyboard shortcuts

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