Skip to content

686: Cmd, enhance generate account #687

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Mar 24, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
186 changes: 117 additions & 69 deletions cmd/account/account.go
Original file line number Diff line number Diff line change
@@ -1,129 +1,177 @@
package account

import (
"encoding/base64"
"encoding/hex"
"fmt"

"github.com/spf13/cobra"
slip10 "github.com/zoobc/zoo-slip10"
"github.com/zoobc/zoobc-core/common/crypto"
"github.com/zoobc/zoobc-core/common/model"
"github.com/zoobc/zoobc-core/common/transaction"
"github.com/zoobc/zoobc-core/common/util"
)

type (
// GeneratorCommands represent struct of account generator commands
GeneratorCommands struct {
Signature crypto.SignatureInterface
TransactionUtil transaction.UtilInterface
}
// RunCommand represent of output function from account generator commands
RunCommand func(ccmd *cobra.Command, args []string)
)

var (
accountGeneratorInstance *GeneratorCommands

accountCmd = &cobra.Command{
Use: "account",
Short: "account is a developer cli tools to generate account.",
Long: `account is a developer cli tools to generate account.
running 'zoobc account generate' will show create an account detail with its public key and
private key both in bytes and hex representation + the secret phrase
`,
Run: func(cmd *cobra.Command, args []string) {
generateRandomAccount()
},
}

randomAccountCmd = &cobra.Command{
Use: "random",
Short: "random defines to generate random account.",
Run: func(cmd *cobra.Command, args []string) {
generateRandomAccount()
},
ed25519AccountCmd = &cobra.Command{
Use: "ed25519",
Short: "Generate account using ed25519 algorithm. This is the default zoobc account",
}

fromSeedCmd = &cobra.Command{
Use: "from-seed",
Short: "from-seed defines to generate account from provided seed.",
Run: func(cmd *cobra.Command, args []string) {
generateAccountFromSeed(signatureType, seed)
},
bitcoinAccuntCmd = &cobra.Command{
Use: "bitcoin",
Short: "Generate account based on Bitcoin signature that using Elliptic Curve Digital Signature Algorithm",
}

multiSigCmd = &cobra.Command{
Use: "multisig",
Aliases: []string{"musig", "ms"},
SuggestFor: []string{"mul", "multisignature", "multi-signature"},
Short: "multisig allow to generate multi sig account",
Short: "Multisig allow to generate multi sig account",
Long: "multisig allow to generate multi sig account address" +
"provides account addresses, nonce, and minimum assignment",
Run: func(cmd *cobra.Command, args []string) {
info := &model.MultiSignatureInfo{
MinimumSignatures: multisigMinimSigs,
Nonce: multiSigNonce,
Addresses: multisigAddresses,
}
address, err := (&transaction.Util{}).GenerateMultiSigAddress(info)
if err != nil {
fmt.Println(err.Error())
} else {
fmt.Println(address)
}

},
}
)

func init() {
accountCmd.PersistentFlags().Int32Var(
&signatureType,
"signature-type",
int32(model.SignatureType_DefaultSignature),
"signature-type that provide type of signature want to use to generate the account",
// ed25519
ed25519AccountCmd.Flags().StringVar(&seed, "seed", "", "Seed that is used to generate the account")
ed25519AccountCmd.Flags().BoolVar(&ed25519UseSlip10, "use-slip10", false, "use slip10 to generate ed25519 private key")
// bitcoin
bitcoinAccuntCmd.Flags().StringVar(&seed, "seed", "", "Seed that is used to generate the account")
bitcoinAccuntCmd.Flags().Int32Var(
&bitcoinPrivateKeyLength,
"private-key-length",
int32(model.PrivateKeyBytesLength_PrivateKey256Bits),
"The length of private key Bitcoin want to generate. supported format are 32, 48 & 64 length",
)
bitcoinAccuntCmd.Flags().Int32Var(
&bitcoinPublicKeyFormat,
"public-key-format",
int32(model.BitcoinPublicKeyFormat_PublicKeyFormatCompressed),
"Defines the format of public key Bitcoin want to generate. 0 for compressed format & 1 for uncompressed format",
)
accountCmd.AddCommand(randomAccountCmd)

fromSeedCmd.Flags().StringVar(&seed, "seed", "", "Seed that is used to generate the account")
fromSeedCmd.Flags().BoolVar(&hd, "hd", true, "--hd allow to generate account HD")
accountCmd.AddCommand(fromSeedCmd)

// multisig
multiSigCmd.Flags().StringSliceVar(&multisigAddresses, "addresses", []string{}, "addresses that provides")
multiSigCmd.Flags().Uint32Var(&multisigMinimSigs, "min-sigs", 0, "min-sigs that provide minimum signs")
multiSigCmd.Flags().Int64Var(&multiSigNonce, "nonce", 0, "nonce that provides")
accountCmd.AddCommand(multiSigCmd)
}

// Commands will return the main generate account cmd
func Commands() *cobra.Command {
if accountGeneratorInstance == nil {
accountGeneratorInstance = &GeneratorCommands{
Signature: &crypto.Signature{},
TransactionUtil: &transaction.Util{},
}
}
ed25519AccountCmd.Run = accountGeneratorInstance.GenerateEd25519Account()
accountCmd.AddCommand(ed25519AccountCmd)
bitcoinAccuntCmd.Run = accountGeneratorInstance.GenerateBitcoinAccount()
accountCmd.AddCommand(bitcoinAccuntCmd)
multiSigCmd.Run = accountGeneratorInstance.GenerateMultiSignatureAccount()
accountCmd.AddCommand(multiSigCmd)
return accountCmd
}

func generateRandomAccount() {
seed = util.GetSecureRandomSeed()
generateAccountFromSeed(signatureType, seed)
}

func generateAccountFromSeed(signatureType int32, seed string) {
var (
signature = crypto.Signature{}
seedBytes, privateKey, publicKey []byte
publicKeyString, address string
err error
slip10Key *slip10.Key
)

if hd {
// GenerateMultiSignatureAccount to generate address for multi signature transaction
func (gc *GeneratorCommands) GenerateMultiSignatureAccount() RunCommand {
return func(cmd *cobra.Command, args []string) {
info := &model.MultiSignatureInfo{
MinimumSignatures: multisigMinimSigs,
Nonce: multiSigNonce,
Addresses: multisigAddresses,
}
address, err := gc.TransactionUtil.GenerateMultiSigAddress(info)
if err != nil {
fmt.Println(err.Error())
} else {
fmt.Println(address)
}
}
}

seedBytes = slip10.NewSeed(seed, slip10.DefaultPassword)
slip10Key, err = slip10.DeriveForPath(slip10.StellarPrimaryAccountPath, seedBytes)
// GenerateEd25519Account to generate ed25519 account
func (gc *GeneratorCommands) GenerateEd25519Account() RunCommand {
return func(ccmd *cobra.Command, args []string) {
if seed == "" {
seed = util.GetSecureRandomSeed()
}
var (
signatureType = model.SignatureType_DefaultSignature
privateKey, publicKey, publicKeyString, address, err = gc.Signature.GenerateAccountFromSeed(
signatureType,
seed,
ed25519UseSlip10,
)
)
if err != nil {
panic(err)
}
PrintAccount(
int32(signatureType),
seed,
publicKeyString,
address,
privateKey,
publicKey,
)
}
}

privateKey = slip10Key.Key
publicKey, _ = slip10Key.PublicKey()
publicKeyString = base64.StdEncoding.EncodeToString(publicKey)
address, _ = crypto.NewEd25519Signature().GetAddressFromPublicKey(publicKey)
} else {
privateKey, publicKey, publicKeyString, address, err = signature.GenerateAccountFromSeed(model.SignatureType(signatureType), seed)
// GenerateBitcoinAccount to generate bitcoin account
func (gc *GeneratorCommands) GenerateBitcoinAccount() RunCommand {
return func(ccmd *cobra.Command, args []string) {
if seed == "" {
seed = util.GetSecureRandomSeed()
}
var (
signatureType = model.SignatureType_BitcoinSignature
privateKey, publicKey, publicKeyString, address, err = gc.Signature.GenerateAccountFromSeed(
signatureType,
seed,
model.PrivateKeyBytesLength(bitcoinPrivateKeyLength),
model.BitcoinPublicKeyFormat(bitcoinPublicKeyFormat),
)
)
if err != nil {
panic(err)
}
PrintAccount(
int32(signatureType),
seed,
publicKeyString,
address,
privateKey,
publicKey,
)
}
}

// PrintAccount print out the generated account
func PrintAccount(
signatureType int32,
seed, publicKeyString, address string,
privateKey, publicKey []byte,
) {
fmt.Printf("signature type: %s\n", model.SignatureType_name[signatureType])
fmt.Printf("seed: %s\n", seed)
fmt.Printf("public key hex: %s\n", hex.EncodeToString(publicKey))
Expand Down
10 changes: 7 additions & 3 deletions cmd/account/const.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
package account

var (
seed string
seed string
// ed25519
ed25519UseSlip10 bool
// bitcoin
bitcoinPrivateKeyLength int32
bitcoinPublicKeyFormat int32
// multisig
multisigAddresses []string
multisigMinimSigs uint32
multiSigNonce int64
signatureType int32
hd bool
)
31 changes: 10 additions & 21 deletions cmd/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,11 @@ Command line interface to as a utility tools to develop the zoobc system.

- example: `go run main.go account generate` will generate account to use.

### See more help about commands
- `go run main --help` to see available commands and flags
- `go run main {command} --help` to see to see available subcommands and flags
- `go run main {command} {subcommand} --help` to see to see available subcommands and flags of subcommand

### Transaction general flag
- `--output` to provide generated ouput type. Example: `--ouput bytes`
- `--version` to provide version of transaction. Example: `--version 1`
Expand Down Expand Up @@ -84,27 +89,16 @@ go run main.go generate transaction remove-account-dataset --timestamp 125789400
go run main.go generate block fake-blocks --numberOfBlocks=1000 --blocksmithSecretPhrase='sprinkled sneak species pork outpost thrift unwind cheesy vexingly dizzy neurology neatness' --out='../resource/zoobc.db'
```

### Account Generating Randomly
### Account Generate Using Ed25519 Algorithm

```
go run main.go generate account random
```bash
go run main.go generate account ed25519 --seed "concur vocalist rotten busload gap quote stinging undiluted surfer goofiness deviation starved" --use-slip10
```

### Account Generating From Seed
```bash
Flags:
--hd --hd allow to generate account HD (default true)
-h, --help help for from-seed
--seed string Seed that is used to generate the account
### Account Generate Using Bitcoin Algorithm

Global Flags:
--signature-type int32 signature-type that provide type of signature want to use to generate the account
```
Example:
```bash
go run main.go generate account from-seed --seed "concur v
ocalist rotten busload gap quote stinging undiluted surfer go
ofiness deviation starved"
go run main.go generate account bitcoin --seed "concur vocalist rotten busload gap quote stinging undiluted surfer goofiness deviation starved" --private-key-length 32 --public-key-format 1
### Genesis Generate From cmd/genesisblock/preRegisteredNodes.json

```
Expand All @@ -114,11 +108,6 @@ ofiness deviation starved"
go run main.go generate account multisig --addresses "BCZnSfqpP5tqFQlMTYkDeBVFWnbyVK7vLr5ORFpTjgtN" --addresses "BCZD_VxfO2S9aziIL3cn_cXW7uPDVPOrnXuP98GEAUC7" --addresses "BCZKLvgUYZ1KKx-jtF9KoJskjVPvB9jpIjfzzI6zDW0J" —-min-sigs=2 --nonce=3
```

### Account Generate with spesific signature type
```
go run main.go generate account random --signature-type 1
```

go run main.go genesis generate
outputs cmd/genesis.go.new and cmd/cluster_config.json

Expand Down
28 changes: 28 additions & 0 deletions common/crypto/ed25519.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package crypto

import (
"bytes"
"encoding/base64"

slip10 "github.com/zoobc/zoo-slip10"
"github.com/zoobc/zoobc-core/common/blocker"
"github.com/zoobc/zoobc-core/common/util"
"golang.org/x/crypto/ed25519"
Expand Down Expand Up @@ -37,6 +39,32 @@ func (*Ed25519Signature) GetPrivateKeyFromSeed(seed string) []byte {
return ed25519.NewKeyFromSeed(seedHash[:])
}

// GetPrivateKeyFromSeedUseSlip10 generate privite key form seed using slip10, this private used by hdwallet
// NOTE: currently this private cannot use to sign message using golang ed25519,
// The output private key is first 32 bytes from private key golang ed25519
func (*Ed25519Signature) GetPrivateKeyFromSeedUseSlip10(seed string) ([]byte, error) {
var (
seedBytes = slip10.NewSeed(seed, slip10.DefaultPassword)
slip10Key, err = slip10.DeriveForPath(slip10.StellarPrimaryAccountPath, seedBytes)
)
if err != nil {
return nil, err
}
return slip10Key.Key, nil
}

// GetPublicKeyFromPrivateKeyUseSlip10 get pubic key from slip10 private key
func (*Ed25519Signature) GetPublicKeyFromPrivateKeyUseSlip10(privateKey []byte) ([]byte, error) {
var (
reader = bytes.NewReader(privateKey)
publicKey, _, err = ed25519.GenerateKey(reader)
)
if err != nil {
return nil, err
}
return publicKey, nil
}

// GetPublicKeyFromSeed Get the raw public key corresponding to a seed (secret phrase)
func (es *Ed25519Signature) GetPublicKeyFromSeed(seed string) []byte {
// Get the private key from the seed
Expand Down
Loading