Skip to content

Commit

Permalink
Merge branch 'development' into v1_api
Browse files Browse the repository at this point in the history
  • Loading branch information
callebtc committed Feb 24, 2024
2 parents 91a66cb + 6008309 commit f9f56e2
Show file tree
Hide file tree
Showing 11 changed files with 181 additions and 107 deletions.
21 changes: 21 additions & 0 deletions .github/workflows/version.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
name: Publish Package to npmjs
permissions:
contents: read
id-token: write
on:
release:
types: [published]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v3
with:
node-version: 20
registry-url: 'https://registry.npmjs.org'
- run: npm i
- run: npm run compile
- run: npm publish --provenance
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
4 changes: 3 additions & 1 deletion .prettierignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
dist
node_modules
package-lock.json
package-lock.json
coverage
docs
87 changes: 44 additions & 43 deletions package-lock.json

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

7 changes: 4 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,10 @@
},
"dependencies": {
"@gandlaf21/bolt11-decode": "^3.0.6",
"@noble/curves": "^1.0.0",
"@scure/bip32": "^1.3.2",
"@scure/bip39": "^1.2.1",
"@noble/curves": "^1.3.0",
"@noble/hashes": "^1.3.3",
"@scure/bip32": "^1.3.3",
"@scure/bip39": "^1.2.2",
"buffer": "^6.0.3"
}
}
7 changes: 2 additions & 5 deletions src/CashuMint.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,7 @@ class CashuMint {
* @param _mintUrl requires mint URL to create this object
* @param _customRequest if passed, use custom request implementation for network communication with the mint
*/
constructor(
private _mintUrl: string,
private _customRequest?: typeof request
) { }
constructor(private _mintUrl: string, private _customRequest?: typeof request) { }

get mintUrl() {
return this._mintUrl;
Expand Down Expand Up @@ -189,7 +186,7 @@ class CashuMint {
});

if (!isObj(data) || !Array.isArray(data?.signatures)) {
throw new Error('bad response');
throw new Error(data.detail ?? 'bad response');
}

return data;
Expand Down
2 changes: 1 addition & 1 deletion src/CashuWallet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ class CashuWallet {
continue;
}
try {
const { proofsWithError, proofs } = await this.receiveTokenEntry(
const { proofs, proofsWithError } = await this.receiveTokenEntry(
tokenEntry,
preference,
counter
Expand Down
30 changes: 16 additions & 14 deletions src/DHKE.ts
Original file line number Diff line number Diff line change
@@ -1,35 +1,37 @@
import { ProjPointType } from '@noble/curves/abstract/weierstrass';
import { secp256k1 } from '@noble/curves/secp256k1';
import { encodeUint8toBase64 } from './base64.js';
import { MintKeys, Proof, SerializedBlindedSignature } from './model/types/index.js';
import { bytesToNumber } from './utils.js';
import { sha256 } from '@noble/hashes/sha256';
import { bytesToHex } from '@noble/curves/abstract/utils';
import { bytesToHex, hexToBytes } from '@noble/curves/abstract/utils';
import { Buffer } from 'buffer/';

const DOMAIN_SEPARATOR = hexToBytes('536563703235366b315f48617368546f43757276655f43617368755f');

function hashToCurve(secret: Uint8Array): ProjPointType<bigint> {
let point: ProjPointType<bigint> | undefined;
while (!point) {
const hash = sha256(secret);
const hashHex = bytesToHex(hash);
const pointX = '02' + hashHex;
const msgToHash = sha256(Buffer.concat([DOMAIN_SEPARATOR, secret]));
const counter = new Uint32Array(1);
const maxIterations = 2 ** 16;
for (let i = 0; i < maxIterations; i++) {
const counterBytes = new Uint8Array(counter.buffer);
const hash = sha256(Buffer.concat([msgToHash, counterBytes]));
try {
point = pointFromHex(pointX);
return pointFromHex(bytesToHex(Buffer.concat([new Uint8Array([0x02]), hash])));
} catch (error) {
secret = sha256(secret);
counter[0]++;
}
}
return point;
throw new Error('No valid point found');
}

export function pointFromHex(hex: string) {
return secp256k1.ProjectivePoint.fromHex(hex);
}
/* export function h2cToPoint(h2c: H2CPoint<bigint>): ProjPointType<bigint> {
return secp256k1.ProjectivePoint.fromAffine(h2c.toAffine());
} */
function blindMessage(secret: Uint8Array, r?: bigint): { B_: ProjPointType<bigint>; r: bigint } {
const secretMessageBase64 = encodeUint8toBase64(secret);
const secretMessage = new TextEncoder().encode(secretMessageBase64);
const Y = hashToCurve(secretMessage);
const Y = hashToCurve(secret);
if (!r) {
r = bytesToNumber(secp256k1.utils.randomPrivateKey());
}
Expand Down Expand Up @@ -60,7 +62,7 @@ function constructProofs(
const proof = {
id: p.id,
amount: p.amount,
secret: encodeUint8toBase64(secrets[i]),
secret: new TextDecoder().decode(secrets[i]),
C: C.toHex(true)
};
return proof;
Expand Down
6 changes: 3 additions & 3 deletions test/dhke.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,14 @@ describe('testing hash to curve', () => {
let secret = hexToBytes('0000000000000000000000000000000000000000000000000000000000000000');
let Y = dhke.hashToCurve(secret);
let hexY = Y.toHex(true);
expect(hexY).toBe('0266687aadf862bd776c8fc18b8e9f8e20089714856ee233b3902a591d0d5f2925');
expect(hexY).toBe('024cce997d3b518f739663b757deaec95bcd9473c30a14ac2fd04023a739d1a725');
});

test('testing string 0000....01', async () => {
let secret = hexToBytes('0000000000000000000000000000000000000000000000000000000000000001');
let Y = dhke.hashToCurve(secret);
let hexY = Y.toHex(true);
expect(hexY).toBe('02ec4916dd28fc4c10d78e287ca5d9cc51ee1ae73cbfde08c6b37324cbfaac8bc5');
expect(hexY).toBe('022e7158e11c9506f1aa4248bf531298daa7febd6194f003edcd9b93ade6253acf');
});
});

Expand Down Expand Up @@ -45,7 +45,7 @@ describe('test blinding message', () => {
r
);
expect(B_.toHex(true)).toBe(
'02a9acc1e48c25eeeb9289b5031cc57da9fe72f3fe2861d264bdc074209b107ba2'
'025cc16fe33b953e2ace39653efb3e7a7049711ae1d8a2f7a9108753f1cdea742b'
);
});
});
Expand Down
40 changes: 30 additions & 10 deletions test/secrets.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { bytesToHex } from '@noble/curves/abstract/utils';
import { deriveSeedFromMnemonic } from '../src/secrets';
import { deriveBlindingFactor, deriveSecret } from '../src/secrets';
import { blindMessage } from '../src/DHKE';
import { HDKey } from '@scure/bip32';

const mnemonic = 'half depart obvious quality work element tank gorilla view sugar picture humble';
Expand All @@ -26,18 +27,24 @@ describe('testing hdkey from seed', () => {

describe('testing deterministic secrets', () => {
const secrets = [
'9d32fc57e6fa2942d05ee475d28ba6a56839b8cb8a3f174b05ed0ed9d3a420f6',
'1c0f2c32e7438e7cc992612049e9dfcdbffd454ea460901f24cc429921437802',
'327c606b761af03cbe26fa13c4b34a6183b868c52cda059fe57fdddcb4e1e1e7',
'53476919560398b56c0fdc5dd92cf8628b1e06de6f2652b0f7d6e8ac319de3b7',
'b2f5d632229378a716be6752fc79ac8c2b43323b820859a7956f2dfe5432b7b4'
'485875df74771877439ac06339e284c3acfcd9be7abf3bc20b516faeadfe77ae',
'8f2b39e8e594a4056eb1e6dbb4b0c38ef13b1b2c751f64f810ec04ee35b77270',
'bc628c79accd2364fd31511216a0fab62afd4a18ff77a20deded7b858c9860c8',
'59284fd1650ea9fa17db2b3acf59ecd0f2d52ec3261dd4152785813ff27a33bf',
'576c23393a8b31cc8da6688d9c9a96394ec74b40fdaf1f693a6bb84284334ea0'
];
test('derive Secret', async () => {
const secret1 = deriveSecret(seed, '1cCNIAZ2X/w1', 0);
const secret2 = deriveSecret(seed, '1cCNIAZ2X/w1', 1);
const secret3 = deriveSecret(seed, '1cCNIAZ2X/w1', 2);
const secret4 = deriveSecret(seed, '1cCNIAZ2X/w1', 3);
const secret5 = deriveSecret(seed, '1cCNIAZ2X/w1', 4);
const secret1 = deriveSecret(seed, '009a1f293253e41e', 0);
const secret2 = deriveSecret(seed, '009a1f293253e41e', 1);
const secret3 = deriveSecret(seed, '009a1f293253e41e', 2);
const secret4 = deriveSecret(seed, '009a1f293253e41e', 3);
const secret5 = deriveSecret(seed, '009a1f293253e41e', 4);

const bf1 = deriveBlindingFactor(seed, '009a1f293253e41e', 0);
const bf2 = deriveBlindingFactor(seed, '009a1f293253e41e', 1);
const bf3 = deriveBlindingFactor(seed, '009a1f293253e41e', 2);
const bf4 = deriveBlindingFactor(seed, '009a1f293253e41e', 3);
const bf5 = deriveBlindingFactor(seed, '009a1f293253e41e', 4);

expect(bytesToHex(secret1)).toBe(secrets[0]);
expect(bytesToHex(secret2)).toBe(secrets[1]);
Expand All @@ -47,6 +54,19 @@ describe('testing deterministic secrets', () => {
});
});

describe('testing deterministic blindedMessage', () => {
const secrets = ['485875df74771877439ac06339e284c3acfcd9be7abf3bc20b516faeadfe77ae'];
test('derive Secret', async () => {
const secret1 = deriveSecret(seed, '009a1f293253e41e', 0);

const bf1 = deriveBlindingFactor(seed, '009a1f293253e41e', 0);

expect(bytesToHex(secret1)).toBe(secrets[0]);

// blindMessage()
});
});

describe('test private key derivation from derivation path', () => {
const seed =
'dd44ee516b0647e80b488e8dcc56d736a148f15276bef588b37057476d4b2b25780d3688a32b37353d6995997842c0fd8b412475c891c16310471fbc86dcbda8';
Expand Down
Loading

0 comments on commit f9f56e2

Please sign in to comment.