Skip to content
This repository has been archived by the owner on Nov 5, 2023. It is now read-only.

Commit

Permalink
Merge pull request #37 from jzaki/revert-36-bw-35-update-signer-for-t…
Browse files Browse the repository at this point in the history
…x-sets

Revert "Update signer for tx sets"
  • Loading branch information
voltrevo authored Nov 5, 2021
2 parents ca2f3bc + d74d019 commit 18569c4
Show file tree
Hide file tree
Showing 10 changed files with 98 additions and 101 deletions.
2 changes: 1 addition & 1 deletion signer/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "bls-wallet-signer",
"version": "0.7.0",
"version": "0.6.1",
"description": "Client-side tool for signing bls transaction data",
"main": "dist/src/index.js",
"types": "dist/src/index.d.ts",
Expand Down
16 changes: 12 additions & 4 deletions signer/src/aggregate.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,21 @@
import * as hubbleBls from "../deps/hubble-bls";

import { Transaction } from "./types";
import { AggregateTransactionData, TransactionData } from "./types";

export default (txs: Transaction[]): Transaction => {
export default (txs: TransactionData[]): AggregateTransactionData => {
const sigsG1 = txs.map(tx => hubbleBls.mcl.loadG1(tx.signature));
const aggSigG1 = hubbleBls.signer.aggregate(sigsG1);

const aggregateSignature = hubbleBls.mcl.dumpG1(aggSigG1);

return {
subTransactions: txs.map(txSet => txSet.subTransactions).flat(),
signature: hubbleBls.mcl.dumpG1(aggSigG1),
transactions: txs.map(tx => ({
publicKey: tx.publicKey,
nonce: tx.nonce,
ethValue: tx.ethValue,
contractAddress: tx.contractAddress,
encodedFunction: tx.encodedFunction,
})),
signature: aggregateSignature,
};
}
12 changes: 6 additions & 6 deletions signer/src/encodeMessageForSigning.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
import { keccak256 } from "@ethersproject/keccak256";
import { pack as solidityPack } from "@ethersproject/solidity";
import { TransactionTemplate } from "./types";
import { RawTransactionData } from "./types";

export default (
chainId: number,
) => (
txTemplate: TransactionTemplate,
rawTxData: RawTransactionData,
): string => {
return solidityPack(
["uint256", "uint256", "uint256", "address", "bytes32"],
[
chainId,
txTemplate.nonce,
txTemplate.ethValue,
txTemplate.contractAddress,
keccak256(txTemplate.encodedFunction),
rawTxData.nonce,
rawTxData.ethValue,
rawTxData.contractAddress,
keccak256(rawTxData.encodedFunction),
]
);
}
2 changes: 2 additions & 0 deletions signer/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import getPublicKeyHash from "./getPublicKeyHash";
import AsyncReturnType from "./helpers/AsyncReturnType";
import sign from "./sign";
import verify from "./verify";
import verifyAggregate from "./verifyAggregate";

export * from "./types";

Expand All @@ -33,5 +34,6 @@ export async function initBlsWalletSigner({
getPublicKeyHash: getPublicKeyHash(signerFactory, domain),
sign: sign(signerFactory, domain, chainId),
verify: verify(domain, chainId),
verifyAggregate: verifyAggregate(domain, chainId),
};
}
16 changes: 6 additions & 10 deletions signer/src/sign.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,28 +2,24 @@ import * as hubbleBls from "../deps/hubble-bls";

import encodeMessageForSigning from "./encodeMessageForSigning";
import getPublicKey from "./getPublicKey";
import { Transaction, TransactionTemplate } from "./types";
import { RawTransactionData, TransactionData } from "./types";

export default (
signerFactory: hubbleBls.signer.BlsSignerFactory,
domain: Uint8Array,
chainId: number,
) => (
txTemplate: TransactionTemplate,
rawTransactionData: RawTransactionData,
privateKey: string,
): Transaction => {
const message = encodeMessageForSigning(chainId)(txTemplate);
): TransactionData => {
const message = encodeMessageForSigning(chainId)(rawTransactionData);
const signer = signerFactory.getSigner(domain, privateKey);

const signature = hubbleBls.mcl.dumpG1(signer.sign(message));

return {
subTransactions: [
{
...txTemplate,
publicKey: getPublicKey(signerFactory, domain)(privateKey),
}
],
...rawTransactionData,
publicKey: getPublicKey(signerFactory, domain)(privateKey),
signature,
}
};
19 changes: 14 additions & 5 deletions signer/src/types.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,24 @@
import { BigNumber } from "@ethersproject/bignumber";

export type TransactionTemplate = {
export type RawTransactionData = {
nonce: BigNumber;
ethValue: BigNumber;
contractAddress: string;
encodedFunction: string;
};

export type SubTransaction = TransactionTemplate & { publicKey: string };

export type Transaction = {
subTransactions: SubTransaction[];
export type TransactionData = RawTransactionData & {
publicKey: string;
signature: string;
};

export type AggregateTransactionData = {
transactions: {
publicKey: string;
nonce: BigNumber;
ethValue: BigNumber;
contractAddress: string;
encodedFunction: string;
}[],
signature: string,
};
18 changes: 8 additions & 10 deletions signer/src/verify.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,19 @@
import * as hubbleBls from "../deps/hubble-bls";

import encodeMessageForSigning from "./encodeMessageForSigning";
import { Transaction } from "./types";
import { TransactionData } from "./types";

export default (
domain: Uint8Array,
chainId: number,
) => (tx: Transaction): boolean => {
) => (
txData: TransactionData,
): boolean => {
const verifier = new hubbleBls.signer.BlsVerifier(domain);

return verifier.verifyMultiple(
hubbleBls.mcl.loadG1(tx.signature),
tx.subTransactions.map(
subTx => hubbleBls.mcl.loadG2(subTx.publicKey),
),
tx.subTransactions.map(
subTx => encodeMessageForSigning(chainId)(subTx),
),
return verifier.verify(
hubbleBls.mcl.loadG1(txData.signature),
hubbleBls.mcl.loadG2(txData.publicKey),
encodeMessageForSigning(chainId)(txData),
);
};
23 changes: 23 additions & 0 deletions signer/src/verifyAggregate.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import * as hubbleBls from "../deps/hubble-bls";

import encodeMessageForSigning from "./encodeMessageForSigning";
import { AggregateTransactionData } from "./types";

export default (
domain: Uint8Array,
chainId: number,
) => (
aggregateTxData: AggregateTransactionData,
): boolean => {
const verifier = new hubbleBls.signer.BlsVerifier(domain);

return verifier.verifyMultiple(
hubbleBls.mcl.loadG1(aggregateTxData.signature),
aggregateTxData.transactions.map(
tx => hubbleBls.mcl.loadG2(tx.publicKey),
),
aggregateTxData.transactions.map(
tx => encodeMessageForSigning(chainId)(tx),
),
);
};
9 changes: 0 additions & 9 deletions signer/test/helpers/Range.ts

This file was deleted.

82 changes: 26 additions & 56 deletions signer/test/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@ import { arrayify } from "@ethersproject/bytes";
import { keccak256 } from "@ethersproject/keccak256";
import { expect } from "chai";

import { initBlsWalletSigner, Transaction, TransactionTemplate } from "../src";
import Range from "./helpers/Range";
import { initBlsWalletSigner, RawTransactionData } from "../src";

const domain = arrayify(keccak256("0xfeedbee5"));
const weiPerToken = BigNumber.from(10).pow(18);
Expand All @@ -15,7 +14,7 @@ const samples = (() => {
const dummy256HexString = "0x" + "0123456789".repeat(10).slice(0, 64);
const contractAddress = dummy256HexString;

const txTemplate: TransactionTemplate = {
const rawTx: RawTransactionData = {
nonce: BigNumber.from(123),
ethValue: BigNumber.from(0),
contractAddress,
Expand All @@ -27,7 +26,7 @@ const samples = (() => {

return {
contractAddress,
txTemplate,
rawTx,
privateKey,
otherPrivateKey,
};
Expand All @@ -40,9 +39,9 @@ describe("index", () => {
domain,
});

const { txTemplate, privateKey, otherPrivateKey } = samples;
const { rawTx, privateKey, otherPrivateKey } = samples;

const tx = sign(txTemplate, privateKey);
const tx = sign(rawTx, privateKey);

expect(tx.signature).to.equal([
"0x177500780b42f245e98229245126c9042e1cdaadc7ada72021ddd43492963a7b26f7a",
Expand All @@ -52,22 +51,18 @@ describe("index", () => {
expect(verify(tx)).to.equal(true);

const txBadSig = {
...tx,
signature: sign(txTemplate, otherPrivateKey).signature,
...sign(rawTx, otherPrivateKey),
publicKey: tx.publicKey, // Pretend this is the public key
};

expect(verify(txBadSig)).to.equal(false);

const txBadMessage: Transaction = {
subTransactions: [
{
...tx.subTransactions[0],
// Pretend the client signed to pay a million tokens
ethValue: weiPerToken.mul(1000000),
},
],
signature: tx.signature,
};
const txBadMessage = {
...tx,

// Pretend the client signed to pay a million tokens
ethValue: weiPerToken.mul(1000000),
}

expect(verify(txBadMessage)).to.equal(false);
});
Expand All @@ -76,59 +71,34 @@ describe("index", () => {
const {
sign,
aggregate,
verify,
verifyAggregate,
} = await initBlsWalletSigner({ chainId: 123, domain });

const { txTemplate, privateKey } = samples;
const { rawTx, privateKey } = samples;

const tx1 = sign(txTemplate, privateKey);
const tx2 = aggregate([tx1, tx1]);
const tx = sign(rawTx, privateKey);
const aggregateTx = aggregate([tx, tx]);

expect(tx2.signature).to.equal([
expect(aggregateTx.signature).to.equal([
"0x2cc0b05e8200cf564042735d15e2cc98181e730203530300022aafdd1ceb905830430",
"28617145dca56a00bf0693710e24683616ff4a42bc3cca7d587b36ff91f",
].join(""));

expect(verify(tx2)).to.equal(true);
expect(verifyAggregate(aggregateTx)).to.equal(true);

const tx2BadMessage: Transaction = {
...tx2,
subTransactions: [
tx2.subTransactions[0],
const aggregateTxBadMessage = {
...aggregateTx,
transactions: [
aggregateTx.transactions[0],
{
...tx2.subTransactions[1],
...aggregateTx.transactions[1],

// Pretend this client signed to pay a million tokens
ethValue: weiPerToken.mul(1000000),
},
}
],
}

expect(verify(tx2BadMessage)).to.equal(false);
});

it("can aggregate transactions which already have multiple subTransactions", async () => {
const {
sign,
aggregate,
verify,
} = await initBlsWalletSigner({ chainId: 123, domain });

const { txTemplate, privateKey } = samples;

const txs = Range(4).map(i => sign(
{
...txTemplate,
ethValue: BigNumber.from(i),
},
privateKey,
));

const aggTx1 = aggregate(txs.slice(0, 2));
const aggTx2 = aggregate(txs.slice(2, 4));

let aggAggTx = aggregate([aggTx1, aggTx2]);

expect(verify(aggAggTx)).to.equal(true);
expect(verifyAggregate(aggregateTxBadMessage)).to.equal(false);
});
});

0 comments on commit 18569c4

Please sign in to comment.