feat: new keygen and importkeys for protocol upgrade

This commit is contained in:
Anh Minh 2025-10-20 10:12:49 +07:00 committed by Trinity
parent 262f7d3bc0
commit 2816e5333b
3 changed files with 95 additions and 77 deletions

View File

@ -13,8 +13,8 @@ import (
var ( var (
DomainSeparator = []byte("Nockchain seed") DomainSeparator = []byte("Nockchain seed")
PrivateKeyStart = []byte{4, 178, 67, 11} PrivateKeyStart = []byte{1, 16, 99, 49}
PublicKeyStart = []byte{234, 230, 92} PublicKeyStart = []byte{12, 14, 187, 9}
MagicDyckForPoint = []uint64{0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1} MagicDyckForPoint = []uint64{0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1}
MagicDyckForT8 = []uint64{0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1} MagicDyckForT8 = []uint64{0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1}
MagicDyckForSeed = []uint64{0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1} MagicDyckForSeed = []uint64{0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1}
@ -29,6 +29,13 @@ type MasterKey struct {
ChainCode []byte ChainCode []byte
} }
type KeyType int32
const (
KeyType_PRIVATE KeyType = 0
KeyType_PUBLIC KeyType = 1
)
func (m *MasterKey) DeriveChild(index uint64) (MasterKey, error) { func (m *MasterKey) DeriveChild(index uint64) (MasterKey, error) {
idxBytes := make([]byte, 4) idxBytes := make([]byte, 4)
binary.BigEndian.PutUint32(idxBytes, uint32(index)) binary.BigEndian.PutUint32(idxBytes, uint32(index))
@ -184,18 +191,29 @@ func BigIntToT8(data big.Int) [8]uint64 {
res := rip(data) res := rip(data)
return [8]uint64(res) return [8]uint64(res)
} }
func SerializeExtend(chainCode []byte, key []byte, version []byte) []byte { func SerializeExtend(chainCode []byte, key []byte, keyType KeyType) []byte {
data := version data := []byte{}
// dep: depth in chain // dep: depth in chain
// idx: index at depth // idx: index at depth
// pf: parent fingerprint // pf: parent fingerprint
// ver: version
ver := 0
depth := 0 depth := 0
idx := []byte{0, 0, 0, 0} idx := []byte{0, 0, 0, 0}
pf := []byte{0, 0, 0, 0} pf := []byte{0, 0, 0, 0}
data = append(data, byte(depth%256)) var typ []byte
data = append(data, pf...) switch keyType {
data = append(data, idx...) case KeyType_PRIVATE:
data = append(data, chainCode...) typ = PrivateKeyStart
case KeyType_PUBLIC:
typ = PublicKeyStart
}
data = append(data, typ...) // 4 bytes
data = append(data, byte(ver)) // 1 byte
data = append(data, byte(depth%256)) // 1 byte
data = append(data, pf...) // 4 bytes
data = append(data, idx...) // 4 bytes
data = append(data, chainCode...) // 32 bytes
data = append(data, key...) data = append(data, key...)
return AddChecksum(data) return AddChecksum(data)
} }

View File

@ -54,8 +54,8 @@ func (h *GprcHandler) Keygen(ctx context.Context, req *nockchain.KeygenRequest)
PrivateKey: base58.Encode(masterKey.PrivateKey), PrivateKey: base58.Encode(masterKey.PrivateKey),
PublicKey: base58.Encode(masterKey.PublicKey), PublicKey: base58.Encode(masterKey.PublicKey),
ChainCode: base58.Encode(masterKey.ChainCode), ChainCode: base58.Encode(masterKey.ChainCode),
ImportPrivateKey: base58.Encode(crypto.SerializeExtend(masterKey.ChainCode, privBytes, crypto.PrivateKeyStart)), ImportPrivateKey: base58.Encode(crypto.SerializeExtend(masterKey.ChainCode, privBytes, crypto.KeyType_PRIVATE)),
ImportPublicKey: base58.Encode(crypto.SerializeExtend(masterKey.ChainCode, masterKey.PublicKey, crypto.PublicKeyStart)), ImportPublicKey: base58.Encode(crypto.SerializeExtend(masterKey.ChainCode, masterKey.PublicKey, crypto.KeyType_PUBLIC)),
}, nil }, nil
} }
@ -68,21 +68,21 @@ func (h *GprcHandler) ImportKeys(ctx context.Context, req *nockchain.ImportKeysR
data := base58.Decode(req.Key) data := base58.Decode(req.Key)
switch { switch {
case strings.HasPrefix(req.Key, "zprv"): case strings.HasPrefix(req.Key, "zprv"):
if len(data) != 82 { if len(data) != 83 {
return nil, fmt.Errorf("invalid extended private key length: %d (expected 82)", len(data)) return nil, fmt.Errorf("invalid extended private key length: %d (expected 83)", len(data))
} }
if data[45] != 0x00 { if data[46] != 0x00 {
return nil, fmt.Errorf("invalid private key prefix at byte 45: 0x%02x (expected 0x00)", data[45]) return nil, fmt.Errorf("invalid private key prefix at byte 46: 0x%02x (expected 0x00)", data[46])
} }
hash := sha256.Sum256(data[:78]) hash := sha256.Sum256(data[:79])
hash = sha256.Sum256(hash[:]) hash = sha256.Sum256(hash[:])
if !slices.Equal(hash[:4], data[78:]) { if !slices.Equal(hash[:4], data[79:]) {
return nil, fmt.Errorf("invalid checksum") return nil, fmt.Errorf("invalid checksum")
} }
chainCode := make([]byte, 32) chainCode := make([]byte, 32)
copy(chainCode, data[13:45]) copy(chainCode, data[14:46])
privateKey := make([]byte, 32) privateKey := make([]byte, 32)
copy(privateKey, data[46:78]) copy(privateKey, data[47:79])
masterKey, err := crypto.MasterKeyFromPrivKey(chainCode, privateKey) masterKey, err := crypto.MasterKeyFromPrivKey(chainCode, privateKey)
if err != nil { if err != nil {
return nil, err return nil, err
@ -93,31 +93,31 @@ func (h *GprcHandler) ImportKeys(ctx context.Context, req *nockchain.ImportKeysR
PrivateKey: base58.Encode(masterKey.PrivateKey), PrivateKey: base58.Encode(masterKey.PrivateKey),
PublicKey: base58.Encode(masterKey.PublicKey), PublicKey: base58.Encode(masterKey.PublicKey),
ChainCode: base58.Encode(masterKey.ChainCode), ChainCode: base58.Encode(masterKey.ChainCode),
ImportPrivateKey: base58.Encode(crypto.SerializeExtend(masterKey.ChainCode, privBytes, crypto.PrivateKeyStart)), ImportPrivateKey: base58.Encode(crypto.SerializeExtend(masterKey.ChainCode, privBytes, crypto.KeyType_PRIVATE)),
ImportPublicKey: base58.Encode(crypto.SerializeExtend(masterKey.ChainCode, masterKey.PublicKey, crypto.PublicKeyStart)), ImportPublicKey: base58.Encode(crypto.SerializeExtend(masterKey.ChainCode, masterKey.PublicKey, crypto.KeyType_PUBLIC)),
}, nil }, nil
case strings.HasPrefix(req.Key, "zpub"): case strings.HasPrefix(req.Key, "zpub"):
if len(data) != 145 { if len(data) != 147 {
return nil, fmt.Errorf("invalid extended public key length: %d (expected 145)", len(data)) return nil, fmt.Errorf("invalid extended public key length: %d (expected 147)", len(data))
} }
hash := sha256.Sum256(data[:141]) hash := sha256.Sum256(data[:143])
hash = sha256.Sum256(hash[:]) hash = sha256.Sum256(hash[:])
if !slices.Equal(hash[:4], data[141:]) { if !slices.Equal(hash[:4], data[143:]) {
return nil, fmt.Errorf("invalid checksum") return nil, fmt.Errorf("invalid checksum")
} }
chainCode := make([]byte, 32) chainCode := make([]byte, 32)
copy(chainCode, data[12:44]) copy(chainCode, data[14:46])
publicKey := make([]byte, 97) publicKey := make([]byte, 97)
copy(publicKey, data[44:141]) copy(publicKey, data[46:143])
return &nockchain.ImportKeysResponse{ return &nockchain.ImportKeysResponse{
Seed: "", Seed: "",
PrivateKey: "", PrivateKey: "",
PublicKey: base58.Encode(publicKey), PublicKey: base58.Encode(publicKey),
ChainCode: base58.Encode(chainCode), ChainCode: base58.Encode(chainCode),
ImportPrivateKey: "", ImportPrivateKey: "",
ImportPublicKey: base58.Encode(crypto.SerializeExtend(chainCode, publicKey, crypto.PublicKeyStart)), ImportPublicKey: base58.Encode(crypto.SerializeExtend(chainCode, publicKey, crypto.KeyType_PUBLIC)),
}, nil }, nil
default: default:
return nil, fmt.Errorf("invalid extended key") return nil, fmt.Errorf("invalid extended key")
@ -145,8 +145,8 @@ func (h *GprcHandler) ImportKeys(ctx context.Context, req *nockchain.ImportKeysR
PrivateKey: base58.Encode(masterKey.PrivateKey), PrivateKey: base58.Encode(masterKey.PrivateKey),
PublicKey: base58.Encode(masterKey.PublicKey), PublicKey: base58.Encode(masterKey.PublicKey),
ChainCode: base58.Encode(masterKey.ChainCode), ChainCode: base58.Encode(masterKey.ChainCode),
ImportPrivateKey: base58.Encode(crypto.SerializeExtend(masterKey.ChainCode, privBytes, crypto.PrivateKeyStart)), ImportPrivateKey: base58.Encode(crypto.SerializeExtend(masterKey.ChainCode, privBytes, crypto.KeyType_PRIVATE)),
ImportPublicKey: base58.Encode(crypto.SerializeExtend(masterKey.ChainCode, masterKey.PublicKey, crypto.PublicKeyStart)), ImportPublicKey: base58.Encode(crypto.SerializeExtend(masterKey.ChainCode, masterKey.PublicKey, crypto.KeyType_PUBLIC)),
}, nil }, nil
case nockchain.ImportType_SEEDPHRASE: case nockchain.ImportType_SEEDPHRASE:
masterKey, err := crypto.MasterKeyFromSeed(req.Key) masterKey, err := crypto.MasterKeyFromSeed(req.Key)
@ -159,8 +159,8 @@ func (h *GprcHandler) ImportKeys(ctx context.Context, req *nockchain.ImportKeysR
PrivateKey: base58.Encode(masterKey.PrivateKey), PrivateKey: base58.Encode(masterKey.PrivateKey),
PublicKey: base58.Encode(masterKey.PublicKey), PublicKey: base58.Encode(masterKey.PublicKey),
ChainCode: base58.Encode(masterKey.ChainCode), ChainCode: base58.Encode(masterKey.ChainCode),
ImportPrivateKey: base58.Encode(crypto.SerializeExtend(masterKey.ChainCode, privBytes, crypto.PrivateKeyStart)), ImportPrivateKey: base58.Encode(crypto.SerializeExtend(masterKey.ChainCode, privBytes, crypto.KeyType_PRIVATE)),
ImportPublicKey: base58.Encode(crypto.SerializeExtend(masterKey.ChainCode, masterKey.PublicKey, crypto.PublicKeyStart)), ImportPublicKey: base58.Encode(crypto.SerializeExtend(masterKey.ChainCode, masterKey.PublicKey, crypto.KeyType_PUBLIC)),
}, nil }, nil
case nockchain.ImportType_WATCH_ONLY: case nockchain.ImportType_WATCH_ONLY:
pubKey := base58.Decode(req.Key) pubKey := base58.Decode(req.Key)
@ -188,21 +188,21 @@ func (h *GprcHandler) DeriveChild(ctx context.Context, req *nockchain.DeriveChil
} }
switch { switch {
case strings.HasPrefix(req.ImportedKey, "zprv"): case strings.HasPrefix(req.ImportedKey, "zprv"):
if len(data) != 82 { if len(data) != 83 {
return nil, fmt.Errorf("invalid extended private key length: %d (expected 82)", len(data)) return nil, fmt.Errorf("invalid extended private key length: %d (expected 83)", len(data))
} }
if data[45] != 0x00 { if data[46] != 0x00 {
return nil, fmt.Errorf("invalid private key prefix at byte 45: 0x%02x (expected 0x00)", data[45]) return nil, fmt.Errorf("invalid private key prefix at byte 46: 0x%02x (expected 0x00)", data[46])
} }
hash := sha256.Sum256(data[:78]) hash := sha256.Sum256(data[:79])
hash = sha256.Sum256(hash[:]) hash = sha256.Sum256(hash[:])
if !slices.Equal(hash[:4], data[78:]) { if !slices.Equal(hash[:4], data[79:]) {
return nil, fmt.Errorf("invalid checksum") return nil, fmt.Errorf("invalid checksum")
} }
chainCode := make([]byte, 32) chainCode := make([]byte, 32)
copy(chainCode, data[13:45]) copy(chainCode, data[14:46])
privateKey := make([]byte, 32) privateKey := make([]byte, 32)
copy(privateKey, data[46:78]) copy(privateKey, data[47:79])
masterKey, err := crypto.MasterKeyFromPrivKey(chainCode, privateKey) masterKey, err := crypto.MasterKeyFromPrivKey(chainCode, privateKey)
if err != nil { if err != nil {
return nil, err return nil, err
@ -219,20 +219,20 @@ func (h *GprcHandler) DeriveChild(ctx context.Context, req *nockchain.DeriveChil
}, nil }, nil
case strings.HasPrefix(req.ImportedKey, "zpub"): case strings.HasPrefix(req.ImportedKey, "zpub"):
if len(data) != 145 { if len(data) != 147 {
return nil, fmt.Errorf("invalid extended public key length: %d (expected 145)", len(data)) return nil, fmt.Errorf("invalid extended public key length: %d (expected 145)", len(data))
} }
hash := sha256.Sum256(data[:141]) hash := sha256.Sum256(data[:143])
hash = sha256.Sum256(hash[:]) hash = sha256.Sum256(hash[:])
if !slices.Equal(hash[:4], data[141:]) { if !slices.Equal(hash[:4], data[143:]) {
return nil, fmt.Errorf("invalid checksum") return nil, fmt.Errorf("invalid checksum")
} }
chainCode := make([]byte, 32) chainCode := make([]byte, 32)
copy(chainCode, data[13:45]) copy(chainCode, data[14:46])
publicKey := make([]byte, 97) publicKey := make([]byte, 97)
copy(publicKey, data[45:141]) copy(publicKey, data[46:143])
masterKey := crypto.MasterKey{ masterKey := crypto.MasterKey{
PublicKey: publicKey, PublicKey: publicKey,

View File

@ -17,13 +17,13 @@ import (
// The entropy, salt and result is taken from "nockchain-wallet keygen" command // The entropy, salt and result is taken from "nockchain-wallet keygen" command
func TestKeyGen(t *testing.T) { func TestKeyGen(t *testing.T) {
entropyBigInt, isOk := new(big.Int).SetString("29615235796517918707367078072007441124337225858809749976291970867443501879006", 10) entropyBigInt, isOk := new(big.Int).SetString("37133536588676344913489312523941366110857274548479981512263368615793750653450", 10)
assert.True(t, isOk) assert.True(t, isOk)
entropy := entropyBigInt.Bytes() entropy := entropyBigInt.Bytes()
assert.Len(t, entropy, 32) assert.Len(t, entropy, 32)
saltBigInt, isOk := new(big.Int).SetString("212311808188922973323281316240858086116", 10) saltBigInt, isOk := new(big.Int).SetString("251632902249061493058993135304695174381", 10)
assert.True(t, isOk) assert.True(t, isOk)
salt := saltBigInt.Bytes() salt := saltBigInt.Bytes()
@ -33,38 +33,38 @@ func TestKeyGen(t *testing.T) {
slices.Reverse(argonBytes) slices.Reverse(argonBytes)
mnemonic, err := bip39.NewMnemonic(argonBytes) mnemonic, err := bip39.NewMnemonic(argonBytes)
assert.NoError(t, err) assert.NoError(t, err)
assert.Equal(t, mnemonic, "brass vacuum stairs hurt brisk govern describe enforce fly exact rescue capable belt flavor lottery sauce easy frame orange legal injury border obey novel") assert.Equal(t, mnemonic, "include lounge salad chicken trumpet embrace grace mercy pulp submit alter weapon plastic welcome funny female palm satoshi open file knock sun fade match")
masterKey, err := crypto.MasterKeyFromSeed(mnemonic) masterKey, err := crypto.MasterKeyFromSeed(mnemonic)
assert.NoError(t, err) assert.NoError(t, err)
assert.Equal(t, assert.Equal(t,
base58.Encode(masterKey.PublicKey), base58.Encode(masterKey.PublicKey),
"39DL6YA1kSRCKMjzpFEtC8rmnxVuseUrP2LnViwY7YEhZYZkX2HmnAZ63Uwy1DwuXstmF1VeJDucg719xw49j9CKL3bsKq3A6SZN918CowcgQroHsgohj7dYgpGRWk41s42F", "34VqjU7ojQXWiFZz7kvXe1xfxhbdimmqqUAgp21XGESLqJSXxHkqrcquWirFcCPPj1pmSL4pRc8GndZoiiK8ijeYjgcJ3QR7fb2s4b2WdJhDao4Dx7gw3NRSt4RjXawqUQw6",
) )
assert.Equal(t, assert.Equal(t,
base58.Encode(masterKey.PrivateKey), base58.Encode(masterKey.PrivateKey),
"4SyUrsbGKPRknzvGakWmFbYefzHzb1r4LUmJpQD8WPcR", "3B8Q5ZTHH63h9DT6WSwNZhea5zvtueuKpxk3qwZJEjsg",
) )
assert.Equal(t, assert.Equal(t,
base58.Encode(masterKey.ChainCode), base58.Encode(masterKey.ChainCode),
"58SARPmADHvUcpq7XfBoCgwzy5QC8Kb3JrezpHqA85x2", "2ztGPxS8xYzMXoAHf3HMbMuyh4siew8X4Kz4KuTXvqX8",
) )
// assert import priv/pubkey // assert import priv/pubkey
privBytes := append([]byte{0x00}, masterKey.PrivateKey...) privBytes := append([]byte{0x00}, masterKey.PrivateKey...)
importPrivKey := crypto.SerializeExtend(masterKey.ChainCode, privBytes, crypto.PrivateKeyStart) importPrivKey := crypto.SerializeExtend(masterKey.ChainCode, privBytes, crypto.KeyType_PRIVATE)
assert.Len(t, importPrivKey, 82) assert.Len(t, importPrivKey, 83)
importPubKey := crypto.SerializeExtend(masterKey.ChainCode, masterKey.PublicKey, crypto.PublicKeyStart) importPubKey := crypto.SerializeExtend(masterKey.ChainCode, masterKey.PublicKey, crypto.KeyType_PUBLIC)
assert.Len(t, importPubKey, 145) assert.Len(t, importPubKey, 147)
assert.Equal(t, assert.Equal(t,
base58.Encode(importPrivKey), base58.Encode(importPrivKey),
"zprv2CyrSHEkzQzu4HCtJRFiP4t2rVMauZwLfJDFrNbqS8Pz3nsmXy5bAUx2HYUykaMuU4MiQTHsDcKYjLCjrPfpceNT9XBHgx1pUjKzBrF6Wdo", "zprvLpf3WSvYWmHRd3jj5oR8UXr7bi88pGnfJXj1dM9RnwJwu1MLo6fZzcKauqpxL2W7dk2fmjYKAUzavbyaGpnvqY5QndcrUzsBrPQAHXNnhiXx",
) )
assert.Equal(t, assert.Equal(t,
base58.Encode(importPubKey), base58.Encode(importPubKey),
"zpubUQwNTNE3hsCkMpBnD37W5QirkyVryokAVPLnPin1c6M13RRsq3yEJbwp5ies6qXF6DvJq5Woxw6ygT53PSVrmrsQgtHhbfMEixKNFm7qb4mELhpyoovpFEV1YPHFZx4xQGYBNF6qvXU6AHNh4TLrUdkYAdXKS2J5rPiSVPrXKGo8fLG6ZBCGBjJfPcwDb2VEJC", "zpub2jgndknkQprVYB4X4mqREyn7ZTUE5zp9qkSugdpiqhC5NSeNBceafoz6jGSLEpzJhaLryvY8MF6TokwZN627UXhsg5zd2U12woEL82UtZaLHRL8PZi8YiQnE41BiNJwkfpWjzAbq8mwbAHV3nXUEFgJW2BKCz4GmfoMCkCUDhJppYh5KFsMUkN41DzsfFZHuFrzo",
) )
} }
@ -76,32 +76,32 @@ func TestImportKey(t *testing.T) {
errStr string errStr string
} }
correctImportPrivKey := base58.Decode("zprv2CyrSHEkzQzu4HCtJRFiP4t2rVMauZwLfJDFrNbqS8Pz3nsmXy5bAUx2HYUykaMuU4MiQTHsDcKYjLCjrPfpceNT9XBHgx1pUjKzBrF6Wdo") correctImportPrivKey := base58.Decode("zprvLpf3WSvYWmHRd3jj5oR8UXr7bi88pGnfJXj1dM9RnwJwu1MLo6fZzcKauqpxL2W7dk2fmjYKAUzavbyaGpnvqY5QndcrUzsBrPQAHXNnhiXx")
invalidImportPrivKeyPrefix := make([]byte, 82) invalidImportPrivKeyPrefix := make([]byte, 83)
copy(invalidImportPrivKeyPrefix[:], correctImportPrivKey) copy(invalidImportPrivKeyPrefix[:], correctImportPrivKey)
invalidImportPrivKeyPrefix[45] = 0x01 invalidImportPrivKeyPrefix[46] = 0x01
invalidImportPrivKeyChecksum := make([]byte, 82) invalidImportPrivKeyChecksum := make([]byte, 83)
copy(invalidImportPrivKeyChecksum[:], correctImportPrivKey) copy(invalidImportPrivKeyChecksum[:], correctImportPrivKey)
copy(invalidImportPrivKeyChecksum[78:], []byte{1, 2, 3, 4}) copy(invalidImportPrivKeyChecksum[79:], []byte{1, 2, 3, 4})
correctImportPubkey := base58.Decode("zpubUQwNTNE3hsCkMpBnD37W5QirkyVryokAVPLnPin1c6M13RRsq3yEJbwp5ies6qXF6DvJq5Woxw6ygT53PSVrmrsQgtHhbfMEixKNFm7qb4mELhpyoovpFEV1YPHFZx4xQGYBNF6qvXU6AHNh4TLrUdkYAdXKS2J5rPiSVPrXKGo8fLG6ZBCGBjJfPcwDb2VEJC") correctImportPubkey := base58.Decode("zpub2jgndknkQprVYB4X4mqREyn7ZTUE5zp9qkSugdpiqhC5NSeNBceafoz6jGSLEpzJhaLryvY8MF6TokwZN627UXhsg5zd2U12woEL82UtZaLHRL8PZi8YiQnE41BiNJwkfpWjzAbq8mwbAHV3nXUEFgJW2BKCz4GmfoMCkCUDhJppYh5KFsMUkN41DzsfFZHuFrzo")
invalidImportPubkeyChecksum := make([]byte, 145) invalidImportPubkeyChecksum := make([]byte, 147)
copy(invalidImportPubkeyChecksum[:], correctImportPubkey) copy(invalidImportPubkeyChecksum[:], correctImportPubkey)
copy(invalidImportPubkeyChecksum[141:], []byte{1, 2, 3, 4}) copy(invalidImportPubkeyChecksum[143:], []byte{1, 2, 3, 4})
response := &nockchain.ImportKeysResponse{ response := &nockchain.ImportKeysResponse{
PublicKey: "39DL6YA1kSRCKMjzpFEtC8rmnxVuseUrP2LnViwY7YEhZYZkX2HmnAZ63Uwy1DwuXstmF1VeJDucg719xw49j9CKL3bsKq3A6SZN918CowcgQroHsgohj7dYgpGRWk41s42F", PublicKey: "34VqjU7ojQXWiFZz7kvXe1xfxhbdimmqqUAgp21XGESLqJSXxHkqrcquWirFcCPPj1pmSL4pRc8GndZoiiK8ijeYjgcJ3QR7fb2s4b2WdJhDao4Dx7gw3NRSt4RjXawqUQw6",
PrivateKey: "4SyUrsbGKPRknzvGakWmFbYefzHzb1r4LUmJpQD8WPcR", PrivateKey: "3B8Q5ZTHH63h9DT6WSwNZhea5zvtueuKpxk3qwZJEjsg",
ChainCode: "58SARPmADHvUcpq7XfBoCgwzy5QC8Kb3JrezpHqA85x2", ChainCode: "2ztGPxS8xYzMXoAHf3HMbMuyh4siew8X4Kz4KuTXvqX8",
ImportPrivateKey: base58.Encode(correctImportPrivKey), ImportPrivateKey: base58.Encode(correctImportPrivKey),
ImportPublicKey: base58.Encode(correctImportPubkey), ImportPublicKey: base58.Encode(correctImportPubkey),
} }
responseReadOnly := &nockchain.ImportKeysResponse{ responseReadOnly := &nockchain.ImportKeysResponse{
PublicKey: "39DL6YA1kSRCKMjzpFEtC8rmnxVuseUrP2LnViwY7YEhZYZkX2HmnAZ63Uwy1DwuXstmF1VeJDucg719xw49j9CKL3bsKq3A6SZN918CowcgQroHsgohj7dYgpGRWk41s42F", PublicKey: "34VqjU7ojQXWiFZz7kvXe1xfxhbdimmqqUAgp21XGESLqJSXxHkqrcquWirFcCPPj1pmSL4pRc8GndZoiiK8ijeYjgcJ3QR7fb2s4b2WdJhDao4Dx7gw3NRSt4RjXawqUQw6",
PrivateKey: "", PrivateKey: "",
ChainCode: "58SARPmADHvUcpq7XfBoCgwzy5QC8Kb3JrezpHqA85x2", ChainCode: "2ztGPxS8xYzMXoAHf3HMbMuyh4siew8X4Kz4KuTXvqX8",
ImportPrivateKey: "", ImportPrivateKey: "",
ImportPublicKey: base58.Encode(correctImportPubkey), ImportPublicKey: base58.Encode(correctImportPubkey),
} }
@ -142,7 +142,7 @@ func TestImportKey(t *testing.T) {
}, },
expectResp: nil, expectResp: nil,
isErr: true, isErr: true,
errStr: "invalid private key prefix at byte 45", errStr: "invalid private key prefix at byte 46",
}, },
{ {
req: &nockchain.ImportKeysRequest{ req: &nockchain.ImportKeysRequest{
@ -195,7 +195,7 @@ func TestImportKey(t *testing.T) {
// case missing chaincode when import master privkey // case missing chaincode when import master privkey
{ {
req: &nockchain.ImportKeysRequest{ req: &nockchain.ImportKeysRequest{
Key: "4SyUrsbGKPRknzvGakWmFbYefzHzb1r4LUmJpQD8WPcR", Key: "3B8Q5ZTHH63h9DT6WSwNZhea5zvtueuKpxk3qwZJEjsg",
ImportType: nockchain.ImportType_MASTER_PRIVKEY, ImportType: nockchain.ImportType_MASTER_PRIVKEY,
}, },
expectResp: nil, expectResp: nil,
@ -205,7 +205,7 @@ func TestImportKey(t *testing.T) {
// case invalid length // case invalid length
{ {
req: &nockchain.ImportKeysRequest{ req: &nockchain.ImportKeysRequest{
Key: "abcdxyz,4SyUrsbGKPRknzvGakWmFbYefzHzb1r4LUmJpQD8WPcR", Key: "abcdxyz,3B8Q5ZTHH63h9DT6WSwNZhea5zvtueuKpxk3qwZJEjsg",
ImportType: nockchain.ImportType_MASTER_PRIVKEY, ImportType: nockchain.ImportType_MASTER_PRIVKEY,
}, },
expectResp: nil, expectResp: nil,
@ -214,7 +214,7 @@ func TestImportKey(t *testing.T) {
}, },
{ {
req: &nockchain.ImportKeysRequest{ req: &nockchain.ImportKeysRequest{
Key: "58SARPmADHvUcpq7XfBoCgwzy5QC8Kb3JrezpHqA85x2,abcdxyz", Key: "2ztGPxS8xYzMXoAHf3HMbMuyh4siew8X4Kz4KuTXvqX8,abcdxyz",
ImportType: nockchain.ImportType_MASTER_PRIVKEY, ImportType: nockchain.ImportType_MASTER_PRIVKEY,
}, },
expectResp: nil, expectResp: nil,
@ -224,7 +224,7 @@ func TestImportKey(t *testing.T) {
// case success import master privkey // case success import master privkey
{ {
req: &nockchain.ImportKeysRequest{ req: &nockchain.ImportKeysRequest{
Key: "58SARPmADHvUcpq7XfBoCgwzy5QC8Kb3JrezpHqA85x2,4SyUrsbGKPRknzvGakWmFbYefzHzb1r4LUmJpQD8WPcR", Key: "2ztGPxS8xYzMXoAHf3HMbMuyh4siew8X4Kz4KuTXvqX8,3B8Q5ZTHH63h9DT6WSwNZhea5zvtueuKpxk3qwZJEjsg",
ImportType: nockchain.ImportType_MASTER_PRIVKEY, ImportType: nockchain.ImportType_MASTER_PRIVKEY,
}, },
expectResp: response, expectResp: response,
@ -234,7 +234,7 @@ func TestImportKey(t *testing.T) {
// case success import seed // case success import seed
{ {
req: &nockchain.ImportKeysRequest{ req: &nockchain.ImportKeysRequest{
Key: "brass vacuum stairs hurt brisk govern describe enforce fly exact rescue capable belt flavor lottery sauce easy frame orange legal injury border obey novel", Key: "include lounge salad chicken trumpet embrace grace mercy pulp submit alter weapon plastic welcome funny female palm satoshi open file knock sun fade match",
ImportType: nockchain.ImportType_SEEDPHRASE, ImportType: nockchain.ImportType_SEEDPHRASE,
}, },
expectResp: response, expectResp: response,
@ -244,11 +244,11 @@ func TestImportKey(t *testing.T) {
// case sucess import pubkey // case sucess import pubkey
{ {
req: &nockchain.ImportKeysRequest{ req: &nockchain.ImportKeysRequest{
Key: "39DL6YA1kSRCKMjzpFEtC8rmnxVuseUrP2LnViwY7YEhZYZkX2HmnAZ63Uwy1DwuXstmF1VeJDucg719xw49j9CKL3bsKq3A6SZN918CowcgQroHsgohj7dYgpGRWk41s42F", Key: "34VqjU7ojQXWiFZz7kvXe1xfxhbdimmqqUAgp21XGESLqJSXxHkqrcquWirFcCPPj1pmSL4pRc8GndZoiiK8ijeYjgcJ3QR7fb2s4b2WdJhDao4Dx7gw3NRSt4RjXawqUQw6",
ImportType: nockchain.ImportType_WATCH_ONLY, ImportType: nockchain.ImportType_WATCH_ONLY,
}, },
expectResp: &nockchain.ImportKeysResponse{ expectResp: &nockchain.ImportKeysResponse{
PublicKey: "39DL6YA1kSRCKMjzpFEtC8rmnxVuseUrP2LnViwY7YEhZYZkX2HmnAZ63Uwy1DwuXstmF1VeJDucg719xw49j9CKL3bsKq3A6SZN918CowcgQroHsgohj7dYgpGRWk41s42F", PublicKey: "34VqjU7ojQXWiFZz7kvXe1xfxhbdimmqqUAgp21XGESLqJSXxHkqrcquWirFcCPPj1pmSL4pRc8GndZoiiK8ijeYjgcJ3QR7fb2s4b2WdJhDao4Dx7gw3NRSt4RjXawqUQw6",
}, },
isErr: false, isErr: false,
errStr: "", errStr: "",