Skip to content

Commit

Permalink
add nonce
Browse files Browse the repository at this point in the history
  • Loading branch information
vlopes11 committed Oct 12, 2023
1 parent 1c1a972 commit d2ccd7b
Show file tree
Hide file tree
Showing 8 changed files with 60 additions and 13 deletions.
24 changes: 23 additions & 1 deletion packages/site/src/components/Sovereign.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ type SovereignState = {
curve: CurveSelectorState;
keyId: number;
message?: string;
nonce?: number;
request?: string;
response?: string;
};
Expand All @@ -27,6 +28,7 @@ export const Sovereign = () => {
curve: `secp256k1`,
keyId: 0,
message: 'Some signature message...',
nonce: 0,
};
const [state, setState] = useState(initialState);

Expand Down Expand Up @@ -97,10 +99,29 @@ export const Sovereign = () => {
cols={40}
/>
</div>
<div>Nonce:</div>
<div>
<input
type="number"
value={state.nonce}
onChange={(ev) => {
const { value } = ev.target;

// Allow only positive integers (whole numbers greater than or equal to zero)
const regex = /^[0-9\b]+$/u; // Allows digits only
if (value === '' || regex.test(value)) {
setState({
...state,
nonce: parseInt(value, 10),
});
}
}}
/>
</div>
<div>
<ExecuteButton
onClick={async () => {
const { method, curve, keyId, message } = state;
const { method, curve, keyId, message, nonce } = state;

const path = ['m', "44'", "1551'"];
path.push(keyId.toString());
Expand All @@ -114,6 +135,7 @@ export const Sovereign = () => {
transaction: {
message: message || '',
},
nonce,
};
} else {
params = {
Expand Down
4 changes: 3 additions & 1 deletion packages/snap/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ Will emit a confirmation dialog for the user.
- `curve`: The curve of the public key (`secp256k1` or `ed25519`).
- `schema`: A [borsh](https://www.npmjs.com/package/borsh) schema for the transaction.
- `transaction`: A transaction to be serialized using the provided schema. The signature will be performed over the serialized transaction.
- `nonce`: An unsigned 64-bits number to be appended to the serialized transaction.

##### Example

Expand Down Expand Up @@ -90,12 +91,13 @@ const response = request({
amount: 1582,
},
},
nonce: 0,
},
});

if (
!response ===
'0xfd2e4b23a3e3f498664af355b341e833324276270a13f9647dd1f043248f92fccaa037d4cfc9d23f13a295f7d505ee13afb2b10cea548890678f9002947cbb0a'
'0xe563b3d772572e57bff43e31e449dbc8e98f7580fea10b2ad1ad8278b3edcf5ff5b3a24b85cef3192fcd70452c58e7c968e500da9e290aefadf5ef22a4efbf0d',
) {
throw new Error('Invalid signature');
}
Expand Down
3 changes: 2 additions & 1 deletion packages/snap/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@
"@noble/ed25519": "^1.6.0",
"@noble/secp256k1": "^1.7.1",
"borsh": "^1.0.0",
"buffer": "^6.0.3"
"buffer": "^6.0.3",
"int64-buffer": "^1.0.1"
},
"devDependencies": {
"@jest/globals": "^29.5.0",
Expand Down
2 changes: 1 addition & 1 deletion packages/snap/snap.manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"url": "https://github.com/Sovereign-Labs/sov-snap.git"
},
"source": {
"shasum": "WZco6V2pvJMpitcOysOcWYoVpGTBAn7cSdHRGM6MRu0=",
"shasum": "wOP1ZGD2ciBIysiXTThBibt0cTkaxNKbsFCLXk+Si/c=",
"location": {
"npm": {
"filePath": "dist/bundle.js",
Expand Down
4 changes: 3 additions & 1 deletion packages/snap/src/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ describe('onRpcRequest', () => {
payload: Array(176).fill(5),
},
},
nonce: 26,
},
});

Expand Down Expand Up @@ -114,6 +115,7 @@ describe('onRpcRequest', () => {
amount: 1582,
},
},
nonce: 0,
},
});

