Skip to content

Commit

Permalink
Merge branch 'rc/salamander' into db/feat/improve-decode-validation
Browse files Browse the repository at this point in the history
  • Loading branch information
danielbate authored Jan 5, 2024
2 parents 23ccf9a + ad7ee46 commit 110c161
Show file tree
Hide file tree
Showing 13 changed files with 118 additions and 68 deletions.
5 changes: 5 additions & 0 deletions .changeset/long-ways-rule.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@fuel-ts/providers": patch
---

bugfix when amount of requested resources to spend is less than 1
5 changes: 5 additions & 0 deletions .changeset/pretty-goats-matter.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"fuels": minor
---

built new js file specifically for cdnjs integration
6 changes: 6 additions & 0 deletions .changeset/warm-poems-swim.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@fuel-ts/signer": minor
---

- Stopped exporting `getCurve()` / secp256k1
- Replaced `elliptic` with `@noble/curves`
5 changes: 3 additions & 2 deletions packages/fuels/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
"dist"
],
"scripts": {
"build": "tsup",
"build": "tsup && pnpm vite build",
"postbuild": "tsc --emitDeclarationOnly -p tsconfig.dts.json",
"prepublishOnly": "cp ../../README.md ./README.md"
},
Expand Down Expand Up @@ -85,7 +85,8 @@
},
"devDependencies": {
"@types/lodash.camelcase": "^4.3.7",
"@types/rimraf": "^3.0.2"
"@types/rimraf": "^3.0.2",
"vite": "^4.3.9"
},
"keywords": [
"ethereum",
Expand Down
18 changes: 18 additions & 0 deletions packages/fuels/vite.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { defineConfig } from 'vite';

export default defineConfig({
build: {
minify: true,
sourcemap: true,
emptyOutDir: false,
lib: {
entry: './src/index.ts',
name: 'browser',
formats: ['es'],
fileName: 'browser',
},
},
define: {
'process.env.NODE_ENV': JSON.stringify('production'),
},
});
3 changes: 2 additions & 1 deletion packages/providers/src/coin-quantity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,10 @@ export const coinQuantityfy = (coinQuantityLike: CoinQuantityLike): CoinQuantity
max = coinQuantityLike.max ?? undefined;
}

const bnAmount = bn(amount);
return {
assetId: hexlify(assetId),
amount: bn(amount),
amount: bnAmount.toNumber() < 1 ? bn(1) : bnAmount,
max: max ? bn(max) : undefined,
};
};
Expand Down
12 changes: 12 additions & 0 deletions packages/providers/src/coin-quantityfy.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { coinQuantityfy } from './coin-quantity';

/**
* @group node
*/
describe('coinQuantityfy', () => {
it('should returns 1 when input is < 1', () => {
expect(coinQuantityfy([0]).amount.toNumber()).toEqual(1);
expect(coinQuantityfy([0.9]).amount.toNumber()).toEqual(1);
expect(coinQuantityfy([2]).amount.toNumber()).toEqual(2);
});
});
7 changes: 2 additions & 5 deletions packages/signer/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,7 @@
"@fuel-ts/crypto": "workspace:*",
"@fuel-ts/hasher": "workspace:*",
"@fuel-ts/math": "workspace:*",
"elliptic": "^6.5.4",
"ethers": "^6.7.1"
},
"devDependencies": {
"@types/elliptic": "^6.4.14"
"ethers": "^6.7.1",
"@noble/curves": "^1.3.0"
}
}
1 change: 0 additions & 1 deletion packages/signer/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
export { default as Signer } from './signer';
export * from './signer';
2 changes: 1 addition & 1 deletion packages/signer/src/signer.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { getBytesCopy, sha256 } from 'ethers';

import Signer from './signer';
import { Signer } from './signer';

/**
* @group node
Expand Down
67 changes: 24 additions & 43 deletions packages/signer/src/signer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,11 @@ import { Address } from '@fuel-ts/address';
import { randomBytes } from '@fuel-ts/crypto';
import { hash } from '@fuel-ts/hasher';
import { toBytes } from '@fuel-ts/math';
import * as elliptic from 'elliptic';
import { hexlify, concat, getBytesCopy } from 'ethers';
import { secp256k1 } from '@noble/curves/secp256k1';
import type { BytesLike } from 'ethers';
import { hexlify, concat, getBytesCopy } from 'ethers';

/* Importing `ec` like this to avoid the 'Requested module is a CommonJS module,
* which may not support all module.exports as named exports' error
* @see https://github.com/FuelLabs/fuels-ts/issues/841
*/
const { ec: EC } = elliptic;

/**
* Return elliptic instance with curve secp256k1
*/
export function getCurve() {
return new EC('secp256k1');
}

