forked from cerc-io/laconicd-deprecated
export funcs for AragonChain (#423)
* export funcs for AragonChain * update comments
This commit is contained in:
parent
9a79bcc4f5
commit
241fb2fe83
63
client/config.go
Normal file
63
client/config.go
Normal file
@ -0,0 +1,63 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/big"
|
||||
"os"
|
||||
"path"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client/flags"
|
||||
"github.com/tendermint/tendermint/libs/cli"
|
||||
)
|
||||
|
||||
// InitConfig adds the chain-id, encoding and output flags to the persistent flag set.
|
||||
func InitConfig(cmd *cobra.Command) error {
|
||||
home, err := cmd.PersistentFlags().GetString(cli.HomeFlag)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
configFile := path.Join(home, "config", "config.toml")
|
||||
if _, err := os.Stat(configFile); err == nil {
|
||||
viper.SetConfigFile(configFile)
|
||||
|
||||
if err := viper.ReadInConfig(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if err := viper.BindPFlag(flags.FlagChainID, cmd.PersistentFlags().Lookup(flags.FlagChainID)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := viper.BindPFlag(cli.EncodingFlag, cmd.PersistentFlags().Lookup(cli.EncodingFlag)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return viper.BindPFlag(cli.OutputFlag, cmd.PersistentFlags().Lookup(cli.OutputFlag))
|
||||
}
|
||||
|
||||
// ValidateChainID wraps a cobra command with a RunE function with base 10 integer chain-id verification.
|
||||
func ValidateChainID(baseCmd *cobra.Command) *cobra.Command {
|
||||
// Copy base run command to be used after chain verification
|
||||
baseRunE := baseCmd.RunE
|
||||
|
||||
// Function to replace command's RunE function
|
||||
validateFn := func(cmd *cobra.Command, args []string) error {
|
||||
chainIDFlag := viper.GetString(flags.FlagChainID)
|
||||
|
||||
// Verify that the chain-id entered is a base 10 integer
|
||||
_, ok := new(big.Int).SetString(chainIDFlag, 10)
|
||||
if !ok {
|
||||
return fmt.Errorf("invalid chainID: %s, must be base-10 integer format", chainIDFlag)
|
||||
}
|
||||
|
||||
return baseRunE(cmd, args)
|
||||
}
|
||||
|
||||
baseCmd.RunE = validateFn
|
||||
return baseCmd
|
||||
}
|
80
client/export.go
Normal file
80
client/export.go
Normal file
@ -0,0 +1,80 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
ethcrypto "github.com/ethereum/go-ethereum/crypto"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client/flags"
|
||||
"github.com/cosmos/cosmos-sdk/client/input"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/keyring"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
|
||||
emintcrypto "github.com/cosmos/ethermint/crypto"
|
||||
)
|
||||
|
||||
// UnsafeExportEthKeyCommand exports a key with the given name as a private key in hex format.
|
||||
func UnsafeExportEthKeyCommand() *cobra.Command {
|
||||
return &cobra.Command{
|
||||
Use: "unsafe-export-eth-key [name]",
|
||||
Short: "**UNSAFE** Export an Ethereum private key",
|
||||
Long: `**UNSAFE** Export an Ethereum private key unencrypted to use in dev tooling`,
|
||||
Args: cobra.ExactArgs(1),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
inBuf := bufio.NewReader(cmd.InOrStdin())
|
||||
|
||||
kb, err := keyring.NewKeyring(
|
||||
sdk.KeyringServiceName(),
|
||||
viper.GetString(flags.FlagKeyringBackend),
|
||||
viper.GetString(flags.FlagHome),
|
||||
inBuf,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
decryptPassword := ""
|
||||
conf := true
|
||||
keyringBackend := viper.GetString(flags.FlagKeyringBackend)
|
||||
switch keyringBackend {
|
||||
case keyring.BackendFile:
|
||||
decryptPassword, err = input.GetPassword(
|
||||
"**WARNING this is an unsafe way to export your unencrypted private key**\nEnter key password:",
|
||||
inBuf)
|
||||
case keyring.BackendOS:
|
||||
conf, err = input.GetConfirmation(
|
||||
"**WARNING** this is an unsafe way to export your unencrypted private key, are you sure?",
|
||||
inBuf)
|
||||
}
|
||||
if err != nil || !conf {
|
||||
return err
|
||||
}
|
||||
|
||||
// Exports private key from keybase using password
|
||||
privKey, err := kb.ExportPrivateKeyObject(args[0], decryptPassword)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Converts key to Ethermint secp256 implementation
|
||||
emintKey, ok := privKey.(emintcrypto.PrivKeySecp256k1)
|
||||
if !ok {
|
||||
return fmt.Errorf("invalid private key type, must be Ethereum key: %T", privKey)
|
||||
}
|
||||
|
||||
// Formats key for output
|
||||
privB := ethcrypto.FromECDSA(emintKey.ToECDSA())
|
||||
keyS := strings.ToUpper(hexutil.Encode(privB)[2:])
|
||||
|
||||
fmt.Println(keyS)
|
||||
|
||||
return nil
|
||||
},
|
||||
}
|
||||
}
|
@ -1,27 +1,27 @@
|
||||
package main
|
||||
package client
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"io"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client/flags"
|
||||
clientkeys "github.com/cosmos/cosmos-sdk/client/keys"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/keyring"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
|
||||
"github.com/cosmos/ethermint/crypto"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
const (
|
||||
flagDryRun = "dry-run"
|
||||
)
|
||||
|
||||
// keyCommands registers a sub-tree of commands to interact with
|
||||
// KeyCommands registers a sub-tree of commands to interact with
|
||||
// local private key storage.
|
||||
func keyCommands() *cobra.Command {
|
||||
func KeyCommands() *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "keys",
|
||||
Short: "Add or view local private keys",
|
||||
@ -31,8 +31,11 @@ func keyCommands() *cobra.Command {
|
||||
used by light-clients, full nodes, or any other application that
|
||||
needs to sign with a private key.`,
|
||||
}
|
||||
|
||||
// support adding Ethereum supported keys
|
||||
addCmd := clientkeys.AddKeyCommand()
|
||||
addCmd.RunE = runAddCmd
|
||||
|
||||
cmd.AddCommand(
|
||||
clientkeys.MnemonicKeyCommand(),
|
||||
addCmd,
|
||||
@ -45,11 +48,21 @@ func keyCommands() *cobra.Command {
|
||||
clientkeys.ParseKeyStringCommand(),
|
||||
clientkeys.MigrateCommand(),
|
||||
flags.LineBreak,
|
||||
unsafeExportEthKeyCommand(),
|
||||
UnsafeExportEthKeyCommand(),
|
||||
)
|
||||
return cmd
|
||||
}
|
||||
|
||||
func runAddCmd(cmd *cobra.Command, args []string) error {
|
||||
inBuf := bufio.NewReader(cmd.InOrStdin())
|
||||
kb, err := getKeybase(viper.GetBool(flagDryRun), inBuf)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return clientkeys.RunAddCmd(cmd, args, kb, inBuf)
|
||||
}
|
||||
|
||||
func getKeybase(transient bool, buf io.Reader) (keyring.Keybase, error) {
|
||||
if transient {
|
||||
return keyring.NewInMemory(keyring.WithKeygenFunc(crypto.EthermintKeygenFunc)), nil
|
||||
@ -62,13 +75,3 @@ func getKeybase(transient bool, buf io.Reader) (keyring.Keybase, error) {
|
||||
buf,
|
||||
keyring.WithKeygenFunc(crypto.EthermintKeygenFunc))
|
||||
}
|
||||
|
||||
func runAddCmd(cmd *cobra.Command, args []string) error {
|
||||
inBuf := bufio.NewReader(cmd.InOrStdin())
|
||||
kb, err := getKeybase(viper.GetBool(flagDryRun), inBuf)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return clientkeys.RunAddCmd(cmd, args, kb, inBuf)
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package main
|
||||
package client
|
||||
|
||||
// DONTCOVER
|
||||
|
||||
@ -52,11 +52,10 @@ var (
|
||||
|
||||
const nodeDirPerm = 0755
|
||||
|
||||
// get cmd to initialize all files for tendermint testnet and application
|
||||
func testnetCmd(ctx *server.Context, cdc *codec.Codec,
|
||||
// TestnetCmd initializes all files for tendermint testnet and application
|
||||
func TestnetCmd(ctx *server.Context, cdc *codec.Codec,
|
||||
mbm module.BasicManager, genBalIterator banktypes.GenesisBalancesIterator,
|
||||
) *cobra.Command {
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "testnet",
|
||||
Short: "Initialize files for a Ethermint testnet",
|
@ -1,82 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
ethcrypto "github.com/ethereum/go-ethereum/crypto"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client/flags"
|
||||
"github.com/cosmos/cosmos-sdk/client/input"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/keyring"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
|
||||
emintcrypto "github.com/cosmos/ethermint/crypto"
|
||||
)
|
||||
|
||||
func unsafeExportEthKeyCommand() *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "unsafe-export-eth-key [name]",
|
||||
Short: "**UNSAFE** Export an Ethereum private key",
|
||||
Long: `**UNSAFE** Export an Ethereum private key unencrypted to use in dev tooling`,
|
||||
Args: cobra.ExactArgs(1),
|
||||
RunE: runExportCmd,
|
||||
}
|
||||
return cmd
|
||||
}
|
||||
|
||||
func runExportCmd(cmd *cobra.Command, args []string) error {
|
||||
inBuf := bufio.NewReader(cmd.InOrStdin())
|
||||
|
||||
kb, err := keyring.NewKeyring(
|
||||
sdk.KeyringServiceName(),
|
||||
viper.GetString(flags.FlagKeyringBackend),
|
||||
viper.GetString(flags.FlagHome),
|
||||
inBuf,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
decryptPassword := ""
|
||||
conf := true
|
||||
keyringBackend := viper.GetString(flags.FlagKeyringBackend)
|
||||
switch keyringBackend {
|
||||
case keyring.BackendFile:
|
||||
decryptPassword, err = input.GetPassword(
|
||||
"**WARNING this is an unsafe way to export your unencrypted private key**\nEnter key password:",
|
||||
inBuf)
|
||||
case keyring.BackendOS:
|
||||
conf, err = input.GetConfirmation(
|
||||
"**WARNING** this is an unsafe way to export your unencrypted private key, are you sure?",
|
||||
inBuf)
|
||||
}
|
||||
if err != nil || !conf {
|
||||
return err
|
||||
}
|
||||
|
||||
// Exports private key from keybase using password
|
||||
privKey, err := kb.ExportPrivateKeyObject(args[0], decryptPassword)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Converts key to Ethermint secp256 implementation
|
||||
emintKey, ok := privKey.(emintcrypto.PrivKeySecp256k1)
|
||||
if !ok {
|
||||
return fmt.Errorf("invalid private key type, must be Ethereum key: %T", privKey)
|
||||
}
|
||||
|
||||
// Formats key for output
|
||||
privB := ethcrypto.FromECDSA(emintKey.ToECDSA())
|
||||
keyS := strings.ToUpper(hexutil.Encode(privB)[2:])
|
||||
|
||||
fmt.Println(keyS)
|
||||
|
||||
return nil
|
||||
}
|
@ -2,21 +2,13 @@ package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
|
||||
"github.com/cosmos/ethermint/app"
|
||||
"github.com/cosmos/ethermint/codec"
|
||||
emintcrypto "github.com/cosmos/ethermint/crypto"
|
||||
"github.com/cosmos/ethermint/rpc"
|
||||
|
||||
tmamino "github.com/tendermint/tendermint/crypto/encoding/amino"
|
||||
"github.com/tendermint/tendermint/libs/cli"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
sdkclient "github.com/cosmos/cosmos-sdk/client"
|
||||
"github.com/cosmos/cosmos-sdk/client/flags"
|
||||
clientkeys "github.com/cosmos/cosmos-sdk/client/keys"
|
||||
clientrpc "github.com/cosmos/cosmos-sdk/client/rpc"
|
||||
@ -28,6 +20,12 @@ import (
|
||||
authcmd "github.com/cosmos/cosmos-sdk/x/auth/client/cli"
|
||||
"github.com/cosmos/cosmos-sdk/x/bank"
|
||||
bankcmd "github.com/cosmos/cosmos-sdk/x/bank/client/cli"
|
||||
|
||||
"github.com/cosmos/ethermint/app"
|
||||
"github.com/cosmos/ethermint/client"
|
||||
"github.com/cosmos/ethermint/codec"
|
||||
"github.com/cosmos/ethermint/crypto"
|
||||
"github.com/cosmos/ethermint/rpc"
|
||||
)
|
||||
|
||||
var (
|
||||
@ -38,8 +36,8 @@ func main() {
|
||||
// Configure cobra to sort commands
|
||||
cobra.EnableCommandSorting = false
|
||||
|
||||
tmamino.RegisterKeyType(emintcrypto.PubKeySecp256k1{}, emintcrypto.PubKeyAminoName)
|
||||
tmamino.RegisterKeyType(emintcrypto.PrivKeySecp256k1{}, emintcrypto.PrivKeyAminoName)
|
||||
tmamino.RegisterKeyType(crypto.PubKeySecp256k1{}, crypto.PubKeyAminoName)
|
||||
tmamino.RegisterKeyType(crypto.PrivKeySecp256k1{}, crypto.PrivKeyAminoName)
|
||||
|
||||
keyring.CryptoCdc = cdc
|
||||
clientkeys.KeysCdc = cdc
|
||||
@ -59,18 +57,18 @@ func main() {
|
||||
// Add --chain-id to persistent flags and mark it required
|
||||
rootCmd.PersistentFlags().String(flags.FlagChainID, "", "Chain ID of tendermint node")
|
||||
rootCmd.PersistentPreRunE = func(_ *cobra.Command, _ []string) error {
|
||||
return initConfig(rootCmd)
|
||||
return client.InitConfig(rootCmd)
|
||||
}
|
||||
|
||||
// Construct Root Command
|
||||
rootCmd.AddCommand(
|
||||
clientrpc.StatusCommand(),
|
||||
client.ConfigCmd(app.DefaultCLIHome),
|
||||
sdkclient.ConfigCmd(app.DefaultCLIHome),
|
||||
queryCmd(cdc),
|
||||
txCmd(cdc),
|
||||
rpc.EmintServeCmd(cdc),
|
||||
flags.LineBreak,
|
||||
keyCommands(),
|
||||
client.KeyCommands(),
|
||||
flags.LineBreak,
|
||||
version.Cmd,
|
||||
flags.NewCompletionCmd(rootCmd, true),
|
||||
@ -140,26 +138,3 @@ func txCmd(cdc *sdkcodec.Codec) *cobra.Command {
|
||||
|
||||
return txCmd
|
||||
}
|
||||
|
||||
func initConfig(cmd *cobra.Command) error {
|
||||
home, err := cmd.PersistentFlags().GetString(cli.HomeFlag)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
cfgFile := path.Join(home, "config", "config.toml")
|
||||
if _, err := os.Stat(cfgFile); err == nil {
|
||||
viper.SetConfigFile(cfgFile)
|
||||
|
||||
if err := viper.ReadInConfig(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if err := viper.BindPFlag(flags.FlagChainID, cmd.PersistentFlags().Lookup(flags.FlagChainID)); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := viper.BindPFlag(cli.EncodingFlag, cmd.PersistentFlags().Lookup(cli.EncodingFlag)); err != nil {
|
||||
return err
|
||||
}
|
||||
return viper.BindPFlag(cli.OutputFlag, cmd.PersistentFlags().Lookup(cli.OutputFlag))
|
||||
}
|
||||
|
@ -2,9 +2,17 @@ package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"math/big"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
|
||||
abci "github.com/tendermint/tendermint/abci/types"
|
||||
tmamino "github.com/tendermint/tendermint/crypto/encoding/amino"
|
||||
"github.com/tendermint/tendermint/libs/cli"
|
||||
"github.com/tendermint/tendermint/libs/log"
|
||||
tmtypes "github.com/tendermint/tendermint/types"
|
||||
dbm "github.com/tendermint/tm-db"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/baseapp"
|
||||
"github.com/cosmos/cosmos-sdk/client/flags"
|
||||
@ -19,19 +27,10 @@ import (
|
||||
genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/staking"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
|
||||
"github.com/cosmos/ethermint/app"
|
||||
"github.com/cosmos/ethermint/client"
|
||||
"github.com/cosmos/ethermint/codec"
|
||||
emintcrypto "github.com/cosmos/ethermint/crypto"
|
||||
|
||||
abci "github.com/tendermint/tendermint/abci/types"
|
||||
tmamino "github.com/tendermint/tendermint/crypto/encoding/amino"
|
||||
"github.com/tendermint/tendermint/libs/cli"
|
||||
"github.com/tendermint/tendermint/libs/log"
|
||||
tmtypes "github.com/tendermint/tendermint/types"
|
||||
dbm "github.com/tendermint/tm-db"
|
||||
"github.com/cosmos/ethermint/crypto"
|
||||
)
|
||||
|
||||
const flagInvCheckPeriod = "inv-check-period"
|
||||
@ -44,8 +43,8 @@ func main() {
|
||||
cdc := codec.MakeCodec(app.ModuleBasics)
|
||||
appCodec := codec.NewAppCodec(cdc)
|
||||
|
||||
tmamino.RegisterKeyType(emintcrypto.PubKeySecp256k1{}, emintcrypto.PubKeyAminoName)
|
||||
tmamino.RegisterKeyType(emintcrypto.PrivKeySecp256k1{}, emintcrypto.PrivKeyAminoName)
|
||||
tmamino.RegisterKeyType(crypto.PubKeySecp256k1{}, crypto.PubKeyAminoName)
|
||||
tmamino.RegisterKeyType(crypto.PrivKeySecp256k1{}, crypto.PrivKeyAminoName)
|
||||
|
||||
keyring.CryptoCdc = cdc
|
||||
genutil.ModuleCdc = cdc
|
||||
@ -67,7 +66,9 @@ func main() {
|
||||
}
|
||||
// CLI commands to initialize the chain
|
||||
rootCmd.AddCommand(
|
||||
withChainIDValidation(genutilcli.InitCmd(ctx, cdc, app.ModuleBasics, app.DefaultNodeHome)),
|
||||
client.ValidateChainID(
|
||||
genutilcli.InitCmd(ctx, cdc, app.ModuleBasics, app.DefaultNodeHome),
|
||||
),
|
||||
genutilcli.CollectGenTxsCmd(ctx, cdc, bank.GenesisBalancesIterator{}, app.DefaultNodeHome),
|
||||
genutilcli.MigrateGenesisCmd(ctx, cdc),
|
||||
genutilcli.GenTxCmd(
|
||||
@ -75,7 +76,7 @@ func main() {
|
||||
app.DefaultNodeHome, app.DefaultCLIHome,
|
||||
),
|
||||
genutilcli.ValidateGenesisCmd(ctx, cdc, app.ModuleBasics),
|
||||
testnetCmd(ctx, cdc, app.ModuleBasics, bank.GenesisBalancesIterator{}),
|
||||
client.TestnetCmd(ctx, cdc, app.ModuleBasics, bank.GenesisBalancesIterator{}),
|
||||
// AddGenesisAccountCmd allows users to add accounts to the genesis file
|
||||
AddGenesisAccountCmd(ctx, cdc, appCodec, app.DefaultNodeHome, app.DefaultCLIHome),
|
||||
flags.NewCompletionCmd(rootCmd, true),
|
||||
@ -116,25 +117,3 @@ func exportAppStateAndTMValidators(
|
||||
|
||||
return emintApp.ExportAppStateAndValidators(forZeroHeight, jailWhiteList)
|
||||
}
|
||||
|
||||
// Wraps cobra command with a RunE function with integer chain-id verification
|
||||
func withChainIDValidation(baseCmd *cobra.Command) *cobra.Command {
|
||||
// Copy base run command to be used after chain verification
|
||||
baseRunE := baseCmd.RunE
|
||||
|
||||
// Function to replace command's RunE function
|
||||
chainIDVerify := func(cmd *cobra.Command, args []string) error {
|
||||
chainIDFlag := viper.GetString(flags.FlagChainID)
|
||||
|
||||
// Verify that the chain-id entered is a base 10 integer
|
||||
_, ok := new(big.Int).SetString(chainIDFlag, 10)
|
||||
if !ok {
|
||||
return fmt.Errorf("invalid chainID: %s, must be base-10 integer format", chainIDFlag)
|
||||
}
|
||||
|
||||
return baseRunE(cmd, args)
|
||||
}
|
||||
|
||||
baseCmd.RunE = chainIDVerify
|
||||
return baseCmd
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user