Skip to content

Commit

Permalink
Merge pull request #288 from casper-ecosystem/feature/ed25519-hd-wallet
Browse files Browse the repository at this point in the history
Implement Ed25519 HD Wallet
  • Loading branch information
hoffmannjan authored May 15, 2023
2 parents 319099d + 67b363b commit 08d9996
Show file tree
Hide file tree
Showing 19 changed files with 746 additions and 133 deletions.
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@ Basic library usage can be found below files:
- [CLByteArray](https://github.com/casper-ecosystem/casper-js-sdk/tree/dev/src/lib/CLValue/ByteArray.test.ts)
- [CLOption](https://github.com/casper-ecosystem/casper-js-sdk/tree/dev/src/lib/CLValue/Option.test.ts)
- [CLList](https://github.com/casper-ecosystem/casper-js-sdk/tree/dev/src/lib/CLValue/List.test.ts)
- [HDKeys](https://github.com/casper-ecosystem/casper-js-sdk/tree/dev/src/lib/CasperHDKeys)
- [CasperHDKey](https://github.com/casper-ecosystem/casper-js-sdk/tree/dev/src/lib/CasperHDKeys/CasperHDKey.test.ts)
- [Ed25519HDKey](https://github.com/casper-ecosystem/casper-js-sdk/tree/dev/src/lib/CasperHDKeys/Ed25519HDKey.test.ts)
- [Secp256K1HDKey](https://github.com/casper-ecosystem/casper-js-sdk/tree/dev/src/lib/CasperHDKeys/Secp256K1HDKey.test.ts)
- [Keys - Ed25519, Secp256K1](https://github.com/casper-ecosystem/casper-js-sdk/tree/dev/e2e/lib/Keys.test.ts)
- [CasperServiceByJsonRPC](https://github.com/casper-ecosystem/casper-js-sdk/tree/dev/e2e/rpc/RPC.test.ts)
- [CasperClient](https://github.com/casper-ecosystem/casper-js-sdk/tree/dev/e2e/lib/CasperClient.test.ts)
Expand Down
16 changes: 1 addition & 15 deletions e2e/lib/CasperClient.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import * as os from 'os';
import { expect } from 'chai';

import { Secp256K1, SignatureAlgorithm } from '../../src/lib/Keys';
import { decodeBase16, Keys, DeployUtil, CasperClient } from '../../src/lib';
import { Keys, DeployUtil, CasperClient } from '../../src/lib';
import { NODE_URL } from '../config';
import { DEFAULT_DEPLOY_TTL } from '../../src/constants';

Expand Down Expand Up @@ -114,20 +114,6 @@ describe('CasperClient', () => {
expect(loadedKeyPair.privateKey).to.deep.equal(edKeyPair.privateKey);
});

it('should create a HK wallet and derive child account correctly', function() {
const seed =
'fffcf9f6f3f0edeae7e4e1dedbd8d5d2cfccc9c6c3c0bdbab7b4b1aeaba8a5a29f9c999693908d8a8784817e7b7875726f6c696663605d5a5754514e4b484542';
const hdKey = casperClient.newHdWallet(decodeBase16(seed));
const secpKey1 = hdKey.deriveIndex(1);
const msg = Buffer.from('hello world');
const signature = secpKey1.sign(msg);
expect(secpKey1.verify(signature, msg)).to.be.equal(true);

const secpKey2 = hdKey.deriveIndex(2);
const signature2 = secpKey2.sign(msg);
expect(secpKey2.verify(signature2, msg)).to.be.equal(true);
});

it('Signatures in deploy signed using Ed25519 / Secp256K1 key', function() {
const json = JSON.parse(
'{"deploy":{"hash":"510d968d880a89cb92b985578312a535ea1412aaa6cb4a514456135d415b32f5","header":{"account":"0109791772400ea911e2adcb7569d805da75654fc1360c06f93832f020e13aa0cf","timestamp":"2022-04-03T19:18:42.176Z","ttl":"30m","gas_price":1,"body_hash":"ea0a6bc12489f4ccf0b7564bcacd2918b744b9e4b8cad71d52afd9159f33b108","dependencies":[],"chain_name":"casper-test"},"payment":{"ModuleBytes":{"module_bytes":"","args":[["amount",{"bytes":"0500e40b5402","cl_type":"U512"}]]}},"session":{"Transfer":{"args":[["amount",{"bytes":"0500ba1dd205","cl_type":"U512"}],["target",{"bytes":"01861759c3e71b1953f2be3a92c406a3423fd36ea6a8ff6fd0e71bb39685d68893","cl_type":"PublicKey"}],["id",{"bytes":"01addd020000000000","cl_type":{"Option":"U64"}}]]}},"approvals":[]}}'
Expand Down
25 changes: 25 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@
"@noble/secp256k1": "^1.7.1",
"@open-rpc/client-js": "^1.6.2",
"@scure/bip32": "^1.1.5",
"@scure/bip39": "^1.2.0",
"@types/ws": "^8.2.2",
"glob": "^7.1.6",
"humanize-duration": "^3.24.0",
Expand Down
4 changes: 2 additions & 2 deletions src/lib/CLValue/Key.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ import {
AccessRights,
CLAccountHash,
CLByteArray
} from './index'; // CLURef, CLAccountHash } from './index';
import { decodeBase16 } from '../../index';
} from './index';
import { decodeBase16 } from '../Conversions';

describe('CLKey', () => {
const urefAddr =
Expand Down
3 changes: 2 additions & 1 deletion src/lib/CLValue/URef.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { expect } from 'chai';
import { CLURef, CLURefType, CLValueParsers, AccessRights } from './index';
import { decodeBase16 } from '../../index';
import { decodeBase16 } from '../Conversions';

const urefAddr =
'2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a';
Expand All @@ -16,6 +16,7 @@ describe('CLUref', () => {
it('Should be valid by construction', () => {
const badFn1 = () =>
new CLURef(decodeBase16('3a3a3a'), AccessRights.READ_ADD_WRITE);
// @ts-ignore
const badFn2 = () => new CLURef(decodeBase16(urefAddr), 10);

expect(RWExampleURef).to.be.an.instanceof(CLURef);
Expand Down
14 changes: 11 additions & 3 deletions src/lib/CasperClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { DeployUtil, Keys, CLPublicKey } from './index';
import { encodeBase16 } from './Conversions';
import { Deploy, DeployParams, ExecutableDeployItem } from './DeployUtil';
import { AsymmetricKey, SignatureAlgorithm } from './Keys';
import { CasperHDKey } from './CasperHDKey';
import { Secp256K1HDKey, Ed25519HDKey, CasperHDKey } from './CasperHDKeys';
import { BigNumber } from '@ethersproject/bignumber';

export class CasperClient {
Expand Down Expand Up @@ -98,8 +98,16 @@ export class CasperClient {
* @param seed The seed buffer for parent key
* @returns A new bip32 compliant hierarchical deterministic wallet
*/
public newHdWallet(seed: Uint8Array): CasperHDKey {
return CasperHDKey.fromMasterSeed(seed);
public newHdWallet(
seed: Uint8Array,
algo: SignatureAlgorithm
): CasperHDKey<AsymmetricKey> {
switch (algo) {
case SignatureAlgorithm.Ed25519:
return new Ed25519HDKey(seed);
case SignatureAlgorithm.Secp256K1:
return new Secp256K1HDKey(seed);
}
}

/**
Expand Down
90 changes: 0 additions & 90 deletions src/lib/CasperHDKey.ts

This file was deleted.

33 changes: 33 additions & 0 deletions src/lib/CasperHDKeys/CasperHDKey.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { expect } from 'chai';
import { wordlist as chiWordlist } from '@scure/bip39/wordlists/simplified-chinese';

import { CasperHDKey } from './CasperHDKey';

describe('CasperHDKey', () => {
it('should generate mnemonic', () => {
const mn = CasperHDKey.newMnemonic();

expect(CasperHDKey.validateMnemonic(mn));
});

it('should set user specific wordlist', () => {
CasperHDKey.setWordlist(chiWordlist);
expect(CasperHDKey.getWordlist()).eq(chiWordlist);
});

it('should generate 24 length mnemonic', () => {
const mn = CasperHDKey.newMnemonic(24);

expect(mn.split(' ').length === 24);
});

it('should generate 12 length mnemonic', () => {
const mn = CasperHDKey.newMnemonic(12);

expect(mn.split(' ').length === 12);
});

it('should throw error if invalid mnemonic length is provided', () => {
expect(() => CasperHDKey.newMnemonic(10)).to.throw('Invalid word length');
});
});
Loading

0 comments on commit 08d9996

Please sign in to comment.