Expand All @@ -122,7 +124,7 @@ describe('onRpcRequest', () => {
await ui.ok();

expect(await response).toRespondWith(
'0xfd2e4b23a3e3f498664af355b341e833324276270a13f9647dd1f043248f92fccaa037d4cfc9d23f13a295f7d505ee13afb2b10cea548890678f9002947cbb0a',
'0xe563b3d772572e57bff43e31e449dbc8e98f7580fea10b2ad1ad8278b3edcf5ff5b3a24b85cef3192fcd70452c58e7c968e500da9e290aefadf5ef22a4efbf0d',
);

await close();
Expand Down
23 changes: 15 additions & 8 deletions packages/snap/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { add0x, assert, bytesToHex, remove0x } from '@metamask/utils';
import { sign as signEd25519 } from '@noble/ed25519';
import { sign as signSecp256k1 } from '@noble/secp256k1';
import { serialize } from 'borsh';
import { Uint64LE } from 'int64-buffer';

import type { GetBip32PublicKeyParams, SignTransactionParams } from './types';

Expand All @@ -28,9 +29,11 @@ export const onRpcRequest: OnRpcRequestHandler = async ({ request }) => {
});

case 'signTransaction': {
const { schema, transaction, curve, ...params } =
const { schema, transaction, nonce, curve, ...params } =
request.params as SignTransactionParams;

const nonceLe = new Uint64LE(nonce);
const nonceBytes = nonceLe.toBuffer();
const serializedTransaction = serialize(schema, transaction);

const json = await snap.request({
Expand Down Expand Up @@ -58,11 +61,11 @@ export const onRpcRequest: OnRpcRequestHandler = async ({ request }) => {
type: DialogType.Confirmation,
content: panel([
heading('Signature request'),
text(
`Do you want to ${curve} sign ${JSON.stringify(
transaction,
)} with the following public key?`,
),
text(`Do you want to ${curve} sign`),
copyable(JSON.stringify(transaction)),
text(`with nonce`),
copyable(String(nonce)),
text(`and the following public key?`),
copyable(add0x(node.publicKey)),
]),
},
Expand All @@ -73,14 +76,18 @@ export const onRpcRequest: OnRpcRequestHandler = async ({ request }) => {
}

const privateKey = remove0x(node.privateKey);
const signedTransaction = new Uint8Array([
...serializedTransaction,
...nonceBytes,
]);

let signed;
switch (curve) {
case 'ed25519':
signed = await signEd25519(serializedTransaction, privateKey);
signed = await signEd25519(signedTransaction, privateKey);
break;
case 'secp256k1':
signed = await signSecp256k1(serializedTransaction, privateKey);
signed = await signSecp256k1(signedTransaction, privateKey);
break;
default:
throw new Error(`Unsupported curve: ${String(curve)}.`);
Expand Down
5 changes: 5 additions & 0 deletions packages/snap/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,11 @@ export type SignTransactionParams = {
*/
transaction: any;

/**
* The nonce of the transaction.
*/
nonce: number;

/**
* The BIP-32 path to the account.
*/
Expand Down
8 changes: 8 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -14277,6 +14277,13 @@ __metadata:
languageName: node
linkType: hard

"int64-buffer@npm:^1.0.1":
version: 1.0.1
resolution: "int64-buffer@npm:1.0.1"
checksum: 9962be285f4a0d6bd8f6fba3cffcfd80b15848af370bd9ec6cb2d9c8a8adf83b230cdf66b694f87c992c1a33724385b28ba7cac61602a7fcf9b9c8691015c7e2
languageName: node
linkType: hard

"internal-slot@npm:^1.0.3":
version: 1.0.3
resolution: "internal-slot@npm:1.0.3"
Expand Down Expand Up @@ -20888,6 +20895,7 @@ __metadata:
eslint-plugin-jsdoc: ^39.2.9
eslint-plugin-node: ^11.1.0
eslint-plugin-prettier: ^4.2.1
int64-buffer: ^1.0.1
jest: ^29.5.0
prettier: ^2.2.1
prettier-plugin-packagejson: ^2.2.11
Expand Down

0 comments on commit d2ccd7b

Please sign in to comment.