From 26ba1b8c9b36608d3b6a2a249429064ef6a407f7 Mon Sep 17 00:00:00 2001 From: tom Date: Wed, 13 Jul 2022 14:35:33 -0500 Subject: [PATCH 1/2] add support for generating neo3 address from neo private key --- src/__tests__/testVectors.json | 16 +++++++- src/generateWallet/generateWallet.spec.ts | 48 ++++++++++------------- src/generateWallet/generateWallet.ts | 48 ++++++++--------------- src/mpc/generateAPIKeys.ts | 2 +- src/types/MPC.ts | 4 +- 5 files changed, 56 insertions(+), 62 deletions(-) diff --git a/src/__tests__/testVectors.json b/src/__tests__/testVectors.json index c7486fc1..d9a213f8 100644 --- a/src/__tests__/testVectors.json +++ b/src/__tests__/testVectors.json @@ -72,6 +72,20 @@ "address": "ANwZ2RFRKrASBvZifGgjqqJNUbfJUW6gbn" } ], + "neo3": [ + { + "index": 0, + "privateKey": "491aac461bd2e0eb02ffe6cdb534a03617e8811764e4eea042f24231ba99b76f", + "publicKey": "0208035f32c5d0e59f71c55b1e060f6d504c004222c25670ff2b788d76a84af2f2", + "address": "NVM1JPRvibsqvQBwmSFQeW7DgfYmHV9WZ9" + }, + { + "index": 1, + "privateKey": "b478febf68d16aa3fa696d684589b9a706f04065407897319a4a4a33aa2cd1e5", + "publicKey": "03a41d39a4209e18eb79245ea368674edf335a4ebeb8ed344b87d3ccaf3a2c730e", + "address": "NQGUB6AxfmYWowUQVXYa46fadqbsh19MYn" + } + ], "ltc": { "MainNet": { "address": "MCPi7QVw4DGJMapjUNtArnMHCsRQpHPo1e", @@ -132,4 +146,4 @@ } } } -] +] \ No newline at end of file diff --git a/src/generateWallet/generateWallet.spec.ts b/src/generateWallet/generateWallet.spec.ts index dd2a9db4..e22966f5 100644 --- a/src/generateWallet/generateWallet.spec.ts +++ b/src/generateWallet/generateWallet.spec.ts @@ -1,6 +1,7 @@ import { generateNashPayloadSigningKey, generateWallet, CoinType } from './generateWallet' import _ from 'lodash' import testVectors from '../__tests__/testVectors.json' +import { Blockchain } from '../types' // import { cryptoWaitReady } from '@polkadot/util-crypto' test('generates deterministic BIP44 ETH keys', async () => { @@ -31,6 +32,24 @@ test('generates deterministic BIP44 NEO keys', async () => { } }) + +test('generates deterministic BIP44 NEO3 keys', async () => { + + for (const vector of testVectors) { + const masterSeed = Buffer.from(vector.masterSeed, 'hex') + + for (const wallet of vector.wallets.neo3) { + const genWallet = generateWallet(masterSeed, CoinType.NEO, wallet.index, '', Blockchain.NEO3) + expect(genWallet.address).toBe(wallet.address) + expect(genWallet.publicKey).toBe(wallet.publicKey) + expect(genWallet.privateKey).toBe(wallet.privateKey) + expect(genWallet.index).toBe(wallet.index) + } + } + +}) + + test('generates deterministic BIP44 BTC keys', async () => { for (const vector of testVectors) { const masterSeed = Buffer.from(vector.masterSeed, 'hex') @@ -105,34 +124,7 @@ test('generates deterministic BIP44 bitcoincash keys', async () => { } }) -// test('generates deterministic BIP44 dot keys', async () => { -// await cryptoWaitReady() - -// for (const vector of testVectors) { -// const masterSeed = Buffer.from(vector.masterSeed, 'hex') -// const wallet = vector.wallets.dot.MainNet - -// const genWallet = generateWallet(masterSeed, CoinType.DOT, wallet.index, 'MainNet') -// expect(genWallet.address).toBe(wallet.address) -// expect(genWallet.publicKey).toBe(wallet.publicKey) -// expect(genWallet.privateKey).toBe(wallet.privateKey) -// expect(genWallet.index).toBe(wallet.index) -// } -// }) - -// test('generates deterministic BIP44 erd keys', async () => { -// await cryptoWaitReady() - -// for (const vector of testVectors) { -// const masterSeed = Buffer.from(vector.masterSeed, 'hex') -// const wallet = vector.wallets.erd.MainNet -// const genWallet = generateWallet(masterSeed, CoinType.ERD, wallet.index, 'MainNet') -// expect(genWallet.address).toBe(wallet.address) -// expect(genWallet.publicKey).toBe(wallet.publicKey) -// expect(genWallet.privateKey).toBe(wallet.privateKey) -// expect(genWallet.index).toBe(wallet.index) -// } -// }) + test('generates deterministic payload signing key', async () => { for (const vector of testVectors) { diff --git a/src/generateWallet/generateWallet.ts b/src/generateWallet/generateWallet.ts index a228af8f..14b8916a 100644 --- a/src/generateWallet/generateWallet.ts +++ b/src/generateWallet/generateWallet.ts @@ -1,5 +1,5 @@ import * as bip32 from 'bip32' -import { Wallet } from '../types' +import { Blockchain, Wallet } from '../types' import { reverseHex } from '../utils/getNEOScriptHash/getNEOScripthash' import * as EthUtil from 'ethereumjs-util' import * as Bitcoin from 'bitcoinjs-lib' @@ -33,21 +33,18 @@ export enum CoinType { const NON_SEGWIT = [CoinType.BCH, CoinType.DOGE] -// interface DotKeyPair { -// publicKey: Uint8Array -// address: string -// } + /** * Creates a wallet for a given token via the * [BIP-44 protocol]((https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki). * * Requires the user's master seed. */ -export function generateWallet(masterSeed: Buffer, coinType: CoinType, index: number, net?: string): Wallet { +export function generateWallet(masterSeed: Buffer, coinType: CoinType, index: number, net?: string, blockchain?: Blockchain): Wallet { const key = derivePath(masterSeed, bip44Purpose, coinType, 0, 0) const derivedChainKey = deriveIndex(key, index) - return generateWalletForCoinType(derivedChainKey, coinType, index, net) + return generateWalletForCoinType(derivedChainKey, coinType, index, net, blockchain) } /** @@ -128,7 +125,10 @@ export function neoGetPublicKeyFromPrivateKey(privateKey: string, encode: boolea } } -const getVerificationScriptFromPublicKey = (publicKey: string): string => { +const getVerificationScriptFromPublicKey = (publicKey: string, blockchain?: Blockchain): string => { + if (blockchain && blockchain === Blockchain.NEO3) { + return '0c21' + publicKey + '4156e7b327' + } return '21' + publicKey + 'ac' } @@ -153,15 +153,17 @@ export function hash256(hex: string): string { } const ADDR_VERSION = '17' +const NEO3_ADDR_VERSION = '35' -export const getAddressFromScriptHash = (scriptHash: string): string => { +export const getAddressFromScriptHash = (scriptHash: string, addressVersion: string): string => { const scriptHashReversed = reverseHex(scriptHash) - const shaChecksum = hash256(ADDR_VERSION + scriptHashReversed).substr(0, 8) - return base58.encode(Buffer.from(ADDR_VERSION + scriptHashReversed + shaChecksum, 'hex')) + const shaChecksum = hash256(addressVersion + scriptHashReversed).substr(0, 8) + return base58.encode(Buffer.from(addressVersion + scriptHashReversed + shaChecksum, 'hex')) } + // NOTE: We can split this out later when there are more wallets needs to be derived. -function generateWalletForCoinType(key: bip32.BIP32Interface, coinType: CoinType, index: number, net?: string): Wallet { +function generateWalletForCoinType(key: bip32.BIP32Interface, coinType: CoinType, index: number, net?: string, blockchain?: Blockchain): Wallet { if (key.privateKey === undefined) { throw new Error('private key not properly derived') } @@ -169,10 +171,11 @@ function generateWalletForCoinType(key: bip32.BIP32Interface, coinType: CoinType case CoinType.NEO: const neoPrivKey = key.privateKey.toString('hex') const publicKey = neoGetPublicKeyFromPrivateKey(neoPrivKey) - const verifiedScript = getVerificationScriptFromPublicKey(publicKey) + const verifiedScript = getVerificationScriptFromPublicKey(publicKey, blockchain) const scriptHash = reverseHex(hash160(verifiedScript)) + const addressVersion = (blockchain && blockchain === Blockchain.NEO3) ? NEO3_ADDR_VERSION : ADDR_VERSION return { - address: getAddressFromScriptHash(scriptHash), + address: getAddressFromScriptHash(scriptHash, addressVersion), index, privateKey: neoPrivKey, publicKey @@ -200,23 +203,6 @@ function generateWalletForCoinType(key: bip32.BIP32Interface, coinType: CoinType privateKey: key.privateKey.toString('hex'), publicKey: key.publicKey.toString('hex') } - // case CoinType.DOT: - // const keypair = dotKeypairFromSeed(key.privateKey) - // return { - // address: keypair.address, - // index, - // privateKey: key.privateKey.toString('hex'), - // publicKey: new Buffer(keypair.publicKey).toString('hex') - // } - // case CoinType.ERD: - // const account = new erdAccount() - // account.loadFromSeed(key.privateKey) - // return { - // address: account.address(), - // index, - // privateKey: key.privateKey.toString('hex'), - // publicKey: account.publicKeyAsString() - // } default: throw new Error(`invalid coin type ${coinType} for generating a wallet`) } diff --git a/src/mpc/generateAPIKeys.ts b/src/mpc/generateAPIKeys.ts index b94e6835..63afc77a 100644 --- a/src/mpc/generateAPIKeys.ts +++ b/src/mpc/generateAPIKeys.ts @@ -84,7 +84,7 @@ export async function generateAPIKeys(params: GenerateApiKeysParams): Promise = { [Blockchain.ETH]: 'Secp256k1', [Blockchain.NEO]: 'Secp256r1', [Blockchain.AVAXC]: 'Secp256k1', - [Blockchain.POLYGON]: 'Secp256k1' + [Blockchain.POLYGON]: 'Secp256k1', + [Blockchain.NEO3]: 'Secp256r1', } export interface PallierPK { From 66cc9d7730d56d6f7ff70b1e0b611c14cdefb734 Mon Sep 17 00:00:00 2001 From: tom Date: Fri, 15 Jul 2022 13:00:35 -0500 Subject: [PATCH 2/2] chore(release): 4.8.1 --- CHANGELOG.md | 2 ++ package.json | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5510131b..bf4e31a6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. +### [4.8.1](https://github.com/nash-io/nash-protocol/compare/v4.7.2...v4.8.1) (2022-07-15) + ### [4.7.2](https://github.com/nash-io/nash-protocol/compare/v4.7.0...v4.7.2) (2022-02-08) ## [4.7.0](https://github.com/nash-io/nash-protocol/compare/v4.5.12...v4.7.0) (2022-01-13) diff --git a/package.json b/package.json index 5d905c36..9a766fa8 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@neon-exchange/nash-protocol", - "version": "4.7.2", + "version": "4.8.1", "description": "TypeScript implementation of Nash crypto routines", "main": "build/main/index.js", "typings": "build/main/index.d.ts",