Creating new keychains by API or cli

Hey @Support, or any community member who knows more than me! :blush:

I’m trying to understand how the Incognito App creates new keychains under the master keys. First of all, what is the ShardID (which seems to be 0 in the App code)? No matter how many --numShards I define when running incognito-cli all the keys are the same but the ShardID field is different.

If I run incognito-cli account import with the same mnemonic as the App, the Anon keychain corresponds to the second private key listed, but after that, I get no correlation.

How and where are the keychain names saved? Because importing the mnemonic in the App on a second phone manages to magically restore them.

What I want to accomplish is to create new keychains using the cli or API that then later can be imported on the phone. Is it possible somehow, and can they be named?

1 Like

Hi @fredlee,

Dua to a little bit difference mechanism between App and Cli tool, there is no correlation when you run import feature on CLI except account Anon.

Roughly on the App, except for the Anon account, all the next generated accounts will be belonging to Shard 0.

So, we will update the CLI tool soon to add an argument --shardID so that users can generate accounts at any shard ID.

I will get back to you when the update is released.

Thanks

1 Like

Yeah this is what confuses me with the --numshard option, is it just broken?

# incognito-cli account generate --numShards 1
mnemonic: display rally endless person giraffe torch improve cereal file ready twist federal
{ "PrivateKey": "112t8rnXGo...4HVKz3msVD", "ShardID": 0 }
{ "PrivateKey": "112t8rnXVA...RNZojRxWqq", "ShardID": 0 }
{ "PrivateKey": "112t8rnXkn...RZk9Zt57RN", "ShardID": 0 }
{ "PrivateKey": "112t8rnY3z...x64SJ9sSRG", "ShardID": 0 }
{ "PrivateKey": "112t8rnYMq...ZvJRc1c88i", "ShardID": 0 }

# incognito-cli account import --mnemonic display-rally-endless-person-giraffe-torch-improve-cereal-file-ready-twist-federal --numShards 10
mnemonic: display rally endless person giraffe torch improve cereal file ready twist federal
{ "PrivateKey": "112t8rnXGo...4HVKz3msVD", "ShardID": 9 }
{ "PrivateKey": "112t8rnXVA...RNZojRxWqq", "ShardID": 0 }
{ "PrivateKey": "112t8rnXkn...RZk9Zt57RN", "ShardID": 3 }
{ "PrivateKey": "112t8rnY3z...x64SJ9sSRG", "ShardID": 9 }
{ "PrivateKey": "112t8rnYMq...ZvJRc1c88i", "ShardID": 9 }

As you see, it shows different shardIDs but with the exact same keys. Using the same test mnemonic in the Incognito App, gives the following keys instead:

{ "PrivateKey": "112t8rnXVA...RNZojRxWqq", "Name": "Anon" }
{ "PrivateKey": "112t8rnZdW...aaNEg9tBrj", "Name": "none" }
{ "PrivateKey": "112t8rndst...o4QVNG7p6z", "Name": "of" }
{ "PrivateKey": "112t8rneVr...6tS9rCas3C", "Name": "your" }
{ "PrivateKey": "112t8rnfAs...6PejaFBGdj", "Name": "business" }

How about the chain names? Are they just stored on your servers? Because somehow the import magically knows how many keys it should generate, and what names they should have.

numShards is the number of shards on the blockchain. Not all networks (e.g, devnet) have 8 shards, for some networks like devnet or localnet (for testing purposes), we only use 2 shards. By default, you don’t need to pass the numShards arguments.

As @hieutran mentioned above, a new shardID argument will be available for generating accounts with-in a specific shard.

1 Like

Ok, but what does --numShards 1 do in the incognito-cli today, and why does it say "ShardID": 0 on every key when I specify it? Despite all the keys being the same as running without the option.

--numShards 1 sets the number of shards of the blockchain to 1. Therefore, there is only one shard (i.e, shard 0) in the network. Thus, every generated account belongs to shard 0.

Right, after checking the code I get it. It does nothing. It’s only there to display what shardID it would belong to depending on how many shards the network has.

So if I get this right. The Anon keychain is always index=1, regardless what shard it belongs to. Then after that, the incognito App keeps generating keys until it finds a new one, that has not been used, that belongs to shard 0, if the number of shards are 8.

That’s why it’s taking so long for me to generate new keys in the App now that I have so many accounts.

Still leaves the question. Where the heck does the names come from? :relaxed:

Yes.

Yes, that’s true.

Yes, this is true.

TBH, I don’t know.

Thanks for the help @daniel

Updated the incognito-cli with some new options to handle this and it seems to work fine.

Here’s the diff if anyone want it.

