Skip to content

Commit

Permalink
refactor: create crypto pkg (#816)
Browse files Browse the repository at this point in the history
  • Loading branch information
dhrubabasu authored Feb 20, 2024
1 parent 4e618f6 commit 0e81005
Show file tree
Hide file tree
Showing 14 changed files with 51 additions and 55 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,15 +59,15 @@ import { avm, pvm, evm } from '@avalabs/avalanchejs';
## Importing Essentials

```ts
import { avm /** X-chain */, pvm /** P-chain */, evm /** C-chain */, utils } from "@avalabs/avalanchejs"
import { avm /** X-chain */, pvm /** P-chain */, evm /** C-chain */, utils, secp256k1 } from "@avalabs/avalanchejs"

// example calls
const exportTx = avm.newExportTx(...) // constructs a new export tx from X
const addValidatorTx = pvm.newAddPermissionlessValidatorTx(...) // constructs a new add validator tx on P
const importTx = evm.newImportTx(...) // constructs a new import tx to C

const publicKeyBytes = utils.hexToBuffer(publicKeyHex)
const signature = utils.signHash(bytes, privateKeyBytes)
const signature = secp256k1.signHash(bytes, privateKeyBytes)
```

Please check out the `examples` folder for more info.
1 change: 1 addition & 0 deletions src/crypto/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * as secp256k1 from './secp256k1';
28 changes: 16 additions & 12 deletions src/utils/secp256k1.spec.ts → src/crypto/secp256k1.spec.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
import { sha256 } from '@noble/hashes/sha256';
import { base58check } from './base58';
import { bufferToHex, hexToBuffer } from './buffer';
import * as secp from './secp256k1';
import { base58check } from '../utils/base58';
import { bufferToHex, hexToBuffer } from '../utils/buffer';
import * as secp256k1 from './secp256k1';

describe('secp256k1', function () {
it('works correctly', async () => {
const key = '24jUJ9vZexUM6expyMcT48LBx27k1m7xpraoV62oSQAHdziao5';
const privKey = base58check.decode(key);
const pubKey = secp.getPublicKey(privKey);
const pubKey = secp256k1.getPublicKey(privKey);

expect(base58check.encode(secp.publicKeyBytesToAddress(pubKey))).toEqual(
'Q4MzFZZDPHRPAHFeDs3NiyyaZDvxHKivf',
);
expect(
base58check.encode(secp256k1.publicKeyBytesToAddress(pubKey)),
).toEqual('Q4MzFZZDPHRPAHFeDs3NiyyaZDvxHKivf');

const tests = [
{
Expand Down Expand Up @@ -52,10 +52,14 @@ describe('secp256k1', function () {
for (const test of tests) {
const hash = sha256(test.msg);

await expect(secp.sign(test.msg, privKey)).resolves.toEqual(test.sig);
await expect(secp.signHash(hash, privKey)).resolves.toEqual(test.sig);
expect(secp.recoverPublicKey(hash, test.sig)).toEqual(pubKey);
expect(secp.verify(test.sig, hash, pubKey)).toEqual(true);
await expect(secp256k1.sign(test.msg, privKey)).resolves.toEqual(
test.sig,
);
await expect(secp256k1.signHash(hash, privKey)).resolves.toEqual(
test.sig,
);
expect(secp256k1.recoverPublicKey(hash, test.sig)).toEqual(pubKey);
expect(secp256k1.verify(test.sig, hash, pubKey)).toEqual(true);
}
});

Expand All @@ -64,7 +68,7 @@ describe('secp256k1', function () {
'04e68acfc0253a10620dff706b0a1b1f1f5833ea3beb3bde2250d5f271f3563606672ebc45e0b7ea2e816ecb70ca03137b1c9476eec63d4632e990020b7b6fba39',
);

const ethAddrKey = bufferToHex(secp.publicKeyToEthAddress(publicKey));
const ethAddrKey = bufferToHex(secp256k1.publicKeyToEthAddress(publicKey));
expect(ethAddrKey).toBe(
'0x90F8bf6A479f320ead074411a4B0e7944Ea8c9C1'.toLocaleLowerCase(),
);
Expand Down
2 changes: 1 addition & 1 deletion src/utils/secp256k1.ts → src/crypto/secp256k1.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { ripemd160 } from '@noble/hashes/ripemd160';
import { sha256 } from '@noble/hashes/sha256';
import * as secp from '@noble/secp256k1';
import { Address } from 'micro-eth-signer';
import { concatBytes, hexToBuffer } from './buffer';
import { concatBytes, hexToBuffer } from '../utils/buffer';

export function randomPrivateKey() {
return secp.utils.randomPrivateKey();
Expand Down
20 changes: 8 additions & 12 deletions src/fixtures/vms.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,16 @@
import {
getPublicKey,
hexToBuffer,
publicKeyBytesToAddress,
publicKeyToEthAddress,
} from '../utils';
import { secp256k1 } from '../crypto';
import { hexToBuffer } from '../utils';

export const testPrivateKey1 = hexToBuffer(
'9c0523e7611e62f5dca291ad335e950db076c5ee31c4107355abde0d357bbd29',
);
export const testPublicKey1 = getPublicKey(testPrivateKey1);
export const testAddress1 = publicKeyBytesToAddress(testPublicKey1);
export const testEthAddress1 = publicKeyToEthAddress(testPublicKey1);
export const testPublicKey1 = secp256k1.getPublicKey(testPrivateKey1);
export const testAddress1 = secp256k1.publicKeyBytesToAddress(testPublicKey1);
export const testEthAddress1 = secp256k1.publicKeyToEthAddress(testPublicKey1);

export const testPrivateKey2 = hexToBuffer(
'd11e7aa633eb15682bc2456d399c2a9861c82e0a308dbfd4d3a51ffa972f2b62',
);
export const testPublicKey2 = getPublicKey(testPrivateKey2);
export const testAddress2 = publicKeyBytesToAddress(testPublicKey2);
export const testEthAddress2 = publicKeyToEthAddress(testPublicKey2);
export const testPublicKey2 = secp256k1.getPublicKey(testPrivateKey2);
export const testAddress2 = secp256k1.publicKeyBytesToAddress(testPublicKey2);
export const testEthAddress2 = secp256k1.publicKeyToEthAddress(testPublicKey2);
2 changes: 1 addition & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ export * as networkIDs from './constants/networkIDs';
export * from './serializable';
export { Utxo } from './serializable/avax/utxo';
export * from './signer';
export * from './utils';
export * as utils from './utils';
export * from './vms';
export { Info } from './info/info';
export * from './crypto';
5 changes: 3 additions & 2 deletions src/signer/addTxSignatures.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { id } from '../fixtures/common';
import { BaseTx } from '../serializable/avm';
import { transferableOutput, utxoId } from '../fixtures/avax';
import { Input, TransferInput } from '../serializable/fxs/secp256k1';
import { AddressMaps, AddressMap, getPublicKey, hexToBuffer } from '../utils';
import { AddressMaps, AddressMap, hexToBuffer } from '../utils';
import { Address } from '../serializable/fxs/common';
import {
testAddress1,
Expand All @@ -18,6 +18,7 @@ import {
testPublicKey2,
} from '../fixtures/vms';
import { addTxSignatures } from './addTxSignatures';
import { secp256k1 } from '../crypto';

describe('addTxSignatures', () => {
beforeEach(() => {
Expand All @@ -30,7 +31,7 @@ describe('addTxSignatures', () => {
const unknownPrivateKey = hexToBuffer(
'1d4ff8f6582d995354f5c03a28a043d22aa1bb6aa15879a632134aaf1f225cf4',
);
const unknownPublicKey = getPublicKey(unknownPrivateKey);
const unknownPublicKey = secp256k1.getPublicKey(unknownPrivateKey);

const unsignedTx = new UnsignedTx(
new BaseTx(
Expand Down
6 changes: 3 additions & 3 deletions src/signer/addTxSignatures.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { UnsignedTx } from '../vms/common/unsignedTx';
import { getPublicKey, sign } from '../utils';
import { secp256k1 } from '../crypto';

export const addTxSignatures = async ({
unsignedTx,
Expand All @@ -12,10 +12,10 @@ export const addTxSignatures = async ({

await Promise.all(
privateKeys.map(async (privateKey) => {
const publicKey = getPublicKey(privateKey);
const publicKey = secp256k1.getPublicKey(privateKey);

if (unsignedTx.hasPubkey(publicKey)) {
const signature = await sign(unsignedBytes, privateKey);
const signature = await secp256k1.sign(unsignedBytes, privateKey);
unsignedTx.addSignature(signature);
}
}),
Expand Down
6 changes: 3 additions & 3 deletions src/utils/address.spec.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import { base58check } from './base58';
import * as secp from './secp256k1';
import { secp256k1 } from '../crypto';
import * as address from './address';

describe('address', () => {
it('parses and formats correctly', async () => {
const key = '24jUJ9vZexUM6expyMcT48LBx27k1m7xpraoV62oSQAHdziao5';
const privKey = base58check.decode(key);
const pubKey = secp.getPublicKey(privKey);
const pubKey = secp256k1.getPublicKey(privKey);

const addrBytes = secp.publicKeyBytesToAddress(pubKey);
const addrBytes = secp256k1.publicKeyBytesToAddress(pubKey);

const addr = address.format('X', 'avax', addrBytes);
expect(addr).toEqual('X-avax1lnk637g0edwnqc2tn8tel39652fswa3xmgyghf');
Expand Down
1 change: 0 additions & 1 deletion src/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ export * from './buffer';
export * from './bytesCompare';
export * from './costs';
export * from './devutils';
export * from './secp256k1';
export * from './typeGuards';
export * from './UTXOSet';
export * from './addChecksum';
Expand Down
4 changes: 2 additions & 2 deletions src/vms/common/evmUnsignedTx.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { signature } from '../../fixtures/secp256k1';
import { exportTx } from '../../fixtures/evm';
import { testEthAddress1, testPrivateKey1 } from '../../fixtures/vms';
import { Address } from '../../serializable/fxs/common';
import { sign } from '../../utils';
import { secp256k1 } from '../../crypto';
import { AddressMap, AddressMaps } from '../../utils/addressMap';
import { EVMUnsignedTx } from './evmUnsignedTx';

Expand All @@ -22,7 +22,7 @@ describe('EVMUnsignedTx', () => {

expect(unsignedTx.hasAllSignatures()).toBeFalsy();

const sig = await sign(unsignedBytes, testPrivateKey1);
const sig = await secp256k1.sign(unsignedBytes, testPrivateKey1);
unsignedTx.addSignature(sig);

expect(unsignedTx.hasAllSignatures()).toBeTruthy();
Expand Down
4 changes: 2 additions & 2 deletions src/vms/common/evmUnsignedTx.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { publicKeyToEthAddress } from '../../utils';
import { secp256k1 } from '../../crypto';
import { UnsignedTx } from './unsignedTx';
import { Address } from '../../serializable/fxs/common';

export class EVMUnsignedTx extends UnsignedTx {
hasPubkey(pubKey: Uint8Array): boolean {
const addrAvax = new Address(this.publicKeyBytesToAddress(pubKey));
const addrEVM = new Address(publicKeyToEthAddress(pubKey));
const addrEVM = new Address(secp256k1.publicKeyToEthAddress(pubKey));

return this.hasAddress(addrAvax) || this.hasAddress(addrEVM);
}
Expand Down
6 changes: 3 additions & 3 deletions src/vms/common/unsignedTx.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import { Utxo } from '../../serializable/avax/utxo';
import { ExportTx } from '../../serializable/avm';
import { Address } from '../../serializable/fxs/common';
import { Input, TransferInput } from '../../serializable/fxs/secp256k1';
import { sign } from '../../utils';
import { secp256k1 } from '../../crypto';
import { AddressMap, AddressMaps } from '../../utils/addressMap';
import { UnsignedTx } from './unsignedTx';

Expand Down Expand Up @@ -64,11 +64,11 @@ describe('UnsignedTx', () => {

expect(unsignedTx.hasAllSignatures()).toBeFalsy();

const sig = await sign(unsignedBytes, testPrivateKey1);
const sig = await secp256k1.sign(unsignedBytes, testPrivateKey1);
unsignedTx.addSignature(sig);
expect(unsignedTx.hasAllSignatures()).toBeFalsy();

const sig2 = await sign(unsignedBytes, testPrivateKey2);
const sig2 = await secp256k1.sign(unsignedBytes, testPrivateKey2);
unsignedTx.addSignature(sig2);

expect(unsignedTx.hasAllSignatures()).toBeTruthy();
Expand Down
17 changes: 6 additions & 11 deletions src/vms/common/unsignedTx.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,8 @@ import type { VM } from '../../serializable/constants';
import { ValidVMs } from '../../serializable/constants';
import { Address } from '../../serializable/fxs/common';
import { Credential } from '../../serializable/fxs/secp256k1';
import {
bufferToHex,
hexToBuffer,
publicKeyBytesToAddress,
publicKeyToEthAddress,
recoverPublicKey,
} from '../../utils';
import { bufferToHex, hexToBuffer } from '../../utils';
import { secp256k1 } from '../../crypto';
import { AddressMaps } from '../../utils/addressMap';
import { getManagerForVM, packTx } from '../../utils/packTx';
import type { Transaction } from './transaction';
Expand Down Expand Up @@ -130,7 +125,7 @@ export class UnsignedTx {

getSigIndicesForPubKey(pubkey: Uint8Array) {
const addrAvax = this.publicKeyBytesToAddress(pubkey);
const addrEvm = publicKeyToEthAddress(pubkey);
const addrEvm = secp256k1.publicKeyToEthAddress(pubkey);

// Check against both addresses
const coordinatesAvax = this.getSigIndicesForAddress(new Address(addrAvax));
Expand Down Expand Up @@ -172,7 +167,7 @@ export class UnsignedTx {

addSignature(sig: Uint8Array) {
const unsignedHash = sha256(this.toBytes());
const publicKey = recoverPublicKey(unsignedHash, sig);
const publicKey = secp256k1.recoverPublicKey(unsignedHash, sig);
this.addSignatureForPubKey(sig, publicKey);
}

Expand All @@ -186,7 +181,7 @@ export class UnsignedTx {
}

protected publicKeyBytesToAddress(pubKey: Uint8Array) {
return publicKeyBytesToAddress(pubKey);
return secp256k1.publicKeyBytesToAddress(pubKey);
}

hasAllSignatures() {
Expand All @@ -210,7 +205,7 @@ export class UnsignedTx {
throw new Error('error: incorrect structure for credentials');
}
const sigBytes = hexToBuffer(sig);
const publicKey = recoverPublicKey(unsignedHash, sigBytes);
const publicKey = secp256k1.recoverPublicKey(unsignedHash, sigBytes);
if (!this.hasPubkey(publicKey)) {
valid = false;
}
Expand Down

0 comments on commit 0e81005

Please sign in to comment.