From 771c5bcb52ceaf80952b58f95307cee685077cf9 Mon Sep 17 00:00:00 2001 From: Jack Li Date: Fri, 16 Aug 2024 20:24:49 +0800 Subject: [PATCH] cmd: add keys command --- app/app.go | 2 +- client/config.go | 67 +++++ client/config_test.go | 27 ++ client/debug/debug.go | 225 ++++++++++++++ client/export.go | 88 ++++++ client/import.go | 48 +++ client/keys.go | 93 ++++++ client/keys/add.go | 306 ++++++++++++++++++++ client/keys/utils.go | 60 ++++ cmd/artelad/cmd/commands.go | 19 +- cmd/artelad/cmd/genaccounts.go | 215 ++++++++++++++ cmd/artelad/cmd/gencontract.go | 153 ++++++++++ cmd/artelad/cmd/keyinfo.go | 124 ++++++++ ethereum/crypto/ethsecp256k1/keys.pb.go | 193 ++++++------ ethereum/types/coin.go | 2 +- go.mod | 6 +- init.sh | 147 ++++++++++ proto/artela/crypto/ethsecp256k1/keys.proto | 23 ++ x/evm/module/genesis.go | 30 +- x/evm/module/module.go | 2 +- x/evm/types/expected_keepers.go | 1 + x/fee/types/params.go | 4 +- 22 files changed, 1723 insertions(+), 112 deletions(-) create mode 100644 client/config.go create mode 100644 client/config_test.go create mode 100644 client/debug/debug.go create mode 100644 client/export.go create mode 100644 client/import.go create mode 100644 client/keys.go create mode 100644 client/keys/add.go create mode 100644 client/keys/utils.go create mode 100644 cmd/artelad/cmd/genaccounts.go create mode 100644 cmd/artelad/cmd/gencontract.go create mode 100644 cmd/artelad/cmd/keyinfo.go create mode 100755 init.sh create mode 100644 proto/artela/crypto/ethsecp256k1/keys.proto diff --git a/app/app.go b/app/app.go index 2020a3f..5d55576 100644 --- a/app/app.go +++ b/app/app.go @@ -91,7 +91,7 @@ import ( const ( AccountAddressPrefix = "art" - Name = "artelad" + Name = "artroll" ) const ( diff --git a/client/config.go b/client/config.go new file mode 100644 index 0000000..7317b9a --- /dev/null +++ b/client/config.go @@ -0,0 +1,67 @@ +package client + +import ( + "fmt" + "os" + "path" + + "github.com/spf13/cobra" + "github.com/spf13/viper" + + "github.com/cometbft/cometbft/libs/cli" + "github.com/cosmos/cosmos-sdk/client/flags" + + "github.com/artela-network/artela-rollkit/ethereum/types" +) + +// 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") + _, err = os.Stat(configFile) + if err != nil && !os.IsNotExist(err) { + // Immediately return if the error isn't related to the file not existing. + return err + } + if 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 { + chainID, _ := cmd.Flags().GetString(flags.FlagChainID) + + if !types.IsValidChainID(chainID) { + return fmt.Errorf("invalid chain-id format: %s", chainID) + } + + return baseRunE(cmd, args) + } + + baseCmd.RunE = validateFn + return baseCmd +} diff --git a/client/config_test.go b/client/config_test.go new file mode 100644 index 0000000..4d04b16 --- /dev/null +++ b/client/config_test.go @@ -0,0 +1,27 @@ +package client + +import ( + "os" + "path/filepath" + "testing" + + "github.com/cosmos/cosmos-sdk/client/flags" + "github.com/spf13/cobra" +) + +func TestInitConfigNonNotExistError(t *testing.T) { + tempDir := t.TempDir() + subDir := filepath.Join(tempDir, "nonPerms") + if err := os.Mkdir(subDir, 0o600); err != nil { + t.Fatalf("Failed to create sub directory: %v", err) + } + cmd := &cobra.Command{} + cmd.PersistentFlags().String(flags.FlagHome, "", "") + if err := cmd.PersistentFlags().Set(flags.FlagHome, subDir); err != nil { + t.Fatalf("Could not set home flag [%T] %v", err, err) + } + + if err := InitConfig(cmd); !os.IsPermission(err) { + t.Fatalf("Failed to catch permissions error, got: [%T] %v", err, err) + } +} diff --git a/client/debug/debug.go b/client/debug/debug.go new file mode 100644 index 0000000..f9c3d2a --- /dev/null +++ b/client/debug/debug.go @@ -0,0 +1,225 @@ +package debug + +import ( + "encoding/base64" + "encoding/hex" + "encoding/json" + "fmt" + "log" + "strconv" + "strings" + + "github.com/pkg/errors" + "github.com/spf13/cobra" + + "github.com/cometbft/cometbft/libs/bytes" + cometbftTypes "github.com/cometbft/cometbft/types" + "github.com/cosmos/cosmos-sdk/client" + cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" + sdk "github.com/cosmos/cosmos-sdk/types" + "github.com/cosmos/cosmos-sdk/version" + authclient "github.com/cosmos/cosmos-sdk/x/auth/client" + "github.com/ethereum/go-ethereum/common" + + appparams "github.com/artela-network/artela-rollkit/app/params" + "github.com/artela-network/artela-rollkit/ethereum/eip712" + artela "github.com/artela-network/artela-rollkit/ethereum/types" + evmtypes "github.com/artela-network/artela-rollkit/x/evm/types" +) + +// Cmd creates a main CLI command +func Cmd(encodingConfig appparams.EncodingConfig) *cobra.Command { + cmd := &cobra.Command{ + Use: "debug", + Short: "Tool for helping with debugging your application", + RunE: client.ValidateCmd, + } + + cmd.AddCommand(PubkeyCmd()) + cmd.AddCommand(AddrCmd()) + cmd.AddCommand(RawBytesCmd()) + cmd.AddCommand(LegacyEIP712Cmd()) + cmd.AddCommand(CosmosTxHash(encodingConfig)) + + return cmd +} + +// getPubKeyFromString decodes SDK PubKey using JSON marshaler. +func getPubKeyFromString(ctx client.Context, pkstr string) (cryptotypes.PubKey, error) { + var pk cryptotypes.PubKey + err := ctx.Codec.UnmarshalInterfaceJSON([]byte(pkstr), &pk) + return pk, err +} + +func PubkeyCmd() *cobra.Command { + return &cobra.Command{ + Use: "pubkey [pubkey]", + Short: "Decode a pubkey from proto JSON", + Long: "Decode a pubkey from proto JSON and display it's address", + Example: fmt.Sprintf( + `"$ %s debug pubkey '{"@type":"/cosmos.crypto.secp256k1.PubKey","key":"AurroA7jvfPd1AadmmOvWM2rJSwipXfRf8yD6pLbA2DJ"}'`, + version.AppName, + ), + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx := client.GetClientContextFromCmd(cmd) + pk, err := getPubKeyFromString(clientCtx, args[0]) + if err != nil { + return err + } + + addr := pk.Address() + cmd.Printf("Address (EIP-55): %s\n", common.BytesToAddress(addr)) + cmd.Printf("Bech32 Acc: %s\n", sdk.AccAddress(addr)) + cmd.Println("PubKey Hex:", hex.EncodeToString(pk.Bytes())) + return nil + }, + } +} + +func AddrCmd() *cobra.Command { + return &cobra.Command{ + Use: "addr [address]", + Short: "Convert an address between hex and bech32", + Long: "Convert an address between hex encoding and bech32.", + Example: fmt.Sprintf( + `$ %s debug addr ethm10jmp6sgh4cc6zt3e8gw05wavvejgr5pw2unfju +$ %s debug addr 0xA588C66983a81e800Db4dF74564F09f91c026351`, version.AppName, version.AppName), + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + addrString := args[0] + cfg := sdk.GetConfig() + + var addr []byte + switch { + case common.IsHexAddress(addrString): + addr = common.HexToAddress(addrString).Bytes() + case strings.HasPrefix(addrString, cfg.GetBech32ValidatorAddrPrefix()): + addr, _ = sdk.ValAddressFromBech32(addrString) + case strings.HasPrefix(addrString, cfg.GetBech32AccountAddrPrefix()): + addr, _ = sdk.AccAddressFromBech32(addrString) + default: + return fmt.Errorf("expected a valid hex or bech32 address (acc prefix %s), got '%s'", cfg.GetBech32AccountAddrPrefix(), addrString) + } + + cmd.Println("Address bytes:", addr) + cmd.Printf("Address (hex): %s\n", bytes.HexBytes(addr)) + cmd.Printf("Address (EIP-55): %s\n", common.BytesToAddress(addr)) + cmd.Printf("Bech32 Acc: %s\n", sdk.AccAddress(addr)) + cmd.Printf("Bech32 Val: %s\n", sdk.ValAddress(addr)) + return nil + }, + } +} + +func RawBytesCmd() *cobra.Command { + return &cobra.Command{ + Use: "raw-bytes [raw-bytes]", + Short: "Convert raw bytes output (eg. [10 21 13 255]) to hex", + Example: fmt.Sprintf(`$ %s debug raw-bytes [72 101 108 108 111 44 32 112 108 97 121 103 114 111 117 110 100]`, version.AppName), + Args: cobra.ExactArgs(1), + RunE: func(_ *cobra.Command, args []string) error { + stringBytes := args[0] + stringBytes = strings.Trim(stringBytes, "[") + stringBytes = strings.Trim(stringBytes, "]") + spl := strings.Split(stringBytes, " ") + + byteArray := []byte{} + for _, s := range spl { + b, err := strconv.ParseInt(s, 10, 8) + if err != nil { + return err + } + byteArray = append(byteArray, byte(b)) + } + fmt.Printf("%X\n", byteArray) + return nil + }, + } +} + +// LegacyEIP712Cmd outputs types of legacy EIP712 typed data +func LegacyEIP712Cmd() *cobra.Command { + return &cobra.Command{ + Use: "legacy-eip712 [file]", + Short: "Output types of legacy eip712 typed data according to the given txs", + Example: fmt.Sprintf(`$ %s debug legacy-eip712 txs.json --chain-id artelad_9000-1`, version.AppName), + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx, err := client.GetClientTxContext(cmd) + if err != nil { + return err + } + + stdTx, err := authclient.ReadTxFromFile(clientCtx, args[0]) + if err != nil { + return errors.Wrap(err, "read txs from file") + } + + txBytes, err := clientCtx.TxConfig.TxJSONEncoder()(stdTx) + if err != nil { + return errors.Wrap(err, "encode txs") + } + + chainID, err := artela.ParseChainID(clientCtx.ChainID) + if err != nil { + return errors.Wrap(err, "invalid chain ID passed as argument") + } + + td, err := eip712.LegacyWrapTxToTypedData(clientCtx.Codec, chainID.Uint64(), stdTx.GetMsgs()[0], txBytes, nil) + if err != nil { + return errors.Wrap(err, "wrap txs to typed data") + } + + bz, err := json.Marshal(td.Map()["types"]) + if err != nil { + return err + } + + fmt.Println(string(bz)) + return nil + }, + } +} + +func CosmosTxHash(encodingConfig appparams.EncodingConfig) *cobra.Command { + return &cobra.Command{ + Use: "tx [base64 encoded tx]", + Short: "Get the ethereum tx of cosmos tx", + Example: "", + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + txBytes, err := base64.StdEncoding.DecodeString(args[0]) + if err != nil { + log.Fatalf("Failed to decode base64: %v", err) + } + + cometbftTx := cometbftTypes.Tx(txBytes) + + tx, err := encodingConfig.TxConfig.TxDecoder()(cometbftTx) + if err != nil { + fmt.Println(err) + } + + for i, msg := range tx.GetMsgs() { + ethMsg, ok := msg.(*evmtypes.MsgEthereumTx) + if !ok { + fmt.Printf("message %d is not etherum tx\n", i) + continue + } + + fmt.Println("this is a ethereum tx:") + ethMsg.Hash = ethMsg.AsTransaction().Hash().Hex() + // result = append(result, ethMsg) + ethTx := ethMsg.AsTransaction() + fmt.Printf(" hash: %s\n to: %s\n value: %s\n data: %s\n", + ethTx.Hash().String(), + ethTx.To().String(), + ethTx.Value().String(), + common.Bytes2Hex(ethTx.Data()), + ) + } + return nil + }, + } +} diff --git a/client/export.go b/client/export.go new file mode 100644 index 0000000..8a85f42 --- /dev/null +++ b/client/export.go @@ -0,0 +1,88 @@ +package client + +import ( + "bufio" + "fmt" + "strings" + + "github.com/spf13/cobra" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/input" + "github.com/cosmos/cosmos-sdk/crypto" + "github.com/cosmos/cosmos-sdk/crypto/keyring" + "github.com/ethereum/go-ethereum/common/hexutil" + ethcrypto "github.com/ethereum/go-ethereum/crypto" + + ethsecp256k12 "github.com/artela-network/artela-rollkit/ethereum/crypto/ethsecp256k1" + "github.com/artela-network/artela-rollkit/ethereum/crypto/hd" +) + +// 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 { + clientCtx := client.GetClientContextFromCmd(cmd).WithKeyringOptions(hd.EthSecp256k1Option()) + clientCtx, err := client.ReadPersistentCommandFlags(clientCtx, cmd.Flags()) + if err != nil { + return err + } + + decryptPassword := "" + conf := true + + inBuf := bufio.NewReader(cmd.InOrStdin()) + switch clientCtx.Keyring.Backend() { + 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, cmd.ErrOrStderr()) + } + if err != nil || !conf { + return err + } + + // Exports private key from keybase using password + armor, err := clientCtx.Keyring.ExportPrivKeyArmor(args[0], decryptPassword) + if err != nil { + return err + } + + privKey, algo, err := crypto.UnarmorDecryptPrivKey(armor, decryptPassword) + if err != nil { + return err + } + + if algo != ethsecp256k12.KeyType { + return fmt.Errorf("invalid key algorithm, got %s, expected %s", algo, ethsecp256k12.KeyType) + } + + // Converts key to Artela secp256k1 implementation + ethPrivKey, ok := privKey.(*ethsecp256k12.PrivKey) + if !ok { + return fmt.Errorf("invalid private key type %T, expected %T", privKey, ðsecp256k12.PrivKey{}) + } + + key, err := ethPrivKey.ToECDSA() + if err != nil { + return err + } + + // Formats key for output + privB := ethcrypto.FromECDSA(key) + keyS := strings.ToUpper(hexutil.Encode(privB)[2:]) + + fmt.Println(keyS) + + return nil + }, + } +} diff --git a/client/import.go b/client/import.go new file mode 100644 index 0000000..846382a --- /dev/null +++ b/client/import.go @@ -0,0 +1,48 @@ +package client + +import ( + "bufio" + + "github.com/spf13/cobra" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/input" + "github.com/cosmos/cosmos-sdk/crypto" + "github.com/ethereum/go-ethereum/common" + + "github.com/artela-network/artela-rollkit/ethereum/crypto/ethsecp256k1" + "github.com/artela-network/artela-rollkit/ethereum/crypto/hd" +) + +// UnsafeImportKeyCommand imports private keys from a keyfile. +func UnsafeImportKeyCommand() *cobra.Command { + return &cobra.Command{ + Use: "unsafe-import-eth-key ", + Short: "**UNSAFE** Import Ethereum private keys into the local keybase", + Long: "**UNSAFE** Import a hex-encoded Ethereum private key into the local keybase.", + Args: cobra.ExactArgs(2), + RunE: runImportCmd, + } +} + +func runImportCmd(cmd *cobra.Command, args []string) error { + clientCtx := client.GetClientContextFromCmd(cmd).WithKeyringOptions(hd.EthSecp256k1Option()) + clientCtx, err := client.ReadPersistentCommandFlags(clientCtx, cmd.Flags()) + if err != nil { + return err + } + + inBuf := bufio.NewReader(cmd.InOrStdin()) + passphrase, err := input.GetPassword("Enter passphrase to encrypt your key:", inBuf) + if err != nil { + return err + } + + privKey := ðsecp256k1.PrivKey{ + Key: common.FromHex(args[1]), + } + + armor := crypto.EncryptArmorPrivKey(privKey, passphrase, "eth_secp256k1") + + return clientCtx.Keyring.ImportPrivKey(args[0], armor, passphrase) +} diff --git a/client/keys.go b/client/keys.go new file mode 100644 index 0000000..9ae2a71 --- /dev/null +++ b/client/keys.go @@ -0,0 +1,93 @@ +package client + +import ( + "bufio" + + "github.com/spf13/cobra" + + "github.com/cometbft/cometbft/libs/cli" + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/flags" + "github.com/cosmos/cosmos-sdk/client/keys" + "github.com/cosmos/cosmos-sdk/crypto/keyring" + + clientkeys "github.com/artela-network/artela-rollkit/client/keys" + "github.com/artela-network/artela-rollkit/ethereum/crypto/ethsecp256k1" + "github.com/artela-network/artela-rollkit/ethereum/crypto/hd" +) + +// KeyCommands registers a sub-tree of commands to interact with +// local private key storage. +func KeyCommands(defaultNodeHome string) *cobra.Command { + cmd := &cobra.Command{ + Use: "keys", + Short: "Manage your application's keys", + Long: `Keyring management commands. These keys may be in any format supported by the +Tendermint crypto library and can be used by light-clients, full nodes, or any other application +that needs to sign with a private key. + +The keyring supports the following backends: + + os Uses the operating system's default credentials store. + file Uses encrypted file-based keystore within the app's configuration directory. + This keyring will request a password each time it is accessed, which may occur + multiple times in a single command resulting in repeated password prompts. + kwallet Uses KDE Wallet Manager as a credentials management application. + pass Uses the pass command line utility to store and retrieve keys. + test Stores keys insecurely to disk. It does not prompt for a password to be unlocked + and it should be use only for testing purposes. + +kwallet and pass backends depend on external tools. Refer to their respective documentation for more +information: + KWallet https://github.com/KDE/kwallet + pass https://www.passwordstore.org/ + +The pass backend requires GnuPG: https://gnupg.org/ +`, + } + + // support adding Ethereum supported keys + addCmd := keys.AddKeyCommand() + + // update the default signing algorithm value to "eth_secp256k1" + algoFlag := addCmd.Flag(ethsecp256k1.FlagKeyAlgorithm) + algoFlag.DefValue = string(hd.EthSecp256k1Type) + err := algoFlag.Value.Set(string(hd.EthSecp256k1Type)) + if err != nil { + panic(err) + } + + addCmd.RunE = runAddCmd + + cmd.AddCommand( + keys.MnemonicKeyCommand(), + addCmd, + keys.ExportKeyCommand(), + keys.ImportKeyCommand(), + keys.ListKeysCmd(), + keys.ShowKeysCmd(), + keys.DeleteKeyCommand(), + keys.RenameKeyCommand(), + keys.ParseKeyStringCommand(), + keys.MigrateCommand(), + flags.LineBreak, + UnsafeExportEthKeyCommand(), + UnsafeImportKeyCommand(), + ) + + cmd.PersistentFlags().String(flags.FlagHome, defaultNodeHome, "The application home directory") + cmd.PersistentFlags().String(flags.FlagKeyringDir, "", "The client Keyring directory; if omitted, the default 'home' directory will be used") + cmd.PersistentFlags().String(flags.FlagKeyringBackend, keyring.BackendOS, "Select keyring's backend (os|file|test)") + cmd.PersistentFlags().String(cli.OutputFlag, "text", "Output format (text|json)") + return cmd +} + +func runAddCmd(cmd *cobra.Command, args []string) error { + clientCtx := client.GetClientContextFromCmd(cmd).WithKeyringOptions(hd.EthSecp256k1Option()) + clientCtx, err := client.ReadPersistentCommandFlags(clientCtx, cmd.Flags()) + if err != nil { + return err + } + buf := bufio.NewReader(clientCtx.Input) + return clientkeys.RunAddCmd(clientCtx, cmd, args, buf) +} diff --git a/client/keys/add.go b/client/keys/add.go new file mode 100644 index 0000000..7ac89a6 --- /dev/null +++ b/client/keys/add.go @@ -0,0 +1,306 @@ +package keys + +import ( + "bufio" + "bytes" + "errors" + "fmt" + "sort" + + "github.com/cosmos/go-bip39" + "github.com/spf13/cobra" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/flags" + "github.com/cosmos/cosmos-sdk/client/input" + "github.com/cosmos/cosmos-sdk/client/keys" + "github.com/cosmos/cosmos-sdk/crypto/hd" + "github.com/cosmos/cosmos-sdk/crypto/keyring" + "github.com/cosmos/cosmos-sdk/crypto/keys/multisig" + cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" + sdk "github.com/cosmos/cosmos-sdk/types" + + "github.com/artela-network/artela-rollkit/ethereum/crypto/codec" + "github.com/artela-network/artela-rollkit/ethereum/crypto/ethsecp256k1" + cryptohd "github.com/artela-network/artela-rollkit/ethereum/crypto/hd" +) + +const ( + flagInteractive = "interactive" + flagRecover = "recover" + flagNoBackup = "no-backup" + flagCoinType = "coin-type" + flagAccount = "account" + flagIndex = "index" + flagMultisig = "multisig" + flagMultiSigThreshold = "multisig-threshold" + flagNoSort = "nosort" + flagHDPath = "hd-path" + + mnemonicEntropySize = 256 +) + +/* +RunAddCmd +input + - bip39 mnemonic + - bip39 passphrase + - bip44 path + - local encryption password + +output + - armor encrypted private key (saved to file) +*/ +func RunAddCmd(ctx client.Context, cmd *cobra.Command, args []string, inBuf *bufio.Reader) error { + var ( + algo keyring.SignatureAlgo + err error + ) + + name := args[0] + + interactive, _ := cmd.Flags().GetBool(flagInteractive) + noBackup, _ := cmd.Flags().GetBool(flagNoBackup) + useLedger, _ := cmd.Flags().GetBool(flags.FlagUseLedger) + algoStr, _ := cmd.Flags().GetString(ethsecp256k1.FlagKeyAlgorithm) + + showMnemonic := !noBackup + kb := ctx.Keyring + outputFormat := ctx.OutputFormat + + keyringAlgos, ledgerAlgos := kb.SupportedAlgorithms() + + // check if the provided signing algorithm is supported by the keyring or + // ledger + if useLedger { + algo, err = keyring.NewSigningAlgoFromString(algoStr, ledgerAlgos) + } else { + algo, err = keyring.NewSigningAlgoFromString(algoStr, keyringAlgos) + } + + if err != nil { + return err + } + + if dryRun, _ := cmd.Flags().GetBool(flags.FlagDryRun); dryRun { + // use in memory keybase + kb = keyring.NewInMemory(ctx.Codec, cryptohd.EthSecp256k1Option()) + } else { + _, err = kb.Key(name) + if err == nil { + // account exists, ask for user confirmation + response, err2 := input.GetConfirmation(fmt.Sprintf("override the existing name %s", name), inBuf, cmd.ErrOrStderr()) + if err2 != nil { + return err2 + } + + if !response { + return errors.New("aborted") + } + + err2 = kb.Delete(name) + if err2 != nil { + return err2 + } + } + + multisigKeys, _ := cmd.Flags().GetStringSlice(flagMultisig) + if len(multisigKeys) != 0 { + pks := make([]cryptotypes.PubKey, len(multisigKeys)) + multisigThreshold, _ := cmd.Flags().GetInt(flagMultiSigThreshold) + if err := validateMultisigThreshold(multisigThreshold, len(multisigKeys)); err != nil { + return err + } + + for i, keyname := range multisigKeys { + k, err := kb.Key(keyname) + if err != nil { + return err + } + + key, err := k.GetPubKey() + if err != nil { + return err + } + pks[i] = key + } + + if noSort, _ := cmd.Flags().GetBool(flagNoSort); !noSort { + sort.Slice(pks, func(i, j int) bool { + return bytes.Compare(pks[i].Address(), pks[j].Address()) < 0 + }) + } + + pk := multisig.NewLegacyAminoPubKey(multisigThreshold, pks) + k, err := kb.SaveMultisig(name, pk) + if err != nil { + return err + } + + return printCreate(cmd, k, false, "", outputFormat) + } + } + + pubKey, _ := cmd.Flags().GetString(keys.FlagPublicKey) + if pubKey != "" { + var pk cryptotypes.PubKey + if err = ctx.Codec.UnmarshalInterfaceJSON([]byte(pubKey), &pk); err != nil { + return err + } + + k, err := kb.SaveOfflineKey(name, pk) + if err != nil { + return err + } + + return printCreate(cmd, k, false, "", outputFormat) + } + + coinType, _ := cmd.Flags().GetUint32(flagCoinType) + account, _ := cmd.Flags().GetUint32(flagAccount) + index, _ := cmd.Flags().GetUint32(flagIndex) + hdPath, _ := cmd.Flags().GetString(flagHDPath) + + if len(hdPath) == 0 { + hdPath = hd.CreateHDPath(coinType, account, index).String() + } else if useLedger { + return errors.New("cannot set custom bip32 path with ledger") + } + + // If we're using ledger, only thing we need is the path and the bech32 prefix. + if useLedger { + bech32PrefixAccAddr := sdk.GetConfig().GetBech32AccountAddrPrefix() + + // use the provided algo to save the ledger key + k, err := kb.SaveLedgerKey(name, algo, bech32PrefixAccAddr, coinType, account, index) + if err != nil { + return err + } + + return printCreate(cmd, k, false, "", outputFormat) + } + + // Get bip39 mnemonic + var mnemonic, bip39Passphrase string + + recoverKey, _ := cmd.Flags().GetBool(flagRecover) + if recoverKey { + mnemonic, err = input.GetString("Enter your bip39 mnemonic", inBuf) + if err != nil { + return err + } + + if !bip39.IsMnemonicValid(mnemonic) { + return errors.New("invalid mnemonic") + } + } else if interactive { + mnemonic, err = input.GetString("Enter your bip39 mnemonic, or hit enter to generate one.", inBuf) + if err != nil { + return err + } + + if !bip39.IsMnemonicValid(mnemonic) && mnemonic != "" { + return errors.New("invalid mnemonic") + } + } + + if len(mnemonic) == 0 { + // read entropy seed straight from tmcrypto.Rand and convert to mnemonic + entropySeed, err := bip39.NewEntropy(mnemonicEntropySize) + if err != nil { + return err + } + + mnemonic, err = bip39.NewMnemonic(entropySeed) + if err != nil { + return err + } + } + + // override bip39 passphrase + if interactive { + bip39Passphrase, err = input.GetString( + "Enter your bip39 passphrase. This is combined with the mnemonic to derive the seed. "+ + "Most users should just hit enter to use the default, \"\"", inBuf) + if err != nil { + return err + } + + // if they use one, make them re-enter it + if len(bip39Passphrase) != 0 { + p2, err := input.GetString("Repeat the passphrase:", inBuf) + if err != nil { + return err + } + + if bip39Passphrase != p2 { + return errors.New("passphrases don't match") + } + } + } + + k, err := kb.NewAccount(name, mnemonic, bip39Passphrase, hdPath, algo) + if err != nil { + return err + } + + // Recover key from seed passphrase + if recoverKey { + // Hide mnemonic from output + showMnemonic = false + mnemonic = "" + } + + return printCreate(cmd, k, showMnemonic, mnemonic, outputFormat) +} + +func printCreate(cmd *cobra.Command, k *keyring.Record, showMnemonic bool, mnemonic, outputFormat string) error { + switch outputFormat { + case OutputFormatText: + cmd.PrintErrln() + if err := printKeyringRecord(cmd.OutOrStdout(), k, keys.MkAccKeyOutput, outputFormat); err != nil { + return err + } + + // print mnemonic unless requested not to. + if showMnemonic { + if _, err := fmt.Fprintf(cmd.ErrOrStderr(), + "\n**Important** write this mnemonic phrase in a safe place.\nIt is the only way to recover your account if you ever forget your password.\n\n%s\n\n", //nolint:lll + mnemonic); err != nil { + return fmt.Errorf("failed to print mnemonic: %v", err) + } + } + case OutputFormatJSON: + out, err := keys.MkAccKeyOutput(k) + if err != nil { + return err + } + + if showMnemonic { + out.Mnemonic = mnemonic + } + + jsonString, err := codec.KeysCdc.MarshalJSON(out) + if err != nil { + return err + } + + cmd.Println(string(jsonString)) + + default: + return fmt.Errorf("invalid output format %s", outputFormat) + } + + return nil +} + +func validateMultisigThreshold(k, nKeys int) error { + if k <= 0 { + return fmt.Errorf("threshold must be a positive integer") + } + if nKeys < k { + return fmt.Errorf( + "threshold k of n multisignature: %d < %d", nKeys, k) + } + return nil +} diff --git a/client/keys/utils.go b/client/keys/utils.go new file mode 100644 index 0000000..3034a84 --- /dev/null +++ b/client/keys/utils.go @@ -0,0 +1,60 @@ +package keys + +import ( + "fmt" + "io" + + "github.com/cosmos/cosmos-sdk/client/keys" + "sigs.k8s.io/yaml" + + cryptokeyring "github.com/cosmos/cosmos-sdk/crypto/keyring" + + "github.com/artela-network/artela-rollkit/ethereum/crypto/codec" +) + +// available output formats. +const ( + OutputFormatText = "text" + OutputFormatJSON = "json" +) + +type bechKeyOutFn func(k *cryptokeyring.Record) (keys.KeyOutput, error) + +func printKeyringRecord(w io.Writer, k *cryptokeyring.Record, bechKeyOut bechKeyOutFn, output string) error { + ko, err := bechKeyOut(k) + if err != nil { + return err + } + + switch output { + case OutputFormatText: + if err := printTextRecords(w, []keys.KeyOutput{ko}); err != nil { + return err + } + + case OutputFormatJSON: + out, err := codec.KeysCdc.MarshalJSON(ko) + if err != nil { + return err + } + + if _, err := fmt.Fprintln(w, string(out)); err != nil { + return err + } + } + + return nil +} + +func printTextRecords(w io.Writer, kos []keys.KeyOutput) error { + out, err := yaml.Marshal(&kos) + if err != nil { + return err + } + + if _, err := fmt.Fprintln(w, string(out)); err != nil { + return err + } + + return nil +} diff --git a/cmd/artelad/cmd/commands.go b/cmd/artelad/cmd/commands.go index 4589d35..fff4744 100644 --- a/cmd/artelad/cmd/commands.go +++ b/cmd/artelad/cmd/commands.go @@ -10,20 +10,23 @@ import ( "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/client/debug" "github.com/cosmos/cosmos-sdk/client/flags" - "github.com/cosmos/cosmos-sdk/client/keys" "github.com/cosmos/cosmos-sdk/client/pruning" "github.com/cosmos/cosmos-sdk/client/rpc" "github.com/cosmos/cosmos-sdk/client/snapshot" + "github.com/cosmos/cosmos-sdk/codec/address" "github.com/cosmos/cosmos-sdk/server" servertypes "github.com/cosmos/cosmos-sdk/server/types" "github.com/cosmos/cosmos-sdk/types/module" authcmd "github.com/cosmos/cosmos-sdk/x/auth/client/cli" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" "github.com/cosmos/cosmos-sdk/x/crisis" genutilcli "github.com/cosmos/cosmos-sdk/x/genutil/client/cli" + genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types" "github.com/spf13/cobra" "github.com/spf13/viper" "github.com/artela-network/artela-rollkit/app" + artclient "github.com/artela-network/artela-rollkit/client" eth "github.com/artela-network/artela-rollkit/ethereum/server/flags" rollconf "github.com/rollkit/rollkit/config" @@ -38,10 +41,22 @@ func initRootCmd( ) { rootCmd.AddCommand( genutilcli.InitCmd(basicManager, app.DefaultNodeHome), + genutilcli.CollectGenTxsCmd(banktypes.GenesisBalancesIterator{}, app.DefaultNodeHome, genutiltypes.DefaultMessageValidator, address.NewBech32Codec(app.AccountAddressPrefix)), + genutilcli.GenTxCmd( + basicManager, + txConfig, + banktypes.GenesisBalancesIterator{}, + app.DefaultNodeHome, + address.NewBech32Codec(app.AccountAddressPrefix), + ), + genutilcli.ValidateGenesisCmd(basicManager), debug.Cmd(), confixcmd.ConfigCommand(), pruning.Cmd(newApp, app.DefaultNodeHome), snapshot.Cmd(newApp), + AddGenesisAccountCmd(app.DefaultNodeHome), + AddGenesisContractCmd(app.DefaultNodeHome), + KeyInfoCmd(), ) server.AddCommandsWithStartCmdOptions( @@ -63,7 +78,7 @@ func initRootCmd( genesisCommand(txConfig, basicManager), queryCommand(), txCommand(), - keys.Commands(), + artclient.KeyCommands(app.DefaultNodeHome), ) } diff --git a/cmd/artelad/cmd/genaccounts.go b/cmd/artelad/cmd/genaccounts.go new file mode 100644 index 0000000..24a6c86 --- /dev/null +++ b/cmd/artelad/cmd/genaccounts.go @@ -0,0 +1,215 @@ +package cmd + +import ( + "bufio" + "encoding/json" + "errors" + "fmt" + + "github.com/spf13/cobra" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/flags" + "github.com/cosmos/cosmos-sdk/crypto/keyring" + "github.com/cosmos/cosmos-sdk/server" + sdk "github.com/cosmos/cosmos-sdk/types" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + authvesting "github.com/cosmos/cosmos-sdk/x/auth/vesting/types" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" + "github.com/cosmos/cosmos-sdk/x/genutil" + genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types" + + "github.com/artela-network/artela-rollkit/ethereum/crypto/hd" +) + +const ( + flagVestingStart = "vesting-start-time" + flagVestingEnd = "vesting-end-time" + flagVestingAmt = "vesting-amount" +) + +// AddGenesisAccountCmd returns add-genesis-account cobra Command. +func AddGenesisAccountCmd(defaultNodeHome string) *cobra.Command { + cmd := &cobra.Command{ + Use: "add-genesis-account [address_or_key_name] [coin][,[coin]]", + Short: "Add a genesis account to genesis.json", + Long: `Add a genesis account to genesis.json. The provided account must specify +the account address or key name and a list of initial coins. If a key name is given, +the address will be looked up in the local Keybase. The list of initial tokens must +contain valid denominations. Accounts may optionally be supplied with vesting parameters. +`, + Args: cobra.ExactArgs(2), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx := client.GetClientContextFromCmd(cmd) + cdc := clientCtx.Codec + + serverCtx := server.GetServerContextFromCmd(cmd) + config := serverCtx.Config + + config.SetRoot(clientCtx.HomeDir) + + coins, err := sdk.ParseCoinsNormalized(args[1]) + if err != nil { + return fmt.Errorf("failed to parse coins: %w", err) + } + + var kb keyring.Keyring + addr, err := sdk.AccAddressFromBech32(args[0]) + if err != nil { + inBuf := bufio.NewReader(cmd.InOrStdin()) + keyringBackend, err := cmd.Flags().GetString(flags.FlagKeyringBackend) + if err != nil { + return err + } + + if keyringBackend != "" && clientCtx.Keyring == nil { + var err error + kb, err = keyring.New( + sdk.KeyringServiceName(), + keyringBackend, + clientCtx.HomeDir, + inBuf, + clientCtx.Codec, + hd.EthSecp256k1Option(), + ) + if err != nil { + return err + } + } else { + var err error + // attempt to lookup address from Keybase if no address was provided + kb, err = keyring.New(sdk.KeyringServiceName(), keyringBackend, clientCtx.HomeDir, inBuf, cdc) + if err != nil { + return err + } + } + + info, err := kb.Key(args[0]) + if err != nil { + return fmt.Errorf("failed to get address from Keybase: %w", err) + } + + addr, err = info.GetAddress() + if err != nil { + return fmt.Errorf("failed to get address from Keybase: %w", err) + } + } + + vestingStart, err := cmd.Flags().GetInt64(flagVestingStart) + if err != nil { + return err + } + vestingEnd, err := cmd.Flags().GetInt64(flagVestingEnd) + if err != nil { + return err + } + vestingAmtStr, err := cmd.Flags().GetString(flagVestingAmt) + if err != nil { + return err + } + + vestingAmt, err := sdk.ParseCoinsNormalized(vestingAmtStr) + if err != nil { + return fmt.Errorf("failed to parse vesting amount: %w", err) + } + + // create concrete account type based on input parameters + var genAccount authtypes.GenesisAccount + + balances := banktypes.Balance{Address: addr.String(), Coins: coins.Sort()} + baseAccount := authtypes.NewBaseAccount(addr, nil, 0, 0) + + if !vestingAmt.IsZero() { + baseVestingAccount, err := authvesting.NewBaseVestingAccount(baseAccount, vestingAmt.Sort(), vestingEnd) + if err != nil { + return fmt.Errorf("failed to create base vesting account: %w", err) + } + + if (balances.Coins.IsZero() && !baseVestingAccount.OriginalVesting.IsZero()) || + baseVestingAccount.OriginalVesting.IsAnyGT(balances.Coins) { + return errors.New("vesting amount cannot be greater than total amount") + } + + switch { + case vestingStart != 0 && vestingEnd != 0: + genAccount = authvesting.NewContinuousVestingAccountRaw(baseVestingAccount, vestingStart) + + case vestingEnd != 0: + genAccount = authvesting.NewDelayedVestingAccountRaw(baseVestingAccount) + + default: + return errors.New("invalid vesting parameters; must supply start and end time or end time") + } + } else { + genAccount = baseAccount + } + + if err := genAccount.Validate(); err != nil { + return fmt.Errorf("failed to validate new genesis account: %w", err) + } + + genFile := config.GenesisFile() + appState, genDoc, err := genutiltypes.GenesisStateFromGenFile(genFile) + if err != nil { + return fmt.Errorf("failed to unmarshal genesis states: %w", err) + } + + authGenState := authtypes.GetGenesisStateFromAppState(cdc, appState) + + accs, err := authtypes.UnpackAccounts(authGenState.Accounts) + if err != nil { + return fmt.Errorf("failed to get accounts from any: %w", err) + } + + if accs.Contains(addr) { + return fmt.Errorf("cannot add account at existing address %s", addr) + } + + // Add the new account to the set of genesis accounts and sanitize the + // accounts afterwards. + accs = append(accs, genAccount) + accs = authtypes.SanitizeGenesisAccounts(accs) + + genAccs, err := authtypes.PackAccounts(accs) + if err != nil { + return fmt.Errorf("failed to convert accounts into any's: %w", err) + } + authGenState.Accounts = genAccs + + authGenStateBz, err := cdc.MarshalJSON(&authGenState) + if err != nil { + return fmt.Errorf("failed to marshal auth genesis states: %w", err) + } + + appState[authtypes.ModuleName] = authGenStateBz + + bankGenState := banktypes.GetGenesisStateFromAppState(cdc, appState) + bankGenState.Balances = append(bankGenState.Balances, balances) + bankGenState.Balances = banktypes.SanitizeGenesisBalances(bankGenState.Balances) + + bankGenStateBz, err := cdc.MarshalJSON(bankGenState) + if err != nil { + return fmt.Errorf("failed to marshal bank genesis states: %w", err) + } + + appState[banktypes.ModuleName] = bankGenStateBz + + appStateJSON, err := json.Marshal(appState) + if err != nil { + return fmt.Errorf("failed to marshal application genesis states: %w", err) + } + + genDoc.AppState = appStateJSON + return genutil.ExportGenesisFile(genDoc, genFile) + }, + } + + cmd.Flags().String(flags.FlagKeyringBackend, flags.DefaultKeyringBackend, "Select keyring's backend (os|file|kwallet|pass|test)") + cmd.Flags().String(flags.FlagHome, defaultNodeHome, "The application home directory") + cmd.Flags().String(flagVestingAmt, "", "amount of coins for vesting accounts") + cmd.Flags().Int64(flagVestingStart, 0, "schedule start time (unix epoch) for vesting accounts") + cmd.Flags().Int64(flagVestingEnd, 0, "schedule end time (unix epoch) for vesting accounts") + flags.AddQueryFlagsToCmd(cmd) + + return cmd +} diff --git a/cmd/artelad/cmd/gencontract.go b/cmd/artelad/cmd/gencontract.go new file mode 100644 index 0000000..e8f9804 --- /dev/null +++ b/cmd/artelad/cmd/gencontract.go @@ -0,0 +1,153 @@ +package cmd + +import ( + "encoding/hex" + "encoding/json" + "errors" + "fmt" + "os" + + "github.com/spf13/cobra" + + "github.com/cosmos/cosmos-sdk/client" + "github.com/cosmos/cosmos-sdk/client/flags" + "github.com/cosmos/cosmos-sdk/server" + sdk "github.com/cosmos/cosmos-sdk/types" + authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" + "github.com/cosmos/cosmos-sdk/x/genutil" + genutiltypes "github.com/cosmos/cosmos-sdk/x/genutil/types" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/crypto" + + ethtypes "github.com/artela-network/artela-rollkit/ethereum/types" + evmtypes "github.com/artela-network/artela-rollkit/x/evm/types" +) + +// AddGenesisContractCmd returns add-genesis-contract cobra Command. +func AddGenesisContractCmd(defaultNodeHome string) *cobra.Command { + cmd := &cobra.Command{ + Use: "add-genesis-contract [contract_address_hex] [bin_runtime_code_hex/bin_runtime_code_path]", + Short: "Add a genesis contract to genesis.json", + Long: `Add a genesis contract to genesis.json. The provided contract must specify +the address and the bin-runtime code.`, + Args: cobra.ExactArgs(2), + RunE: func(cmd *cobra.Command, args []string) error { + clientCtx := client.GetClientContextFromCmd(cmd) + serverCtx := server.GetServerContextFromCmd(cmd) + + config := serverCtx.Config + config.SetRoot(clientCtx.HomeDir) + + rawAddr, err := hexutil.Decode(args[0]) + if err != nil { + return errors.New("invalid address, please input a valid ethereum format address") + } + + addr, err := sdk.AccAddressFromHexUnsafe(hex.EncodeToString(rawAddr)) + if err != nil { + return errors.New("unable to parse address") + } + + // load contract bin-runtime code + contractBin, err := hexutil.Decode(args[1]) + if err != nil { + contractBin, err = os.ReadFile(args[1]) + if err != nil { + return errors.New("failed to load contract bytecode") + } + } + + // create concrete account type based on input parameters + var genAccount *ethtypes.EthAccount + + balances := banktypes.Balance{Address: addr.String(), Coins: []sdk.Coin{}} + baseAccount := authtypes.NewBaseAccount(addr, nil, 0, 0) + + genAccount = ðtypes.EthAccount{ + BaseAccount: baseAccount, + CodeHash: crypto.Keccak256Hash(contractBin).Hex(), + } + + if err := genAccount.Validate(); err != nil { + return fmt.Errorf("failed to validate new genesis contract: %w", err) + } + + genFile := config.GenesisFile() + appState, genDoc, err := genutiltypes.GenesisStateFromGenFile(genFile) + if err != nil { + return fmt.Errorf("failed to unmarshal genesis state: %w", err) + } + + authGenState := authtypes.GetGenesisStateFromAppState(clientCtx.Codec, appState) + + accs, err := authtypes.UnpackAccounts(authGenState.Accounts) + if err != nil { + return fmt.Errorf("failed to get accounts from any: %w", err) + } + + if accs.Contains(addr) { + return fmt.Errorf("cannot add account at existing address %s", addr) + } + + // Add the new account to the set of genesis accounts and sanitize the + // accounts afterward. + accs = append(accs, genAccount) + accs = authtypes.SanitizeGenesisAccounts(accs) + + genAccs, err := authtypes.PackAccounts(accs) + if err != nil { + return fmt.Errorf("failed to convert accounts into any's: %w", err) + } + authGenState.Accounts = genAccs + + authGenStateBz, err := clientCtx.Codec.MarshalJSON(&authGenState) + if err != nil { + return fmt.Errorf("failed to marshal auth genesis state: %w", err) + } + + appState[authtypes.ModuleName] = authGenStateBz + + bankGenState := banktypes.GetGenesisStateFromAppState(clientCtx.Codec, appState) + bankGenState.Balances = append(bankGenState.Balances, balances) + bankGenState.Balances = banktypes.SanitizeGenesisBalances(bankGenState.Balances) + bankGenState.Supply = bankGenState.Supply.Add(balances.Coins...) + + bankGenStateBz, err := clientCtx.Codec.MarshalJSON(bankGenState) + if err != nil { + return fmt.Errorf("failed to marshal bank genesis state: %w", err) + } + appState[banktypes.ModuleName] = bankGenStateBz + + // generate evm state + var evmGenState evmtypes.GenesisState + if err := clientCtx.Codec.UnmarshalJSON(appState[evmtypes.ModuleName], &evmGenState); err != nil { + return err + } + + evmGenState.Accounts = append(evmGenState.Accounts, evmtypes.GenesisAccount{ + Address: genAccount.EthAddress().Hex(), + Code: hex.EncodeToString(contractBin), + }) + + evmGenStateBz, err := clientCtx.Codec.MarshalJSON(&evmGenState) + if err != nil { + return fmt.Errorf("failed to marshal bank genesis state: %w", err) + } + appState[evmtypes.ModuleName] = evmGenStateBz + + appStateJSON, err := json.Marshal(appState) + if err != nil { + return fmt.Errorf("failed to marshal application genesis state: %w", err) + } + + genDoc.AppState = appStateJSON + return genutil.ExportGenesisFile(genDoc, genFile) + }, + } + + cmd.Flags().String(flags.FlagHome, defaultNodeHome, "The application home directory") + flags.AddQueryFlagsToCmd(cmd) + + return cmd +} diff --git a/cmd/artelad/cmd/keyinfo.go b/cmd/artelad/cmd/keyinfo.go new file mode 100644 index 0000000..c8923f5 --- /dev/null +++ b/cmd/artelad/cmd/keyinfo.go @@ -0,0 +1,124 @@ +package cmd + +import ( + "crypto/ecdsa" + "encoding/hex" + "encoding/json" + "errors" + "fmt" + "os" + + "github.com/spf13/cobra" + + "github.com/cosmos/cosmos-sdk/crypto/keyring" + "github.com/cosmos/cosmos-sdk/version" + jose "github.com/dvsekhvalnov/jose2go" + "github.com/ethereum/go-ethereum/crypto" +) + +const ( + flagKeyinfoFile = "file" + flagKeyinfoPasswd = "passwd" +) + +// Item is a thing stored on the keyring +type Item struct { + Key string + Data []byte + Label string + Description string + + // Backend specific config + KeychainNotTrustApplication bool + KeychainNotSynchronizable bool +} + +func KeyInfoCmd() *cobra.Command { + cmd := &cobra.Command{ + Use: "keyinfo", + Short: "keyinfo retrieves private key and address", + Long: fmt.Sprintf(`Keyinfo print the private key and address to StdOut. + +Example: +$ %s keyinfo --file '/root/.artelad/keyring/mykey.info' --passwd 'test' +`, version.AppName), + Args: cobra.ExactArgs(0), + RunE: func(cmd *cobra.Command, args []string) error { + kfile, _ := cmd.Flags().GetString(flagKeyinfoFile) + kpasswd, _ := cmd.Flags().GetString(flagKeyinfoPasswd) + privKey, err := readKeyStore(kfile, kpasswd) + if err != nil { + return err + } + if len(privKey) != 34 { + return errors.New("read key store failed, priveKey length is not 34") + } + + privateKey, err := crypto.ToECDSA(privKey[2:]) + if err != nil { + return err + } + + privateKeyBytes := privateKey.D.Bytes() + privateKeyBytesPadded := make([]byte, 32) + copy(privateKeyBytesPadded[32-len(privateKeyBytes):], privateKeyBytes) + fmt.Printf("private key: 0x%s\n", hex.EncodeToString(privateKeyBytesPadded)) + + publicKey := privateKey.Public() + publicKeyECDSA, ok := publicKey.(*ecdsa.PublicKey) + if !ok { + return errors.New("error casting public key to ECDSA") + } + // publicKeyBytes := crypto.CompressPubkey(publicKeyECDSA) + // fmt.Println("public key: 0x", hex.EncodeToString(publicKeyBytes)) + + fromAddress := crypto.PubkeyToAddress(*publicKeyECDSA) + fmt.Printf("address: 0x%s\n", hex.EncodeToString(fromAddress[:])) + return nil + }, + } + + cmd.Flags().String(flagKeyinfoFile, "", "the fullpath of the keyinfo file") + cmd.Flags().String(flagKeyinfoPasswd, "", "the password of the keyinfo file") + + return cmd +} + +func readKeyStore(file string, passwd string) ([]byte, error) { + // Expand environment variables in the file path + file = os.ExpandEnv(file) + fmt.Printf("file: %s\n", file) + + bytes, err := os.ReadFile(file) + if os.IsNotExist(err) { + return nil, fmt.Errorf("file %s not found", file) + } else if err != nil { + return nil, err + } + + payload, _, err := jose.Decode(string(bytes), passwd) + if err != nil { + return nil, err + } + + decoded := &Item{} + err = json.Unmarshal([]byte(payload), decoded) + if err != nil { + return nil, err + } + + record, err := unmarshalRecord(decoded.Data) + if err != nil { + return nil, err + } + key := record.GetLocal().PrivKey + return key.Value, nil +} + +func unmarshalRecord(data []byte) (*keyring.Record, error) { + record := &keyring.Record{} + if err := record.Unmarshal(data); err != nil { + return nil, err + } + return record, nil +} diff --git a/ethereum/crypto/ethsecp256k1/keys.pb.go b/ethereum/crypto/ethsecp256k1/keys.pb.go index e6551ad..b6cfd5e 100644 --- a/ethereum/crypto/ethsecp256k1/keys.pb.go +++ b/ethereum/crypto/ethsecp256k1/keys.pb.go @@ -1,16 +1,15 @@ -// Code support by protoc-gen-gogo. DO NOT EDIT. -// source: artela/crypto/v1/ethsecp256k1/keys.proto +// Code generated by protoc-gen-gogo. DO NOT EDIT. +// source: artela/crypto/ethsecp256k1/keys.proto package ethsecp256k1 import ( - "fmt" - "io" - "math" - math_bits "math/bits" - + fmt "fmt" _ "github.com/cosmos/gogoproto/gogoproto" - "github.com/cosmos/gogoproto/proto" + proto "github.com/cosmos/gogoproto/proto" + io "io" + math "math" + math_bits "math/bits" ) // Reference imports to suppress errors if they are not otherwise used. @@ -18,7 +17,7 @@ var _ = proto.Marshal var _ = fmt.Errorf var _ = math.Inf -// This is a compile-time assertion to ensure that this support file +// This is a compile-time assertion to ensure that this generated file // is compatible with the proto package it is being compiled against. // A compilation error at this line likely means your copy of the // proto package needs to be updated. @@ -32,41 +31,41 @@ type PubKey struct { Key []byte `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"` } -func (pubKey *PubKey) Reset() { *pubKey = PubKey{} } +func (m *PubKey) Reset() { *m = PubKey{} } func (*PubKey) ProtoMessage() {} func (*PubKey) Descriptor() ([]byte, []int) { - return fileDescriptor_56b55ddbae0a9542, []int{0} + return fileDescriptor_d7f5413363a778b7, []int{0} } -func (pubKey *PubKey) XXX_Unmarshal(b []byte) error { - return pubKey.Unmarshal(b) +func (m *PubKey) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) } -func (pubKey *PubKey) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { +func (m *PubKey) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { if deterministic { - return xxx_messageInfo_PubKey.Marshal(b, pubKey, deterministic) + return xxx_messageInfo_PubKey.Marshal(b, m, deterministic) } else { b = b[:cap(b)] - n, err := pubKey.MarshalToSizedBuffer(b) + n, err := m.MarshalToSizedBuffer(b) if err != nil { return nil, err } return b[:n], nil } } -func (pubKey *PubKey) XXX_Merge(src proto.Message) { - xxx_messageInfo_PubKey.Merge(pubKey, src) +func (m *PubKey) XXX_Merge(src proto.Message) { + xxx_messageInfo_PubKey.Merge(m, src) } -func (pubKey *PubKey) XXX_Size() int { - return pubKey.Size() +func (m *PubKey) XXX_Size() int { + return m.Size() } -func (pubKey *PubKey) XXX_DiscardUnknown() { - xxx_messageInfo_PubKey.DiscardUnknown(pubKey) +func (m *PubKey) XXX_DiscardUnknown() { + xxx_messageInfo_PubKey.DiscardUnknown(m) } var xxx_messageInfo_PubKey proto.InternalMessageInfo -func (pubKey *PubKey) GetKey() []byte { - if pubKey != nil { - return pubKey.Key +func (m *PubKey) GetKey() []byte { + if m != nil { + return m.Key } return nil } @@ -78,126 +77,126 @@ type PrivKey struct { Key []byte `protobuf:"bytes,1,opt,name=key,proto3" json:"key,omitempty"` } -func (privKey *PrivKey) Reset() { *privKey = PrivKey{} } -func (privKey *PrivKey) String() string { return proto.CompactTextString(privKey) } -func (*PrivKey) ProtoMessage() {} +func (m *PrivKey) Reset() { *m = PrivKey{} } +func (m *PrivKey) String() string { return proto.CompactTextString(m) } +func (*PrivKey) ProtoMessage() {} func (*PrivKey) Descriptor() ([]byte, []int) { - return fileDescriptor_56b55ddbae0a9542, []int{1} + return fileDescriptor_d7f5413363a778b7, []int{1} } -func (privKey *PrivKey) XXX_Unmarshal(b []byte) error { - return privKey.Unmarshal(b) +func (m *PrivKey) XXX_Unmarshal(b []byte) error { + return m.Unmarshal(b) } -func (privKey *PrivKey) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { +func (m *PrivKey) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { if deterministic { - return xxx_messageInfo_PrivKey.Marshal(b, privKey, deterministic) + return xxx_messageInfo_PrivKey.Marshal(b, m, deterministic) } else { b = b[:cap(b)] - n, err := privKey.MarshalToSizedBuffer(b) + n, err := m.MarshalToSizedBuffer(b) if err != nil { return nil, err } return b[:n], nil } } -func (privKey *PrivKey) XXX_Merge(src proto.Message) { - xxx_messageInfo_PrivKey.Merge(privKey, src) +func (m *PrivKey) XXX_Merge(src proto.Message) { + xxx_messageInfo_PrivKey.Merge(m, src) } -func (privKey *PrivKey) XXX_Size() int { - return privKey.Size() +func (m *PrivKey) XXX_Size() int { + return m.Size() } -func (privKey *PrivKey) XXX_DiscardUnknown() { - xxx_messageInfo_PrivKey.DiscardUnknown(privKey) +func (m *PrivKey) XXX_DiscardUnknown() { + xxx_messageInfo_PrivKey.DiscardUnknown(m) } var xxx_messageInfo_PrivKey proto.InternalMessageInfo -func (privKey *PrivKey) GetKey() []byte { - if privKey != nil { - return privKey.Key +func (m *PrivKey) GetKey() []byte { + if m != nil { + return m.Key } return nil } func init() { - proto.RegisterType((*PubKey)(nil), "artela.crypto.v1.ethsecp256k1.PubKey") - proto.RegisterType((*PrivKey)(nil), "artela.crypto.v1.ethsecp256k1.PrivKey") + proto.RegisterType((*PubKey)(nil), "artela.crypto.ethsecp256k1.PubKey") + proto.RegisterType((*PrivKey)(nil), "artela.crypto.ethsecp256k1.PrivKey") } func init() { - proto.RegisterFile("artela/crypto/v1/ethsecp256k1/keys.proto", fileDescriptor_56b55ddbae0a9542) + proto.RegisterFile("artela/crypto/ethsecp256k1/keys.proto", fileDescriptor_d7f5413363a778b7) } -var fileDescriptor_56b55ddbae0a9542 = []byte{ - // 204 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xd2, 0x48, 0x2c, 0x2a, 0x49, - 0xcd, 0x49, 0xd4, 0x4f, 0x2e, 0xaa, 0x2c, 0x28, 0xc9, 0xd7, 0x2f, 0x33, 0xd4, 0x4f, 0x2d, 0xc9, - 0x28, 0x4e, 0x4d, 0x2e, 0x30, 0x32, 0x35, 0xcb, 0x36, 0xd4, 0xcf, 0x4e, 0xad, 0x2c, 0xd6, 0x2b, - 0x28, 0xca, 0x2f, 0xc9, 0x17, 0x92, 0x85, 0xa8, 0xd4, 0x83, 0xa8, 0xd4, 0x2b, 0x33, 0xd4, 0x43, - 0x56, 0x29, 0x25, 0x92, 0x9e, 0x9f, 0x9e, 0x0f, 0x56, 0xa9, 0x0f, 0x62, 0x41, 0x34, 0x29, 0x29, - 0x70, 0xb1, 0x05, 0x94, 0x26, 0x79, 0xa7, 0x56, 0x0a, 0x09, 0x70, 0x31, 0x67, 0xa7, 0x56, 0x4a, - 0x30, 0x2a, 0x30, 0x6a, 0xf0, 0x04, 0x81, 0x98, 0x56, 0x2c, 0x33, 0x16, 0xc8, 0x33, 0x28, 0x49, - 0x73, 0xb1, 0x07, 0x14, 0x65, 0x96, 0x61, 0x55, 0xe2, 0x14, 0x75, 0xe2, 0x91, 0x1c, 0xe3, 0x85, - 0x47, 0x72, 0x8c, 0x0f, 0x1e, 0xc9, 0x31, 0x4e, 0x78, 0x2c, 0xc7, 0x70, 0xe1, 0xb1, 0x1c, 0xc3, - 0x8d, 0xc7, 0x72, 0x0c, 0x51, 0x0e, 0xe9, 0x99, 0x25, 0x19, 0xa5, 0x49, 0x7a, 0xc9, 0xf9, 0xb9, - 0xfa, 0x10, 0x87, 0xe9, 0xe6, 0xa5, 0x96, 0x94, 0xe7, 0x17, 0x65, 0x43, 0xb9, 0x50, 0xaf, 0xa4, - 0x16, 0xa5, 0x96, 0xe6, 0xc2, 0x7c, 0x87, 0xec, 0xe0, 0x24, 0x36, 0xb0, 0x0b, 0x8d, 0x01, 0x01, - 0x00, 0x00, 0xff, 0xff, 0x8e, 0xb4, 0xc3, 0x6c, 0x02, 0x01, 0x00, 0x00, +var fileDescriptor_d7f5413363a778b7 = []byte{ + // 203 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x52, 0x4d, 0x2c, 0x2a, 0x49, + 0xcd, 0x49, 0xd4, 0x4f, 0x2e, 0xaa, 0x2c, 0x28, 0xc9, 0xd7, 0x4f, 0x2d, 0xc9, 0x28, 0x4e, 0x4d, + 0x2e, 0x30, 0x32, 0x35, 0xcb, 0x36, 0xd4, 0xcf, 0x4e, 0xad, 0x2c, 0xd6, 0x2b, 0x28, 0xca, 0x2f, + 0xc9, 0x17, 0x92, 0x82, 0x28, 0xd3, 0x83, 0x28, 0xd3, 0x43, 0x56, 0x26, 0x25, 0x92, 0x9e, 0x9f, + 0x9e, 0x0f, 0x56, 0xa6, 0x0f, 0x62, 0x41, 0x74, 0x28, 0x29, 0x70, 0xb1, 0x05, 0x94, 0x26, 0x79, + 0xa7, 0x56, 0x0a, 0x09, 0x70, 0x31, 0x67, 0xa7, 0x56, 0x4a, 0x30, 0x2a, 0x30, 0x6a, 0xf0, 0x04, + 0x81, 0x98, 0x56, 0x2c, 0x33, 0x16, 0xc8, 0x33, 0x28, 0x49, 0x73, 0xb1, 0x07, 0x14, 0x65, 0x96, + 0x61, 0x55, 0xe2, 0x14, 0x7f, 0xe2, 0x91, 0x1c, 0xe3, 0x85, 0x47, 0x72, 0x8c, 0x0f, 0x1e, 0xc9, + 0x31, 0x4e, 0x78, 0x2c, 0xc7, 0x70, 0xe1, 0xb1, 0x1c, 0xc3, 0x8d, 0xc7, 0x72, 0x0c, 0x51, 0xae, + 0xe9, 0x99, 0x25, 0x19, 0xa5, 0x49, 0x7a, 0xc9, 0xf9, 0xb9, 0xfa, 0x10, 0x57, 0xe9, 0xe6, 0xa5, + 0x96, 0x94, 0xe7, 0x17, 0x65, 0xc3, 0xb8, 0x45, 0xf9, 0x39, 0x39, 0xd9, 0x99, 0x25, 0x20, 0xcf, + 0xa4, 0x16, 0xa5, 0x96, 0xe6, 0x62, 0xf3, 0x5c, 0x12, 0x1b, 0xd8, 0x99, 0xc6, 0x80, 0x00, 0x00, + 0x00, 0xff, 0xff, 0xc0, 0x14, 0x59, 0x07, 0x01, 0x01, 0x00, 0x00, } -func (pubKey *PubKey) Marshal() (dAtA []byte, err error) { - size := pubKey.Size() +func (m *PubKey) Marshal() (dAtA []byte, err error) { + size := m.Size() dAtA = make([]byte, size) - n, err := pubKey.MarshalToSizedBuffer(dAtA[:size]) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) if err != nil { return nil, err } return dAtA[:n], nil } -func (pubKey *PubKey) MarshalTo(dAtA []byte) (int, error) { - size := pubKey.Size() - return pubKey.MarshalToSizedBuffer(dAtA[:size]) +func (m *PubKey) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) } -func (pubKey *PubKey) MarshalToSizedBuffer(dAtA []byte) (int, error) { +func (m *PubKey) MarshalToSizedBuffer(dAtA []byte) (int, error) { i := len(dAtA) _ = i var l int _ = l - if len(pubKey.Key) > 0 { - i -= len(pubKey.Key) - copy(dAtA[i:], pubKey.Key) - i = encodeVarintKeys(dAtA, i, uint64(len(pubKey.Key))) + if len(m.Key) > 0 { + i -= len(m.Key) + copy(dAtA[i:], m.Key) + i = encodeVarintKeys(dAtA, i, uint64(len(m.Key))) i-- dAtA[i] = 0xa } return len(dAtA) - i, nil } -func (privKey *PrivKey) Marshal() (dAtA []byte, err error) { - size := privKey.Size() +func (m *PrivKey) Marshal() (dAtA []byte, err error) { + size := m.Size() dAtA = make([]byte, size) - n, err := privKey.MarshalToSizedBuffer(dAtA[:size]) + n, err := m.MarshalToSizedBuffer(dAtA[:size]) if err != nil { return nil, err } return dAtA[:n], nil } -func (privKey *PrivKey) MarshalTo(dAtA []byte) (int, error) { - size := privKey.Size() - return privKey.MarshalToSizedBuffer(dAtA[:size]) +func (m *PrivKey) MarshalTo(dAtA []byte) (int, error) { + size := m.Size() + return m.MarshalToSizedBuffer(dAtA[:size]) } -func (privKey *PrivKey) MarshalToSizedBuffer(dAtA []byte) (int, error) { +func (m *PrivKey) MarshalToSizedBuffer(dAtA []byte) (int, error) { i := len(dAtA) _ = i var l int _ = l - if len(privKey.Key) > 0 { - i -= len(privKey.Key) - copy(dAtA[i:], privKey.Key) - i = encodeVarintKeys(dAtA, i, uint64(len(privKey.Key))) + if len(m.Key) > 0 { + i -= len(m.Key) + copy(dAtA[i:], m.Key) + i = encodeVarintKeys(dAtA, i, uint64(len(m.Key))) i-- dAtA[i] = 0xa } @@ -215,26 +214,26 @@ func encodeVarintKeys(dAtA []byte, offset int, v uint64) int { dAtA[offset] = uint8(v) return base } -func (pubKey *PubKey) Size() (n int) { - if pubKey == nil { +func (m *PubKey) Size() (n int) { + if m == nil { return 0 } var l int _ = l - l = len(pubKey.Key) + l = len(m.Key) if l > 0 { n += 1 + l + sovKeys(uint64(l)) } return n } -func (privKey *PrivKey) Size() (n int) { - if privKey == nil { +func (m *PrivKey) Size() (n int) { + if m == nil { return 0 } var l int _ = l - l = len(privKey.Key) + l = len(m.Key) if l > 0 { n += 1 + l + sovKeys(uint64(l)) } @@ -247,7 +246,7 @@ func sovKeys(x uint64) (n int) { func sozKeys(x uint64) (n int) { return sovKeys(uint64((x << 1) ^ uint64((int64(x) >> 63)))) } -func (pubKey *PubKey) Unmarshal(dAtA []byte) error { +func (m *PubKey) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -305,9 +304,9 @@ func (pubKey *PubKey) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - pubKey.Key = append(pubKey.Key[:0], dAtA[iNdEx:postIndex]...) - if pubKey.Key == nil { - pubKey.Key = []byte{} + m.Key = append(m.Key[:0], dAtA[iNdEx:postIndex]...) + if m.Key == nil { + m.Key = []byte{} } iNdEx = postIndex default: @@ -331,7 +330,7 @@ func (pubKey *PubKey) Unmarshal(dAtA []byte) error { } return nil } -func (privKey *PrivKey) Unmarshal(dAtA []byte) error { +func (m *PrivKey) Unmarshal(dAtA []byte) error { l := len(dAtA) iNdEx := 0 for iNdEx < l { @@ -389,9 +388,9 @@ func (privKey *PrivKey) Unmarshal(dAtA []byte) error { if postIndex > l { return io.ErrUnexpectedEOF } - privKey.Key = append(privKey.Key[:0], dAtA[iNdEx:postIndex]...) - if privKey.Key == nil { - privKey.Key = []byte{} + m.Key = append(m.Key[:0], dAtA[iNdEx:postIndex]...) + if m.Key == nil { + m.Key = []byte{} } iNdEx = postIndex default: diff --git a/ethereum/types/coin.go b/ethereum/types/coin.go index 330a95e..13a7bd3 100644 --- a/ethereum/types/coin.go +++ b/ethereum/types/coin.go @@ -15,7 +15,7 @@ const ( // - Governance parameters: denomination used for spam prevention in proposal deposits // - Crisis parameters: constant fee denomination used for spam prevention to check broken invariant // - EVM parameters: denomination used for running EVM states transitions in Artela. - AttoArtela string = "uart" + AttoArtela string = "aart" // BaseDenomUnit defines the base denomination unit for Artela. // 1 art = 1x10^{BaseDenomUnit} uart diff --git a/go.mod b/go.mod index 72b712c..1c447a2 100644 --- a/go.mod +++ b/go.mod @@ -42,10 +42,12 @@ require ( github.com/cosmos/cosmos-db v1.0.2 github.com/cosmos/cosmos-proto v1.0.0-beta.5 github.com/cosmos/cosmos-sdk v0.50.6 + github.com/cosmos/go-bip39 v1.0.0 github.com/cosmos/gogoproto v1.5.0 github.com/cosmos/ibc-go/modules/capability v1.0.0 github.com/cosmos/ibc-go/v8 v8.2.0 github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc + github.com/dvsekhvalnov/jose2go v1.6.0 github.com/emirpasic/gods v1.18.1 github.com/ethereum/go-ethereum v1.12.0 github.com/golang/protobuf v1.5.4 @@ -75,6 +77,7 @@ require ( google.golang.org/grpc v1.65.0 google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.3.0 google.golang.org/protobuf v1.34.2 + sigs.k8s.io/yaml v1.4.0 ) require ( @@ -125,7 +128,6 @@ require ( github.com/containerd/stargz-snapshotter/estargz v0.15.1 // indirect github.com/coreos/go-systemd/v22 v22.5.0 // indirect github.com/cosmos/btcutil v1.0.5 // indirect - github.com/cosmos/go-bip39 v1.0.0 // indirect github.com/cosmos/gogogateway v1.2.0 // indirect github.com/cosmos/iavl v1.1.2 // indirect github.com/cosmos/ics23/go v0.10.0 // indirect @@ -150,7 +152,6 @@ require ( github.com/docker/go-connections v0.5.0 // indirect github.com/docker/go-units v0.5.0 // indirect github.com/dustin/go-humanize v1.0.1 // indirect - github.com/dvsekhvalnov/jose2go v1.6.0 // indirect github.com/elastic/gosigar v0.14.2 // indirect github.com/emicklei/dot v1.6.1 // indirect github.com/fatih/color v1.15.0 // indirect @@ -395,5 +396,4 @@ require ( lukechampine.com/blake3 v1.2.1 // indirect nhooyr.io/websocket v1.8.7 // indirect pgregory.net/rapid v1.1.0 // indirect - sigs.k8s.io/yaml v1.4.0 // indirect ) diff --git a/init.sh b/init.sh new file mode 100755 index 0000000..25b73a7 --- /dev/null +++ b/init.sh @@ -0,0 +1,147 @@ +#!/bin/bash + +KEY="mykey" +KEY2="mykey2" +KEY3="mykey3" +KEY4="mykey4" + +CHAINID="artroll_11820-1" +MONIKER="localtestnet" +KEYRING="test" +KEYALGO="eth_secp256k1" +LOGLEVEL="debug" +# trace evm +TRACE="--trace" +# TRACE="" + +export PATH=./:./build:$PATH + +# validate dependencies are installed +command -v jq >/dev/null 2>&1 || { + echo >&2 "jq not installed. More info: https://stedolan.github.io/jq/download/" + exit 1 +} + +# remove existing daemon and client +folder_path="$HOME/.artroll" +echo folder_path +if [ -d "$folder_path" ]; then + read -p "Are you sure you want to delete the folder '$folder_path' ? (y/n): " confirm + + if [ "$confirm" == "y" ]; then + rm -rf "$folder_path" + echo "The folder has been deleted." + else + echo "Operation canceled." + exit 1 + fi +fi + +echo artela-rollkitd config set client keyring-backend $KEYRING +artela-rollkitd config set client keyring-backend $KEYRING +echo artela-rollkitd config set client chain-id $CHAINID +artela-rollkitd config set client chain-id $CHAINID + +# if $KEY exists it should be deleted +artela-rollkitd keys add $KEY --keyring-backend $KEYRING --algo $KEYALGO +artela-rollkitd keys add $KEY2 --keyring-backend $KEYRING --algo $KEYALGO +artela-rollkitd keys add $KEY3 --keyring-backend $KEYRING --algo $KEYALGO +artela-rollkitd keys add $KEY4 --keyring-backend $KEYRING --algo $KEYALGO + +# Set moniker and chain-id for artela (Moniker can be anything, chain-id must be an integer) +echo artela-rollkitd init $MONIKER --chain-id $CHAINID +artela-rollkitd init $MONIKER --chain-id $CHAINID + +# Change parameter token denominations to aart +cat $HOME/.artroll/config/genesis.json | jq '.app_state["staking"]["params"]["bond_denom"]="aart"' >$HOME/.artroll/config/tmp_genesis.json && mv $HOME/.artroll/config/tmp_genesis.json $HOME/.artroll/config/genesis.json +cat $HOME/.artroll/config/genesis.json | jq '.app_state["crisis"]["constant_fee"]["denom"]="aart"' >$HOME/.artroll/config/tmp_genesis.json && mv $HOME/.artroll/config/tmp_genesis.json $HOME/.artroll/config/genesis.json +cat $HOME/.artroll/config/genesis.json | jq '.app_state["gov"]["deposit_params"]["min_deposit"][0]["denom"]="aart"' >$HOME/.artroll/config/tmp_genesis.json && mv $HOME/.artroll/config/tmp_genesis.json $HOME/.artroll/config/genesis.json +cat $HOME/.artroll/config/genesis.json | jq '.app_state["gov"]["params"]["min_deposit"][0]["denom"]="aart"' >$HOME/.artroll/config/tmp_genesis.json && mv $HOME/.artroll/config/tmp_genesis.json $HOME/.artroll/config/genesis.json +cat $HOME/.artroll/config/genesis.json | jq '.app_state["mint"]["params"]["mint_denom"]="aart"' >$HOME/.artroll/config/tmp_genesis.json && mv $HOME/.artroll/config/tmp_genesis.json $HOME/.artroll/config/genesis.json + +# Set gas limit in genesis +cat $HOME/.artroll/config/genesis.json | jq '.consensus_params["block"]["max_gas"]="20000000"' >$HOME/.artroll/config/tmp_genesis.json && mv $HOME/.artroll/config/tmp_genesis.json $HOME/.artroll/config/genesis.json +cat $HOME/.artroll/config/genesis.json | jq '.app_state["evm"]["params"]["extra_eips"]=[3855]' >$HOME/.artroll/config/tmp_genesis.json && mv $HOME/.artroll/config/tmp_genesis.json $HOME/.artroll/config/genesis.json + +# Enable unprotected txs +cat $HOME/.artroll/config/genesis.json | jq '.app_state["evm"]["params"]["allow_unprotected_txs"]=true' >$HOME/.artroll/config/tmp_genesis.json && mv $HOME/.artroll/config/tmp_genesis.json $HOME/.artroll/config/genesis.json + +# Allocate genesis contract +artela-rollkitd add-genesis-contract 0x000000000000000000000000000000000000AAEC 0x60806040526004361015610023575b361561001957600080fd5b610021615531565b005b60003560e01c80630396cb60146101b35780630bd28e3b146101aa5780631b2e01b8146101a15780631d732756146101985780631fad948c1461018f578063205c28781461018657806335567e1a1461017d5780634b1d7cf5146101745780635287ce121461016b57806370a08231146101625780638f41ec5a14610159578063957122ab146101505780639b249f6914610147578063a61935311461013e578063b760faf914610135578063bb9fe6bf1461012c578063c23a5cea14610123578063d6383f941461011a578063ee219423146101115763fc7e286d0361000e5761010c611bcd565b61000e565b5061010c6119b5565b5061010c61184d565b5061010c6116b4565b5061010c611536565b5061010c6114f7565b5061010c6114d6565b5061010c611337565b5061010c611164565b5061010c611129565b5061010c6110a4565b5061010c610f54565b5061010c610bf8565b5061010c610b33565b5061010c610994565b5061010c6108ba565b5061010c6106e7565b5061010c610467565b5061010c610385565b5060207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595760043563ffffffff8116808203610359576103547fa5ae833d0bb1dcd632d98a8b70973e8516812898e19bf27b70071ebc8dc52c01916102716102413373ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b9161024d811515615697565b61026a610261600185015463ffffffff1690565b63ffffffff1690565b11156156fc565b54926103366dffffffffffffffffffffffffffff946102f461029834888460781c166121d5565b966102a4881515615761565b6102b0818911156157c6565b6102d4816102bc6105ec565b941684906dffffffffffffffffffffffffffff169052565b6001602084015287166dffffffffffffffffffffffffffff166040830152565b63ffffffff83166060820152600060808201526103313373ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b61582b565b6040805194855263ffffffff90911660208501523393918291820190565b0390a2005b600080fd5b6024359077ffffffffffffffffffffffffffffffffffffffffffffffff8216820361035957565b50346103595760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595760043577ffffffffffffffffffffffffffffffffffffffffffffffff81168103610359576104149033600052600160205260406000209077ffffffffffffffffffffffffffffffffffffffffffffffff16600052602052604060002090565b61041e8154612491565b9055005b73ffffffffffffffffffffffffffffffffffffffff81160361035957565b6024359061044d82610422565b565b60c4359061044d82610422565b359061044d82610422565b50346103595760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595760206104fc6004356104a881610422565b73ffffffffffffffffffffffffffffffffffffffff6104c561035e565b91166000526001835260406000209077ffffffffffffffffffffffffffffffffffffffffffffffff16600052602052604060002090565b54604051908152f35b507f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60a0810190811067ffffffffffffffff82111761055157604052565b610559610505565b604052565b610100810190811067ffffffffffffffff82111761055157604052565b67ffffffffffffffff811161055157604052565b6060810190811067ffffffffffffffff82111761055157604052565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff82111761055157604052565b6040519061044d82610535565b6040519060c0820182811067ffffffffffffffff82111761055157604052565b604051906040820182811067ffffffffffffffff82111761055157604052565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f60209267ffffffffffffffff8111610675575b01160190565b61067d610505565b61066f565b92919261068e82610639565b9161069c60405193846105ab565b829481845281830111610359578281602093846000960137010152565b9181601f840112156103595782359167ffffffffffffffff8311610359576020838186019501011161035957565b5034610359576101c07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595767ffffffffffffffff60043581811161035957366023820112156103595761074a903690602481600401359101610682565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffdc36016101808112610359576101006040519161078783610535565b12610359576040516107988161055e565b6107a0610440565b815260443560208201526064356040820152608435606082015260a43560808201526107ca61044f565b60a082015260e43560c08201526101043560e082015281526101243560208201526101443560408201526101643560608201526101843560808201526101a4359182116103595761083e9261082661082e9336906004016106b9565b9290916128b1565b6040519081529081906020820190565b0390f35b9060407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc8301126103595760043567ffffffffffffffff9283821161035957806023830112156103595781600401359384116103595760248460051b830101116103595760240191906024356108b781610422565b90565b5034610359576108c936610842565b6108d4929192611e3a565b6108dd83611d2d565b60005b84811061095d57506000927fbb47ee3e183a558b1a2ff0874b079f3fc5478b7454eacf2bfc5af2ff5878f9728480a183915b85831061092d576109238585611ed7565b6100216001600255565b909193600190610953610941878987611dec565b61094b8886611dca565b51908861233f565b0194019190610912565b8061098b610984610972600194869896611dca565b5161097e848a88611dec565b84613448565b9083612f30565b019290926108e0565b50346103595760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610359576004356109d081610422565b6024359060009133835282602052604083206dffffffffffffffffffffffffffff81541692838311610ad557848373ffffffffffffffffffffffffffffffffffffffff829593610a788496610a3f610a2c8798610ad29c6121c0565b6dffffffffffffffffffffffffffff1690565b6dffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffff0000000000000000000000000000825416179055565b6040805173ffffffffffffffffffffffffffffffffffffffff831681526020810185905233917fd1c19fbcd4551a5edfb66d43d2e337c04837afda3482b42bdf569a8fccdae5fb91a2165af1610acc611ea7565b50615ba2565b80f35b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f576974686472617720616d6f756e7420746f6f206c61726765000000000000006044820152fd5b50346103595760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610359576020600435610b7181610422565b73ffffffffffffffffffffffffffffffffffffffff610b8e61035e565b911660005260018252610bc98160406000209077ffffffffffffffffffffffffffffffffffffffffffffffff16600052602052604060002090565b547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000006040519260401b16178152f35b503461035957610c0736610842565b610c0f611e3a565b6000805b838210610df657610c249150611d2d565b7fbb47ee3e183a558b1a2ff0874b079f3fc5478b7454eacf2bfc5af2ff5878f972600080a16000805b848110610d5c57505060008093815b818110610c9357610923868660007f575ff3acadd5ab348fe1855e217e0f3678f8d767d7494c9f9fefbee2e17cca4d8180a2611ed7565b610cf7610ca182848a6124cb565b610ccc610cb3610cb36020840161256d565b73ffffffffffffffffffffffffffffffffffffffff1690565b7f575ff3acadd5ab348fe1855e217e0f3678f8d767d7494c9f9fefbee2e17cca4d600080a280612519565b906000915b808310610d1457505050610d0f90612491565b610c5c565b90919497610d4f610d49610d5592610d438c8b610d3c82610d368e8b8d611dec565b92611dca565b519161233f565b906121d5565b99612491565b95612491565b9190610cfc565b610d678186886124cb565b6020610d7f610d768380612519565b9290930161256d565b9173ffffffffffffffffffffffffffffffffffffffff60009316905b828410610db45750505050610daf90612491565b610c4d565b90919294610d4f81610de985610de2610dd0610dee968d611dca565b51610ddc8c8b8a611dec565b85613448565b908b613148565b612491565b929190610d9b565b610e018285876124cb565b90610e0c8280612519565b92610e1c610cb36020830161256d565b9173ffffffffffffffffffffffffffffffffffffffff8316610e416001821415612577565b610e62575b505050610e5c91610e56916121d5565b91612491565b90610c13565b909592610e7b6040999693999895989788810190611fc8565b92908a3b156103595789938b918a5193849283927fe3563a4f00000000000000000000000000000000000000000000000000000000845260049e8f850193610ec294612711565b03815a93600094fa9081610f3b575b50610f255786517f86a9f75000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8a16818a0190815281906020010390fd5b0390fd5b9497509295509093509181610e56610e5c610e46565b80610f48610f4e9261057b565b8061111e565b38610ed1565b50346103595760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595761083e73ffffffffffffffffffffffffffffffffffffffff600435610fa881610422565b608060409283928351610fba81610535565b60009381858093528260208201528287820152826060820152015216815280602052209061104965ffffffffffff6001835194610ff686610535565b80546dffffffffffffffffffffffffffff8082168852607082901c60ff161515602089015260789190911c1685870152015463ffffffff8116606086015260201c16608084019065ffffffffffff169052565b5191829182919091608065ffffffffffff8160a08401956dffffffffffffffffffffffffffff808251168652602082015115156020870152604082015116604086015263ffffffff6060820151166060860152015116910152565b50346103595760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595773ffffffffffffffffffffffffffffffffffffffff6004356110f581610422565b16600052600060205260206dffffffffffffffffffffffffffff60406000205416604051908152f35b600091031261035957565b50346103595760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261035957602060405160018152f35b50346103595760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261035957600467ffffffffffffffff8135818111610359576111b590369084016106b9565b9050602435916111c483610422565b604435908111610359576111db90369085016106b9565b92909115908161132d575b506112c6576014821015611236575b610f21836040519182917f08c379a0000000000000000000000000000000000000000000000000000000008352820160409060208152600060208201520190565b6112466112529261124c92612b88565b90612b96565b60601c90565b3b1561125f5738806111f5565b610f21906040519182917f08c379a0000000000000000000000000000000000000000000000000000000008352820160609060208152601b60208201527f41413330207061796d6173746572206e6f74206465706c6f796564000000000060408201520190565b610f21836040519182917f08c379a0000000000000000000000000000000000000000000000000000000008352820160609060208152601960208201527f41413230206163636f756e74206e6f74206465706c6f7965640000000000000060408201520190565b90503b15386111e6565b50346103595760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595760043567ffffffffffffffff81116103595761138960249136906004016106b9565b906113bf6040519283927f570e1a3600000000000000000000000000000000000000000000000000000000845260048401612d2c565b0360208273ffffffffffffffffffffffffffffffffffffffff92816000857f0000000000000000000000000000000000000000000000000000000000000000165af1918215611471575b600092611441575b50604051917f6ca7b806000000000000000000000000000000000000000000000000000000008352166004820152fd5b61146391925060203d811161146a575b61145b81836105ab565b810190612d17565b9038611411565b503d611451565b611479612183565b611409565b90816101609103126103595790565b60207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc820112610359576004359067ffffffffffffffff8211610359576108b79160040161147e565b50346103595760206114ef6114ea3661148d565b612a0c565b604051908152f35b5060207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595761002160043561153181610422565b61562b565b5034610359576000807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126116b1573381528060205260408120600181019063ffffffff825416908115611653576115f06115b5611618936115a76115a2855460ff9060701c1690565b61598f565b65ffffffffffff42166159f4565b84547fffffffffffffffffffffffffffffffffffffffffffff000000000000ffffffff16602082901b69ffffffffffff000000001617909455565b7fffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffff8154169055565b60405165ffffffffffff91909116815233907ffa9b3c14cc825c412c9ed81b3ba365a5b459439403f18829e572ed53a4180f0a90602090a280f35b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600a60248201527f6e6f74207374616b6564000000000000000000000000000000000000000000006044820152fd5b80fd5b50346103595760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610359576004356116f081610422565b610ad273ffffffffffffffffffffffffffffffffffffffff6117323373ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b926117ea611755610a2c86546dffffffffffffffffffffffffffff9060781c1690565b94611761861515615a0e565b6117c26001820161179a65ffffffffffff611786835465ffffffffffff9060201c1690565b16611792811515615a73565b421015615ad8565b80547fffffffffffffffffffffffffffffffffffffffffffff00000000000000000000169055565b7fffffff0000000000000000000000000000ffffffffffffffffffffffffffffff8154169055565b6040805173ffffffffffffffffffffffffffffffffffffffff831681526020810186905233917fb7c918e0e249f999e965cafeb6c664271b3f4317d296461500e71da39f0cbda391a2600080809581948294165af1611847611ea7565b50615b3d565b50346103595760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595767ffffffffffffffff6004358181116103595761189e90369060040161147e565b602435916118ab83610422565b604435908111610359576118c6610f219136906004016106b9565b6118ce611caa565b6118d785612e2b565b6118ea6118e48287613240565b906153ba565b946118fa826000924384526121e2565b96438252819360609573ffffffffffffffffffffffffffffffffffffffff8316611981575b50505050608001519361194e6040611940602084015165ffffffffffff1690565b92015165ffffffffffff1690565b906040519687967f8b7ac980000000000000000000000000000000000000000000000000000000008852600488016127e1565b8395508394965061199b60409492939451809481936127d3565b03925af19060806119aa611ea7565b92919038808061191f565b5034610359576119c43661148d565b6119cc611caa565b6119d582612e2b565b6119df8183613240565b825160a00151919391611a0c9073ffffffffffffffffffffffffffffffffffffffff166154dc565b6154dc565b90611a30611a07855173ffffffffffffffffffffffffffffffffffffffff90511690565b94611a39612b50565b50611a68611a4c60409586810190611fc8565b90600060148310611bc55750611246611a079261124c92612b88565b91611a72916153ba565b805173ffffffffffffffffffffffffffffffffffffffff169073ffffffffffffffffffffffffffffffffffffffff821660018114916080880151978781015191886020820151611ac79065ffffffffffff1690565b91015165ffffffffffff16916060015192611ae06105f9565b9a8b5260208b0152841515898b015265ffffffffffff1660608a015265ffffffffffff16608089015260a088015215159081611bbc575b50611b515750610f2192519485947fe0cff05f00000000000000000000000000000000000000000000000000000000865260048601612cbd565b9190610f2193611b60846154dc565b611b87611b6b610619565b73ffffffffffffffffffffffffffffffffffffffff9096168652565b6020850152519586957ffaecb4e400000000000000000000000000000000000000000000000000000000875260048701612c2b565b90501538611b17565b9150506154dc565b50346103595760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126103595773ffffffffffffffffffffffffffffffffffffffff600435611c1e81610422565b16600052600060205260a0604060002065ffffffffffff60018254920154604051926dffffffffffffffffffffffffffff90818116855260ff8160701c161515602086015260781c16604084015263ffffffff8116606084015260201c166080820152f35b60209067ffffffffffffffff8111611c9d575b60051b0190565b611ca5610505565b611c96565b60405190611cb782610535565b604051608083610100830167ffffffffffffffff811184821017611d20575b60405260009283815283602082015283604082015283606082015283838201528360a08201528360c08201528360e082015281528260208201528260408201528260608201520152565b611d28610505565b611cd6565b90611d3782611c83565b611d4460405191826105ab565b8281527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0611d728294611c83565b019060005b828110611d8357505050565b602090611d8e611caa565b82828501015201611d77565b507f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6020918151811015611ddf575b60051b010190565b611de7611d9a565b611dd7565b9190811015611e2d575b60051b810135907ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffea181360301821215610359570190565b611e35611d9a565b611df6565b6002805414611e495760028055565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152fd5b3d15611ed2573d90611eb882610639565b91611ec660405193846105ab565b82523d6000602084013e565b606090565b73ffffffffffffffffffffffffffffffffffffffff168015611f6a57600080809381935af1611f04611ea7565b5015611f0c57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f41413931206661696c65642073656e6420746f2062656e6566696369617279006044820152fd5b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f4141393020696e76616c69642062656e656669636961727900000000000000006044820152fd5b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe181360301821215610359570180359067ffffffffffffffff82116103595760200191813603831361035957565b90816020910312610359575190565b601f82602094937fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0938186528686013760008582860101520116010190565b60005b83811061207a5750506000910152565b818101518382015260200161206a565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f6020936120c681518092818752878088019101612067565b0116010190565b906120e76080916108b796946101c0808652850191612028565b9360e0815173ffffffffffffffffffffffffffffffffffffffff80825116602087015260208201516040870152604082015160608701526060820151858701528482015160a087015260a08201511660c086015260c081015182860152015161010084015260208101516101208401526040810151610140840152606081015161016084015201516101808201526101a081840391015261208a565b506040513d6000823e3d90fd5b507f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b919082039182116121cd57565b61044d612190565b919082018092116121cd57565b905a918160206121fb6060830151936060810190611fc8565b906122348560405195869485947f1d732756000000000000000000000000000000000000000000000000000000008652600486016120cd565b03816000305af16000918161230f575b50612308575060206000803e7fdeaddead000000000000000000000000000000000000000000000000000000006000511461229b5761229561228a6108b7945a906121c0565b6080840151906121d5565b91614afc565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152600f60408201527f41413935206f7574206f6620676173000000000000000000000000000000000060608201520190565b9250505090565b61233191925060203d8111612338575b61232981836105ab565b810190612019565b9038612244565b503d61231f565b909291925a9380602061235b6060830151946060810190611fc8565b906123948660405195869485947f1d732756000000000000000000000000000000000000000000000000000000008652600486016120cd565b03816000305af160009181612471575b5061246a575060206000803e7fdeaddead00000000000000000000000000000000000000000000000000000000600051146123fc576123f66123eb6108b795965a906121c0565b6080830151906121d5565b92614ddf565b610f21836040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152600f60408201527f41413935206f7574206f6620676173000000000000000000000000000000000060608201520190565b9450505050565b61248a91925060203d81116123385761232981836105ab565b90386123a4565b6001907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81146124bf570190565b6124c7612190565b0190565b919081101561250c575b60051b810135907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa181360301821215610359570190565b612514611d9a565b6124d5565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe181360301821215610359570180359067ffffffffffffffff821161035957602001918160051b3603831361035957565b356108b781610422565b1561257e57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f4141393620696e76616c69642061676772656761746f720000000000000000006044820152fd5b90357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18236030181121561035957016020813591019167ffffffffffffffff821161035957813603831361035957565b6108b7916126578161263d8461045c565b73ffffffffffffffffffffffffffffffffffffffff169052565b602082013560208201526126f26126a361268861267760408601866125dc565b610160806040880152860191612028565b61269560608601866125dc565b908583036060870152612028565b6080840135608084015260a084013560a084015260c084013560c084015260e084013560e084015261010080850135908401526101206126e5818601866125dc565b9185840390860152612028565b9161270361014091828101906125dc565b929091818503910152612028565b949391929083604087016040885252606086019360608160051b8801019482600090815b848310612754575050505050508460206108b795968503910152612028565b9091929394977fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa08b820301855288357ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffea1843603018112156127cf57600191846127bd920161262c565b98602090810196950193019190612735565b8280fd5b908092918237016000815290565b9290936108b796959260c0958552602085015265ffffffffffff8092166040850152166060830152151560808201528160a0820152019061208a565b1561282457565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f4141393220696e7465726e616c2063616c6c206f6e6c790000000000000000006044820152fd5b9060406108b79260008152816020820152019061208a565b6040906108b793928152816020820152019061208a565b909291925a936128c230331461281d565b8151946040860151955a6113886060830151890101116129e2576108b7966000958051612909575b50505090612903915a9003608084015101943691610682565b91615047565b612938916129349161292f855173ffffffffffffffffffffffffffffffffffffffff1690565b615c12565b1590565b612944575b80806128ea565b61290392919450612953615c24565b908151612967575b5050600193909161293d565b7f1c4fada7374c0a9ee8841fc38afe82932dc0f8e69012e927f061a8bae611a20173ffffffffffffffffffffffffffffffffffffffff6020870151926129d860206129c6835173ffffffffffffffffffffffffffffffffffffffff1690565b9201519560405193849316968361289a565b0390a3388061295b565b7fdeaddead0000000000000000000000000000000000000000000000000000000060005260206000fd5b612a22612a1c6040830183611fc8565b90615c07565b90612a33612a1c6060830183611fc8565b90612ae9612a48612a1c610120840184611fc8565b60405194859360208501956101008201359260e08301359260c08101359260a08201359260808301359273ffffffffffffffffffffffffffffffffffffffff60208201359135168c9693909a9998959261012098959273ffffffffffffffffffffffffffffffffffffffff6101408a019d168952602089015260408801526060870152608086015260a085015260c084015260e08301526101008201520152565b0391612b1b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0938481018352826105ab565b51902060408051602081019283523091810191909152466060820152608092830181529091612b4a90826105ab565b51902090565b604051906040820182811067ffffffffffffffff821117612b7b575b60405260006020838281520152565b612b83610505565b612b6c565b906014116103595790601490565b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000009035818116939260148110612bcb57505050565b60140360031b82901b16169150565b9060c060a06108b793805184526020810151602085015260408101511515604085015265ffffffffffff80606083015116606086015260808201511660808501520151918160a0820152019061208a565b9294612c8c61044d95612c7a610100959998612c68612c54602097610140808c528b0190612bda565b9b878a019060208091805184520151910152565b80516060890152602001516080880152565b805160a08701526020015160c0860152565b73ffffffffffffffffffffffffffffffffffffffff81511660e0850152015191019060208091805184520151910152565b612d0661044d94612cf4612cdf60a0959998969960e0865260e0860190612bda565b98602085019060208091805184520151910152565b80516060840152602001516080830152565b019060208091805184520151910152565b9081602091031261035957516108b781610422565b9160206108b7938181520191612028565b90612d6c73ffffffffffffffffffffffffffffffffffffffff916108b797959694606085526060850191612028565b941660208201526040818503910152612028565b60009060033d11612d8d57565b905060046000803e60005160e01c90565b600060443d106108b7576040517ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc91823d016004833e815167ffffffffffffffff918282113d602484011117612e1a57818401948551938411612e22573d85010160208487010111612e1a57506108b7929101602001906105ab565b949350505050565b50949350505050565b612e386040820182611fc8565b612e50612e448461256d565b93610120810190611fc8565b9290303b1561035957600093612e949160405196879586957f957122ab00000000000000000000000000000000000000000000000000000000875260048701612d3d565b0381305afa9081612f1d575b5061044d576001612eaf612d80565b6308c379a014612ec8575b612ec057565b61044d612183565b612ed0612d9e565b80612edc575b50612eba565b80516000925015612ed657610f21906040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301612882565b80610f48612f2a9261057b565b38612ea0565b9190612f3b9061317f565b73ffffffffffffffffffffffffffffffffffffffff929183166130da5761306c57612f659061317f565b9116612ffe57612f725750565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152602160448201527f41413332207061796d61737465722065787069726564206f72206e6f7420647560648201527f6500000000000000000000000000000000000000000000000000000000000000608482015260a490fd5b610f21826040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601460408201527f41413334207369676e6174757265206572726f7200000000000000000000000060608201520190565b610f21836040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601760408201527f414132322065787069726564206f72206e6f742064756500000000000000000060608201520190565b610f21846040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601460408201527f41413234207369676e6174757265206572726f7200000000000000000000000060608201520190565b9291906131549061317f565b909273ffffffffffffffffffffffffffffffffffffffff808095169116036130da5761306c57612f65905b80156131d25761318e9061535f565b73ffffffffffffffffffffffffffffffffffffffff65ffffffffffff8060408401511642119081156131c2575b5091511691565b90506020830151164210386131bb565b50600090600090565b156131e257565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f41413934206761732076616c756573206f766572666c6f7700000000000000006044820152fd5b916000915a9381519061325382826136b3565b61325c81612a0c565b602084015261329a6effffffffffffffffffffffffffffff60808401516060850151176040850151176101008401359060e0850135171711156131db565b6132a382613775565b6132ae818584613836565b97906132df6129346132d4875173ffffffffffffffffffffffffffffffffffffffff1690565b60208801519061546c565b6133db576132ec43600052565b73ffffffffffffffffffffffffffffffffffffffff61332460a0606097015173ffffffffffffffffffffffffffffffffffffffff1690565b166133c1575b505a810360a0840135106133545760809360c092604087015260608601525a900391013501910152565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601e60408201527f41413430206f76657220766572696669636174696f6e4761734c696d6974000060608201520190565b909350816133d2929750858461455c565b9590923861332a565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601a60408201527f4141323520696e76616c6964206163636f756e74206e6f6e636500000000000060608201520190565b9290916000925a825161345b81846136b3565b61346483612a0c565b60208501526134a26effffffffffffffffffffffffffffff60808301516060840151176040840151176101008601359060e0870135171711156131db565b6134ab81613775565b6134b78186868b613ba2565b98906134e86129346134dd865173ffffffffffffffffffffffffffffffffffffffff1690565b60208701519061546c565b6135e0576134f543600052565b73ffffffffffffffffffffffffffffffffffffffff61352d60a0606096015173ffffffffffffffffffffffffffffffffffffffff1690565b166135c5575b505a840360a08601351061355f5750604085015260608401526080919060c0905a900391013501910152565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152601e60448201527f41413430206f76657220766572696669636174696f6e4761734c696d697400006064820152608490fd5b909250816135d79298508686856147ef565b96909138613533565b610f21826040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601a60408201527f4141323520696e76616c6964206163636f756e74206e6f6e636500000000000060608201520190565b1561365557565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f4141393320696e76616c6964207061796d6173746572416e64446174610000006044820152fd5b613725906136dd6136c38261256d565b73ffffffffffffffffffffffffffffffffffffffff168452565b602081013560208401526080810135604084015260a0810135606084015260c0810135608084015260e081013560c084015261010081013560e0840152610120810190611fc8565b90811561376a5761374f61124c6112468460a09461374a601461044d9998101561364e565b612b88565b73ffffffffffffffffffffffffffffffffffffffff16910152565b505060a06000910152565b60a081015173ffffffffffffffffffffffffffffffffffffffff16156137b75760c060035b60ff60408401519116606084015102016080830151019101510290565b60c0600161379a565b6137d86040929594939560608352606083019061262c565b9460208201520152565b9061044d602f60405180947f414132332072657665727465643a20000000000000000000000000000000000060208301526138268151809260208686019101612067565b810103600f8101855201836105ab565b916000926000925a936139046020835193613865855173ffffffffffffffffffffffffffffffffffffffff1690565b9561387d6138766040830183611fc8565b9084613e0d565b60a086015173ffffffffffffffffffffffffffffffffffffffff16906138a243600052565b85809373ffffffffffffffffffffffffffffffffffffffff809416159889613b3a575b60600151908601516040517f3a871cdd0000000000000000000000000000000000000000000000000000000081529788968795869390600485016137c0565b03938a1690f1829181613b1a575b50613b115750600190613923612d80565b6308c379a014613abd575b50613a50575b613941575b50505a900391565b61396b9073ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b613986610a2c82546dffffffffffffffffffffffffffff1690565b8083116139e3576139dc926dffffffffffffffffffffffffffff9103166dffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffff0000000000000000000000000000825416179055565b3880613939565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601760408201527f41413231206469646e2774207061792070726566756e6400000000000000000060608201520190565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601660408201527f4141323320726576657274656420286f72204f4f47290000000000000000000060608201520190565b613ac5612d9e565b9081613ad1575061392e565b610f2191613adf91506137e2565b6040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301612882565b95506139349050565b613b3391925060203d81116123385761232981836105ab565b9038613912565b9450613b80610a2c613b6c8c73ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b546dffffffffffffffffffffffffffff1690565b8b811115613b975750856060835b969150506138c5565b606087918d03613b8e565b90926000936000935a94613beb6020835193613bd2855173ffffffffffffffffffffffffffffffffffffffff1690565b9561387d613be36040830183611fc8565b90848c61412b565b03938a1690f1829181613ded575b50613de45750600190613c0a612d80565b6308c379a014613d8e575b50613d20575b613c29575b5050505a900391565b613c539073ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b91613c6f610a2c84546dffffffffffffffffffffffffffff1690565b90818311613cba575082547fffffffffffffffffffffffffffffffffffff0000000000000000000000000000169190036dffffffffffffffffffffffffffff16179055388080613c20565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152601760448201527f41413231206469646e2774207061792070726566756e640000000000000000006064820152608490fd5b610f21846040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601660408201527f4141323320726576657274656420286f72204f4f47290000000000000000000060608201520190565b613d96612d9e565b9081613da25750613c15565b8691613dae91506137e2565b90610f216040519283927f220266b60000000000000000000000000000000000000000000000000000000084526004840161289a565b9650613c1b9050565b613e0691925060203d81116123385761232981836105ab565b9038613bf9565b909180613e1957505050565b81515173ffffffffffffffffffffffffffffffffffffffff1692833b6140be57606083510151604051907f570e1a3600000000000000000000000000000000000000000000000000000000825260208280613e78878760048401612d2c565b0381600073ffffffffffffffffffffffffffffffffffffffff95867f00000000000000000000000000000000000000000000000000000000000000001690f19182156140b1575b600092614091575b508082169586156140245716809503613fb7573b15613f4a5761124c6112467fd51a9c61267aa6196961883ecf5ff2da6619c37dac0fa92122513fb32c032d2d93613f1193612b88565b602083810151935160a001516040805173ffffffffffffffffffffffffffffffffffffffff9485168152939091169183019190915290a3565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152602060408201527f4141313520696e6974436f6465206d757374206372656174652073656e64657260608201520190565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152602060408201527f4141313420696e6974436f6465206d7573742072657475726e2073656e64657260608201520190565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601b60408201527f4141313320696e6974436f6465206661696c6564206f72204f4f47000000000060608201520190565b6140aa91925060203d811161146a5761145b81836105ab565b9038613ec7565b6140b9612183565b613ebf565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601f60408201527f414131302073656e64657220616c726561647920636f6e73747275637465640060608201520190565b9290918161413a575b50505050565b82515173ffffffffffffffffffffffffffffffffffffffff1693843b6143e257606084510151604051907f570e1a3600000000000000000000000000000000000000000000000000000000825260208280614199888860048401612d2c565b0381600073ffffffffffffffffffffffffffffffffffffffff95867f00000000000000000000000000000000000000000000000000000000000000001690f19182156143d5575b6000926143b5575b5080821696871561434757168096036142d9573b15614273575061124c6112467fd51a9c61267aa6196961883ecf5ff2da6619c37dac0fa92122513fb32c032d2d9361423393612b88565b602083810151935160a001516040805173ffffffffffffffffffffffffffffffffffffffff9485168152939091169183019190915290a338808080614134565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152602060448201527f4141313520696e6974436f6465206d757374206372656174652073656e6465726064820152608490fd5b610f21826040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152602060408201527f4141313420696e6974436f6465206d7573742072657475726e2073656e64657260608201520190565b610f21846040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601b60408201527f4141313320696e6974436f6465206661696c6564206f72204f4f47000000000060608201520190565b6143ce91925060203d811161146a5761145b81836105ab565b90386141e8565b6143dd612183565b6141e0565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152601f60448201527f414131302073656e64657220616c726561647920636f6e7374727563746564006064820152608490fd5b1561444f57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f4141343120746f6f206c6974746c6520766572696669636174696f6e476173006044820152fd5b919060408382031261035957825167ffffffffffffffff81116103595783019080601f83011215610359578151916144e483610639565b916144f260405193846105ab565b838352602084830101116103595760209261451291848085019101612067565b92015190565b9061044d602f60405180947f414133332072657665727465643a20000000000000000000000000000000000060208301526138268151809260208686019101612067565b93919260609460009460009380519261459b60a08a86015195614580888811614448565b015173ffffffffffffffffffffffffffffffffffffffff1690565b916145c68373ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b946145e2610a2c87546dffffffffffffffffffffffffffff1690565b968588106147825773ffffffffffffffffffffffffffffffffffffffff60208a98946146588a966dffffffffffffffffffffffffffff8b6146919e03166dffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffff0000000000000000000000000000825416179055565b015194604051998a98899788937ff465c77e000000000000000000000000000000000000000000000000000000008552600485016137c0565b0395169103f190818391849361475c575b506147555750506001906146b4612d80565b6308c379a014614733575b506146c657565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601660408201527f4141333320726576657274656420286f72204f4f47290000000000000000000060608201520190565b61473b612d9e565b908161474757506146bf565b610f2191613adf9150614518565b9450925050565b90925061477b91503d8085833e61477381836105ab565b8101906144ad565b91386146a2565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601e60408201527f41413331207061796d6173746572206465706f73697420746f6f206c6f77000060608201520190565b91949293909360609560009560009382519061481660a08b84015193614580848611614448565b936148418573ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b61485c610a2c82546dffffffffffffffffffffffffffff1690565b8781106149b7579273ffffffffffffffffffffffffffffffffffffffff60208a989693946146588a966dffffffffffffffffffffffffffff8d6148d69e9c9a03166dffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffff0000000000000000000000000000825416179055565b0395169103f1908183918493614999575b506149915750506001906148f9612d80565b6308c379a014614972575b5061490c5750565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152601660448201527f4141333320726576657274656420286f72204f4f4729000000000000000000006064820152608490fd5b61497a612d9e565b90816149865750614904565b613dae925050614518565b955093505050565b9092506149b091503d8085833e61477381836105ab565b91386148e7565b610f218a6040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601e60408201527f41413331207061796d6173746572206465706f73697420746f6f206c6f77000060608201520190565b60031115614a2f57565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b929190614a7c6040916002865260606020870152606086019061208a565b930152565b939291906003811015614a2f57604091614a7c91865260606020870152606086019061208a565b9061044d603660405180947f4141353020706f73744f702072657665727465643a20000000000000000000006020830152614aec8151809260208686019101612067565b81010360168101855201836105ab565b929190925a93600091805191614b1183615318565b9260a0810195614b35875173ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff93908481169081614ca457505050614b76825173ffffffffffffffffffffffffffffffffffffffff1690565b985b5a90030193840297604084019089825110614c37577f49628fd1471006c1482da88028e9ce4dbb080b815c9b0344d39e5a8e6ec1419f94614bc26020928c614c329551039061553a565b015194896020614c04614be9865173ffffffffffffffffffffffffffffffffffffffff1690565b9a5173ffffffffffffffffffffffffffffffffffffffff1690565b9401519785604051968796169a16988590949392606092608083019683521515602083015260408201520152565b0390a4565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152602060408201527f414135312070726566756e642062656c6f772061637475616c476173436f737460608201520190565b9a918051614cb4575b5050614b78565b6060850151600099509091803b15614ddb579189918983614d07956040518097819682957fa9a234090000000000000000000000000000000000000000000000000000000084528c029060048401614a5e565b0393f19081614dc8575b50614dc3576001614d20612d80565b6308c379a014614da4575b614d37575b3880614cad565b6040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601260408201527f4141353020706f73744f7020726576657274000000000000000000000000000060608201520190565b614dac612d9e565b80614db75750614d2b565b613adf610f2191614aa8565b614d30565b80610f48614dd59261057b565b38614d11565b8980fd5b9392915a90600092805190614df382615318565b9360a0830196614e17885173ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff95908681169081614f0d57505050614e58845173ffffffffffffffffffffffffffffffffffffffff1690565b915b5a9003019485029860408301908a825110614ea757507f49628fd1471006c1482da88028e9ce4dbb080b815c9b0344d39e5a8e6ec1419f949392614bc2614c32938c60209451039061553a565b604080517f220266b600000000000000000000000000000000000000000000000000000000815260048101929092526024820152602060448201527f414135312070726566756e642062656c6f772061637475616c476173436f73746064820152608490fd5b93918051614f1d575b5050614e5a565b606087015160009a509091803b1561504357918a918a83614f70956040518097819682957fa9a234090000000000000000000000000000000000000000000000000000000084528c029060048401614a5e565b0393f19081615030575b5061502b576001614f89612d80565b6308c379a01461500e575b614fa0575b3880614f16565b610f218b6040519182917f220266b600000000000000000000000000000000000000000000000000000000835260048301608091815260406020820152601260408201527f4141353020706f73744f7020726576657274000000000000000000000000000060608201520190565b615016612d9e565b806150215750614f94565b613dae8d91614aa8565b614f99565b80610f4861503d9261057b565b38614f7a565b8a80fd5b909392915a9480519161505983615318565b9260a081019561507d875173ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff938185169182615165575050506150bd825173ffffffffffffffffffffffffffffffffffffffff1690565b985b5a90030193840297604084019089825110614c37577f49628fd1471006c1482da88028e9ce4dbb080b815c9b0344d39e5a8e6ec1419f946151096020928c614c329551039061553a565b61511288614a25565b015194896020615139614be9865173ffffffffffffffffffffffffffffffffffffffff1690565b940151604080519182529815602082015297880152606087015290821695909116939081906080820190565b9a918151615175575b50506150bf565b8784026151818a614a25565b60028a1461520c576060860151823b15610359576151d493600080948d604051978896879586937fa9a2340900000000000000000000000000000000000000000000000000000000855260048501614a81565b0393f180156151ff575b6151ec575b505b388061516e565b80610f486151f99261057b565b386151e3565b615207612183565b6151de565b6060860151823b156103595761525793600080948d604051978896879586937fa9a2340900000000000000000000000000000000000000000000000000000000855260048501614a81565b0393f19081615305575b50615300576001615270612d80565b6308c379a0146152ed575b156151e5576040517f220266b600000000000000000000000000000000000000000000000000000000815280610f21600482016080906000815260406020820152601260408201527f4141353020706f73744f7020726576657274000000000000000000000000000060608201520190565b6152f5612d9e565b80614db7575061527b565b6151e5565b80610f486153129261057b565b38615261565b60e060c082015191015180821461533c57480180821015615337575090565b905090565b5090565b6040519061534d8261058f565b60006040838281528260208201520152565b615367615340565b5065ffffffffffff808260a01c1680156153b3575b604051926153898461058f565b73ffffffffffffffffffffffffffffffffffffffff8116845260d01c602084015216604082015290565b508061537c565b6153cf6153d5916153c9615340565b5061535f565b9161535f565b9073ffffffffffffffffffffffffffffffffffffffff9182825116928315615461575b65ffffffffffff928391826040816020850151169301511693836040816020840151169201511690808410615459575b50808511615451575b506040519561543f8761058f565b16855216602084015216604082015290565b935038615431565b925038615428565b8151811693506153f8565b73ffffffffffffffffffffffffffffffffffffffff16600052600160205267ffffffffffffffff6154c88260401c60406000209077ffffffffffffffffffffffffffffffffffffffffffffffff16600052602052604060002090565b918254926154d584612491565b9055161490565b9073ffffffffffffffffffffffffffffffffffffffff6154fa612b50565b9216600052600060205263ffffffff600160406000206dffffffffffffffffffffffffffff815460781c1685520154166020830152565b61044d3361562b565b73ffffffffffffffffffffffffffffffffffffffff16600052600060205260406000206dffffffffffffffffffffffffffff8082541692830180931161561e575b8083116155c05761044d92166dffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffff0000000000000000000000000000825416179055565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f6465706f736974206f766572666c6f77000000000000000000000000000000006044820152fd5b615626612190565b61557b565b73ffffffffffffffffffffffffffffffffffffffff9061564b348261553a565b168060005260006020527f2da466a7b24304f47e87fa2e1e5a81b9831ce54fec19055ce277ca2f39ba42c460206dffffffffffffffffffffffffffff60406000205416604051908152a2565b1561569e57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f6d757374207370656369667920756e7374616b652064656c61790000000000006044820152fd5b1561570357565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f63616e6e6f7420646563726561736520756e7374616b652074696d65000000006044820152fd5b1561576857565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f6e6f207374616b652073706563696669656400000000000000000000000000006044820152fd5b156157cd57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f7374616b65206f766572666c6f770000000000000000000000000000000000006044820152fd5b9065ffffffffffff6080600161044d9461588b6dffffffffffffffffffffffffffff86511682906dffffffffffffffffffffffffffff167fffffffffffffffffffffffffffffffffffff0000000000000000000000000000825416179055565b602085015115156eff000000000000000000000000000082549160701b16807fffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffff83161783557fffffff000000000000000000000000000000ffffffffffffffffffffffffffff7cffffffffffffffffffffffffffff000000000000000000000000000000604089015160781b16921617178155019263ffffffff6060820151167fffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000008554161784550151167fffffffffffffffffffffffffffffffffffffffffffff000000000000ffffffff69ffffffffffff0000000083549260201b169116179055565b1561599657565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f616c726561647920756e7374616b696e670000000000000000000000000000006044820152fd5b91909165ffffffffffff808094169116019182116121cd57565b15615a1557565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f4e6f207374616b6520746f2077697468647261770000000000000000000000006044820152fd5b15615a7a57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f6d7573742063616c6c20756e6c6f636b5374616b6528292066697273740000006044820152fd5b15615adf57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f5374616b65207769746864726177616c206973206e6f742064756500000000006044820152fd5b15615b4457565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f6661696c656420746f207769746864726177207374616b6500000000000000006044820152fd5b15615ba957565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f6661696c656420746f20776974686472617700000000000000000000000000006044820152fd5b816040519182372090565b9060009283809360208451940192f190565b3d610800808211615c4b575b50604051906020818301016040528082526000602083013e90565b905038615c3056fea2646970667358221220a706d8b02d7086d80e9330811f5af84b2614abdc5e9a1f2260126070a31d7cee64736f6c63430008110033 + +# Allocate genesis accounts (cosmos formatted addresses) +artela-rollkitd add-genesis-account $KEY 100000000000000000000000000aart --keyring-backend $KEYRING +artela-rollkitd add-genesis-account $KEY2 100000000000000000000000000aart --keyring-backend $KEYRING +artela-rollkitd add-genesis-account $KEY3 100000000000000000000000000aart --keyring-backend $KEYRING +artela-rollkitd add-genesis-account $KEY4 100000000000000000000000000aart --keyring-backend $KEYRING +echo artela-rollkitd add-genesis-account $KEY 100000000000000000000000000aart --keyring-backend $KEYRING + +# Sign genesis transaction +artela-rollkitd gentx $KEY 1000000000000000000000aart --keyring-backend $KEYRING --chain-id $CHAINID + +# Collect genesis tx +artela-rollkitd collect-gentxs + +# Run this to ensure everything worked and that the genesis file is setup correctly +artela-rollkitd validate-genesis + +# disable produce empty block and enable prometheus metrics +if [[ "$OSTYPE" == "darwin"* ]]; then + sed -i '' 's/create_empty_blocks = true/create_empty_blocks = false/g' $HOME/.artroll/config/config.toml + sed -i '' 's/prometheus = false/prometheus = true/' $HOME/.artroll/config/config.toml + sed -i '' 's/prometheus-retention-time = 0/prometheus-retention-time = 1000000000000/g' $HOME/.artroll/config/app.toml + sed -i '' 's/enabled = false/enabled = true/g' $HOME/.artroll/config/app.toml + sed -i '' 's/127.0.0.1:8545/0.0.0.0:8545/g' $HOME/.artroll/config/app.toml + sed -i '' 's/allow-unprotected-txs = false/allow-unprotected-txs = true/g' $HOME/.artroll/config/app.toml + + # set prunning options + sed -i '' 's/pruning = "default"/pruning = "custom"/g' $HOME/.artroll/config/app.toml + sed -i '' 's/pruning-keep-recent = "0"/pruning-keep-recent = "2"/g' $HOME/.artroll/config/app.toml + sed -i '' 's/pruning-interval = "0"/pruning-interval = "10"/g' $HOME/.artroll/config/app.toml + + # set snapshot options + sed -i '' 's/snapshot-interval = 0/snapshot-interval = 2000/g' $HOME/.artroll/config/app.toml +else + sed -i 's/create_empty_blocks = true/create_empty_blocks = false/g' $HOME/.artroll/config/config.toml + sed -i 's/prometheus = false/prometheus = true/' $HOME/.artroll/config/config.toml + sed -i 's/prometheus-retention-time = "0"/prometheus-retention-time = "1000000000000"/g' $HOME/.artroll/config/app.toml + sed -i 's/enabled = false/enabled = true/g' $HOME/.artroll/config/app.toml + sed -i 's/127.0.0.1:8545/0.0.0.0:8545/g' $HOME/.artroll/config/app.toml + sed -i 's/allow-unprotected-txs = false/allow-unprotected-txs = true/g' $HOME/.artroll/config/app.toml + + # set prunning options + sed -i 's/pruning = "default"/pruning = "custom"/g' $HOME/.artroll/config/app.toml + sed -i 's/pruning-keep-recent = "0"/pruning-keep-recent = "2"/g' $HOME/.artroll/config/app.toml + sed -i 's/pruning-interval = "0"/pruning-interval = "10"/g' $HOME/.artroll/config/app.toml + + # set snapshot options + sed -i 's/snapshot-interval = 0/snapshot-interval = 2000/g' $HOME/.artroll/config/app.toml + sed -i 's/enable = false/enable = true/g' $HOME/.artroll/config/app.toml + sed -i 's/prometheus = false/prometheus = true/' $HOME/.artroll/config/config.toml + sed -i 's/timeout_commit = "5s"/timeout_commit = "500ms"/' $HOME/.artroll/config/config.toml +fi + +if [[ $1 == "pending" ]]; then + echo "pending mode is on, please wait for the first block committed." + if [[ $OSTYPE == "darwin"* ]]; then + sed -i '' 's/create_empty_blocks_interval = "0s"/create_empty_blocks_interval = "30s"/g' $HOME/.artroll/config/config.toml + sed -i '' 's/timeout_propose = "3s"/timeout_propose = "30s"/g' $HOME/.artroll/config/config.toml + sed -i '' 's/timeout_propose_delta = "500ms"/timeout_propose_delta = "5s"/g' $HOME/.artroll/config/config.toml + sed -i '' 's/timeout_prevote = "1s"/timeout_prevote = "10s"/g' $HOME/.artroll/config/config.toml + sed -i '' 's/timeout_prevote_delta = "500ms"/timeout_prevote_delta = "5s"/g' $HOME/.artroll/config/config.toml + sed -i '' 's/timeout_precommit = "1s"/timeout_precommit = "10s"/g' $HOME/.artroll/config/config.toml + sed -i '' 's/timeout_precommit_delta = "500ms"/timeout_precommit_delta = "5s"/g' $HOME/.artroll/config/config.toml + sed -i '' 's/timeout_commit = "5s"/timeout_commit = "150s"/g' $HOME/.artroll/config/config.toml + sed -i '' 's/timeout_broadcast_tx_commit = "10s"/timeout_broadcast_tx_commit = "150s"/g' $HOME/.artroll/config/config.toml + else + sed -i 's/create_empty_blocks_interval = "0s"/create_empty_blocks_interval = "30s"/g' $HOME/.artroll/config/config.toml + sed -i 's/timeout_propose = "3s"/timeout_propose = "30s"/g' $HOME/.artroll/config/config.toml + sed -i 's/timeout_propose_delta = "500ms"/timeout_propose_delta = "5s"/g' $HOME/.artroll/config/config.toml + sed -i 's/timeout_prevote = "1s"/timeout_prevote = "10s"/g' $HOME/.artroll/config/config.toml + sed -i 's/timeout_prevote_delta = "500ms"/timeout_prevote_delta = "5s"/g' $HOME/.artroll/config/config.toml + sed -i 's/timeout_precommit = "1s"/timeout_precommit = "10s"/g' $HOME/.artroll/config/config.toml + sed -i 's/timeout_precommit_delta = "500ms"/timeout_precommit_delta = "5s"/g' $HOME/.artroll/config/config.toml + sed -i 's/timeout_commit = "5s"/timeout_commit = "150s"/g' $HOME/.artroll/config/config.toml + sed -i 's/timeout_broadcast_tx_commit = "10s"/timeout_broadcast_tx_commit = "150s"/g' $HOME/.artroll/config/config.toml + fi +fi \ No newline at end of file diff --git a/proto/artela/crypto/ethsecp256k1/keys.proto b/proto/artela/crypto/ethsecp256k1/keys.proto new file mode 100644 index 0000000..dc978d5 --- /dev/null +++ b/proto/artela/crypto/ethsecp256k1/keys.proto @@ -0,0 +1,23 @@ +syntax = "proto3"; +package artela.crypto.ethsecp256k1; + +import "gogoproto/gogo.proto"; + +option go_package = "github.com/artela-network/artela-rollkit/ethereum/crypto/ethsecp256k1"; + +// PubKey defines a type alias for an ecdsa.PublicKey that implements +// Tendermint's PubKey interface. It represents the 33-byte compressed public +// key format. +message PubKey { + option (gogoproto.goproto_stringer) = false; + + // key is the public key in byte form + bytes key = 1; +} + +// PrivKey defines a type alias for an ecdsa.PrivateKey that implements +// Tendermint's PrivateKey interface. +message PrivKey { + // key is the private key in byte form + bytes key = 1; +} \ No newline at end of file diff --git a/x/evm/module/genesis.go b/x/evm/module/genesis.go index 462548f..46aff54 100644 --- a/x/evm/module/genesis.go +++ b/x/evm/module/genesis.go @@ -61,11 +61,31 @@ func InitGenesis(ctx sdk.Context, k keeper.Keeper, accountKeeper types.AccountKe } // ExportGenesis returns the module's exported genesis. -func ExportGenesis(ctx sdk.Context, k keeper.Keeper) *types.GenesisState { - genesis := types.DefaultGenesis() - genesis.Params = k.GetParams(ctx) +func ExportGenesis(ctx sdk.Context, k keeper.Keeper, ak types.AccountKeeper) *types.GenesisState { + var ethGenAccounts []types.GenesisAccount + ak.IterateAccounts(ctx, func(account sdk.AccountI) bool { + ethAccount, ok := account.(artela.EthAccountI) + if !ok { + // ignore non EthAccounts + return false + } - // this line is used by starport scaffolding # genesis/module/export + addr := ethAccount.EthAddress() - return genesis + storage := k.GetAccountStorage(ctx, addr) + + genAccount := types.GenesisAccount{ + Address: addr.String(), + Code: common.Bytes2Hex(k.GetCode(ctx, ethAccount.GetCodeHash())), + Storage: storage, + } + + ethGenAccounts = append(ethGenAccounts, genAccount) + return false + }) + + return &types.GenesisState{ + Accounts: ethGenAccounts, + Params: k.GetParams(ctx), + } } diff --git a/x/evm/module/module.go b/x/evm/module/module.go index abbbd90..9b198bb 100644 --- a/x/evm/module/module.go +++ b/x/evm/module/module.go @@ -133,7 +133,7 @@ func (am AppModule) InitGenesis(ctx sdk.Context, cdc codec.JSONCodec, gs json.Ra // ExportGenesis returns the module's exported genesis state as raw JSON bytes. func (am AppModule) ExportGenesis(ctx sdk.Context, cdc codec.JSONCodec) json.RawMessage { - genState := ExportGenesis(ctx, am.keeper) + genState := ExportGenesis(ctx, am.keeper, am.accountKeeper) return cdc.MustMarshalJSON(genState) } diff --git a/x/evm/types/expected_keepers.go b/x/evm/types/expected_keepers.go index cdc4319..059d337 100644 --- a/x/evm/types/expected_keepers.go +++ b/x/evm/types/expected_keepers.go @@ -26,6 +26,7 @@ type AccountKeeper interface { SetAccount(ctx context.Context, acc sdk.AccountI) AddressCodec() address.Codec RemoveAccount(ctx context.Context, acc sdk.AccountI) + IterateAccounts(ctx context.Context, cb func(account sdk.AccountI) (stop bool)) // Methods imported from account should be defined here } diff --git a/x/fee/types/params.go b/x/fee/types/params.go index ce103de..3e9d55d 100644 --- a/x/fee/types/params.go +++ b/x/fee/types/params.go @@ -23,8 +23,8 @@ var _ paramtypes.ParamSet = (*Params)(nil) var ( // DefaultMinGasMultiplier is 0.5 or 50% DefaultMinGasMultiplier = sdkmath.LegacyNewDecWithPrec(50, 2) - // DefaultMinGasPrice is 0 (i.e disabled) - DefaultMinGasPrice = sdkmath.LegacyZeroDec() + // DefaultMinGasPrice is 20Gwei (i.e disabled) + DefaultMinGasPrice = sdkmath.LegacyNewDec(20000000000) // DefaultEnableHeight is 0 (i.e disabled) DefaultEnableHeight = int64(0) // DefaultNoBaseFee is false