diff --git a/common.go b/common.go
index 409454e..d02bb03 100644
--- a/common.go
+++ b/common.go
@@ -53,8 +53,10 @@ const (
 	pairHashFlag             = "pairHash"
 	amplifierFlag            = "amplifier"
 
-	mnemonicFlag  = "mnemonic"
-	numShardsFlag = "numShards"
+	mnemonicFlag    = "mnemonic"
+	numShardsFlag   = "numShards"
+	shardIDFlag     = "shardID"
+	numAccountsFlag = "numAccounts"
 
 	evmAddressFlag      = "evmAddress"
 	tokenAddressFlag    = "externalTokenAddress"
diff --git a/flags.go b/flags.go
index 73cb551..0d1b311 100644
--- a/flags.go
+++ b/flags.go
@@ -231,6 +231,17 @@ var defaultFlags = map[string]cli.Flag{
 		Usage: "The number of shard",
 		Value: 8,
 	},
+	shardIDFlag: &cli.IntFlag{
+		Name:  shardIDFlag,
+		Usage: "Only generate accounts belonging to this shardID",
+		Value: -1,
+		DefaultText: "any",
+	},
+	numAccountsFlag: &cli.IntFlag{
+		Name:  numAccountsFlag,
+		Usage: "The number of accounts to generate",
+		Value: 5,
+	},
 
 	evmAddressFlag: &cli.StringFlag{
 		Name:  evmAddressFlag,
diff --git a/commands.go b/commands.go
index 23438cb..26d99d8 100644
--- a/commands.go
+++ b/commands.go
@@ -136,6 +136,8 @@ var accountCommands = []*cli.Command{
 				Description: "This command helps generate a new mnemonic phrase and its Incognito accounts.",
 				Flags: []cli.Flag{
 					defaultFlags[numShardsFlag],
+					defaultFlags[shardIDFlag],
+					defaultFlags[numAccountsFlag],
 				},
 				Action: genKeySet,
 			},
@@ -147,6 +149,8 @@ var accountCommands = []*cli.Command{
 				Flags: []cli.Flag{
 					defaultFlags[mnemonicFlag],
 					defaultFlags[numShardsFlag],
+					defaultFlags[shardIDFlag],
+					defaultFlags[numAccountsFlag],
 				},
 				Action: importMnemonic,
 			},
diff --git a/account.go b/account.go
index a5ac4ce..0233378 100644
--- a/account.go
+++ b/account.go
@@ -408,14 +408,19 @@ func genKeySet(c *cli.Context) error {
 	}
 
 	numShards := c.Int(numShardsFlag)
-	if numShards == 0 {
+	if (numShards < 1 || numShards > 255) {
 		return fmt.Errorf("%v is invalid", numShardsFlag)
 	}
 	common.MaxShardNumber = numShards
 
-	numAccounts := 5
+	shardFilter := c.Int(shardIDFlag)
+	if (shardFilter >= numShards) {
+		return fmt.Errorf("%v is invalid for %v shards", shardIDFlag, numShards)
+	}
+
+	numAccounts := c.Int(numAccountsFlag)
 	fmt.Printf("mnemonic: %v\n", mnemonic)
-	for i := 0; i < numAccounts; i++ {
+	for i := 0; numAccounts > 0; i++ {
 		childKey, err := w.DeriveChild(uint32(i))
 		if err != nil {
 			return err
@@ -425,12 +430,14 @@ func genKeySet(c *cli.Context) error {
 		if err != nil {
 			return err
 		}
-
-		jsb, err := json.MarshalIndent(info, "", "\t")
-		if err != nil {
-			return fmt.Errorf("marshalling key info error: %v", err)
+		if (shardFilter < 0 || info.ShardID == byte(shardFilter)) {
+			jsb, err := json.MarshalIndent(info, "", "\t")
+			if err != nil {
+				return fmt.Errorf("marshalling key info error: %v", err)
+			}
+			fmt.Println(string(jsb))
+			numAccounts--
 		}
-		fmt.Println(string(jsb))
 	}
 
 	return nil
@@ -445,14 +452,19 @@ func importMnemonic(c *cli.Context) error {
 	}
 
 	numShards := c.Int(numShardsFlag)
-	if numShards == 0 {
+	if (numShards < 1 || numShards > 255) {
 		return fmt.Errorf("%v is invalid", numShardsFlag)
 	}
 	common.MaxShardNumber = numShards
 
-	numAccounts := 5
+        shardFilter := c.Int(shardIDFlag)
+        if (shardFilter > numShards) {
+                return fmt.Errorf("%v is invalid for %v shards", shardIDFlag, numShards) 
+        }
+
+	numAccounts := c.Int(numAccountsFlag)
 	fmt.Printf("mnemonic: %v\n", mnemonic)
-	for i := 0; i < numAccounts; i++ {
+	for i := 0; numAccounts > 0; i++ {
 		childKey, err := w.DeriveChild(uint32(i))
 		if err != nil {
 			return err
@@ -463,11 +475,14 @@ func importMnemonic(c *cli.Context) error {
 			return err
 		}
 
-		jsb, err := json.MarshalIndent(info, "", "\t")
-		if err != nil {
-			return fmt.Errorf("marshalling key info error: %v", err)
+		if (shardFilter < 0 || info.ShardID == byte(shardFilter)) {
+			jsb, err := json.MarshalIndent(info, "", "\t")
+			if err != nil {
+				return fmt.Errorf("marshalling key info error: %v", err)
+			}
+			fmt.Println(string(jsb))
+			numAccounts--
 		}
-		fmt.Println(string(jsb))
 	}
 
 	return nil
1 Like

Haha, sorry, I didn’t pull the latest before going to work. Seems you’ve started this already. :joy:

Where did you get the codes?

We have also added more options for this, but they are still at the development branch.

I was also in development branch but a couple commits back. I forgot to fetch and just started hacking. Funny though that we named our flags the same. :slightly_smiling_face:

2 Likes

Wow, great!