class Signer {
export class Signer {
readonly address: Address;

readonly publicKey: string;
Expand All @@ -42,16 +29,15 @@ class Signer {
privateKey = `0x${privateKey}`;
}
}

// Convert to byte array, normalize private key input allowing it to be BytesLike
// like remove 0x prefix and accept array of bytes
const privateKeyBytes = getBytesCopy(privateKey);
const keyPair = getCurve().keyFromPrivate(privateKeyBytes, 'hex');
const privateKeyBytes = toBytes(privateKey, 32);

// Slice(1) removes the encoding scheme from the public key
this.compressedPublicKey = hexlify(Uint8Array.from(keyPair.getPublic(true, 'array')));
this.publicKey = hexlify(Uint8Array.from(keyPair.getPublic(false, 'array').slice(1)));
this.privateKey = hexlify(privateKeyBytes);

// Slice(1) removes the encoding scheme from the public key
this.publicKey = hexlify(secp256k1.getPublicKey(privateKeyBytes, false).slice(1));
this.compressedPublicKey = hexlify(secp256k1.getPublicKey(privateKeyBytes, true));
this.address = Address.fromPublicKey(this.publicKey);
}

Expand All @@ -64,15 +50,13 @@ class Signer {
* @returns hashed signature
*/
sign(data: BytesLike) {
const keyPair = getCurve().keyFromPrivate(getBytesCopy(this.privateKey), 'hex');
const signature = keyPair.sign(getBytesCopy(data), {
canonical: true,
});
const r = toBytes(signature.r, 32);
const s = toBytes(signature.s, 32);
const signature = secp256k1.sign(getBytesCopy(data), getBytesCopy(this.privateKey));

const r = toBytes(`0x${signature.r.toString(16)}`, 32);
const s = toBytes(`0x${signature.s.toString(16)}`, 32);

// add recoveryParam to first s byte
s[0] |= (signature.recoveryParam || 0) << 7;
s[0] |= (signature.recovery || 0) << 7;

return concat([r, s]);
}
Expand All @@ -84,11 +68,10 @@ class Signer {
* @returns compressed point on the curve
*/
addPoint(point: BytesLike) {
const p0 = getCurve().keyFromPublic(getBytesCopy(this.compressedPublicKey));
const p1 = getCurve().keyFromPublic(getBytesCopy(point));
const result = p0.getPublic().add(p1.getPublic());

return hexlify(Uint8Array.from(result.encode('array', true)));
const p0 = secp256k1.ProjectivePoint.fromHex(getBytesCopy(this.compressedPublicKey));
const p1 = secp256k1.ProjectivePoint.fromHex(getBytesCopy(point));
const result = p0.add(p1);
return `0x${result.toHex(true)}`;
}

/**
Expand All @@ -107,12 +90,12 @@ class Signer {
// remove recoveryParam from s first byte
s[0] &= 0x7f;

const publicKey = getCurve()
.recoverPubKey(getBytesCopy(data), { r, s }, recoveryParam)
.encode('array', false)
.slice(1);
const sig = new secp256k1.Signature(BigInt(hexlify(r)), BigInt(hexlify(s))).addRecoveryBit(
recoveryParam
);

return hexlify(Uint8Array.from(publicKey));
const publicKey = sig.recoverPublicKey(getBytesCopy(data)).toRawBytes(false).slice(1);
return hexlify(publicKey);
}

/**
Expand Down Expand Up @@ -143,9 +126,7 @@ class Signer {
* @returns extended publicKey
*/
static extendPublicKey(publicKey: BytesLike) {
const keyPair = getCurve().keyFromPublic(getBytesCopy(publicKey));
return hexlify(Uint8Array.from(keyPair.getPublic(false, 'array').slice(1)));
const point = secp256k1.ProjectivePoint.fromHex(getBytesCopy(publicKey));
return hexlify(point.toRawBytes(false).slice(1));
}
}

export default Signer;
14 changes: 14 additions & 0 deletions packages/wallet/src/account.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,20 @@ describe('Account', () => {
// #endregion Message-getResourcesToSpend
});

it('getResourcesToSpend should work with <1 amount', async () => {
const account = new Account(
'0x09c0b2d1a486c439a87bcba6b46a7a1a23f3897cc83a94521a96da5c23bc58db',
provider
);
const resourcesToSpend = await account.getResourcesToSpend([
{
amount: 0.9,
assetId: '0x0101010101010101010101010101010101010101010101010101010101010101',
},
]);
expect(resourcesToSpend[0].amount.gte(1)).toBeTruthy();
});

it('should get messages just fine', async () => {
const account = new Account(
'0x69a2b736b60159b43bb8a4f98c0589f6da5fa3a3d101e8e269c499eb942753ba',
Expand Down
41 changes: 26 additions & 15 deletions pnpm-lock.yaml

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

0 comments on commit 110c161

Please sign in to comment.