8000 Clean up bls provider and signer by JohnGuilding · Pull Request #599 · getwax/bls-wallet · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content
This repository was archived by the owner on Nov 5, 2023. It is now read-only.

Clean up bls provider and signer #599

Merged
merged 6 commits into from
May 4, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 23 additions & 11 deletions contracts/clients/src/BlsSigner.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,11 @@
/* eslint-disable camelcase */
import { ethers, BigNumber, Signer, Bytes, BigNumberish } from "ethers";
import {
AccessListish,
Deferrable,
hexlify,
isBytes,
RLP,
} from "ethers/lib/utils";
import { AccessListish, Deferrable, hexlify, isBytes } from "ethers/lib/utils";

import BlsProvider, { PublicKeyLinkedToActions } from "./BlsProvider";
import BlsWalletWrapper from "./BlsWalletWrapper";
import addSafetyPremiumToFee from "./helpers/addSafetyDivisorToFee";
import { ActionData, bundleToDto } from "./signer";
import { ActionData, Signature, bundleToDto } from "./signer";

export const _constructorGuard = {};

Expand Down Expand Up @@ -393,16 +387,34 @@ export default class BlsSigner extends Signer {
return JSON.stringify(bundleToDto(bundle));
}

/** Signs a message */
// TODO: bls-wallet #201 Come back to this once we support EIP-1271
/**
* Signs a message. Because of the function signature enforced by ethers, we cannot return the signature
* in it's default type. Instead, we return a concatenated string of the signature.
*
* Use BlsSigner.signedMessageToSignature to convert the concatenated signature string into a BLS Signature type.
*
* @param message the message to be signed
* @returns a concatenated string of the signature
*/
override async signMessage(message: Bytes | string): Promise<string> {
await this.initPromise;
if (isBytes(message)) {
message = hexlify(message);
}

const signedMessage = this.wallet.signMessage(message);
return RLP.encode(signedMessage);
return (
ethers.utils.hexlify(signedMessage[0]) +
ethers.utils.hexlify(signedMessage[1]).substring(2)
);
}

/** helper method to convert blsSigner.signMessage concatenated signature string into BLS Signature type */
static signedMessageToSignature(signedMessage: string): Signature {
return [
ethers.utils.hexlify(signedMessage.substring(0, 66)),
ethers.utils.hexlify("0x" + signedMessage.substring(66, 130)),
];
}

override connect(provider: ethers.providers.Provider): BlsSigner {
Expand Down
75 changes: 71 additions & 4 deletions contracts/clients/test/BlsProvider.test.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { expect } from "chai";
import { ethers } from "ethers";
import { BigNumber, ethers } from "ethers";
import { parseEther } from "ethers/lib/utils";

import { BlsProvider, BlsSigner } from "../src";
import { BlsProvider, BlsSigner, bundleToDto } from "../src";
import { UncheckedBlsSigner } from "../src/BlsSigner";
import { initBlsWalletSigner } from "../src/signer";

let aggregatorUrl: string;
let verificationGateway: string;
Expand All @@ -20,8 +21,8 @@ let regularProvider: ethers.providers.JsonRpcProvider;
describe("BlsProvider", () => {
beforeEach(async () => {
aggregatorUrl = "http://localhost:3000";
verificationGateway = "mockVerificationGatewayAddress";
aggregatorUtilities = "mockAggregatorUtilitiesAddress";
verificationGateway = "0xC8CD2BE653759aed7B0996315821AAe71e1FEAdF";
aggregatorUtilities = "0xC8CD2BE653759aed7B0996315821AAe71e1FEAdF";
rpcUrl = "http://localhost:8545";
network = {
name: "localhost",
Expand Down Expand Up @@ -216,4 +217,70 @@ describe("BlsProvider", () => {
// Assert
expect(ready).to.deep.equal(expectedReady);
});

it("should throw an error when sending multiple signed operations to sendTransaction", async () => {
// Arrange
const mockWalletAddress = "0x1337AF0f4b693fd1c36d7059a0798Ff05a60DFFE";
const { sign, aggregate } = await initBlsWalletSigner({
chainId: 123,
verificationGatewayAddress: verificationGateway,
privateKey,
});

const expectedAmount = parseEther("1");
const verySafeFee = parseEther("0.1");
const firstRecipient = ethers.Wallet.createRandom().address;
const secondRecipient = ethers.Wallet.createRandom().address;

const firstActionWithSafeFee = blsProvider._addFeePaymentActionWithSafeFee(
[
{
ethValue: expectedAmount,
contractAddress: firstRecipient,
encodedFunction: "0x",
},
],
verySafeFee,
);
const secondActionWithSafeFee = blsProvider._addFeePaymentActionWithSafeFee(
[
{
ethValue: expectedAmount,
contractAddress: secondRecipient,
encodedFunction: "0x",
},
],
verySafeFee,
);

const nonce = BigNumber.from(0);

const firstOperation = {
nonce,
gas: BigNumber.from(30_000_000),
actions: [...firstActionWithSafeFee],
};
const secondOperation = {
nonce,
gas: BigNumber.from(30_000_000),
actions: [...secondActionWithSafeFee],
};

const firstBundle = sign(firstOperation, mockWalletAddress);
const secondBundle = sign(secondOperation, mockWalletAddress);

const aggregatedBundle = aggregate([firstBundle, secondBundle]);

// Act
const result = async () =>
await blsProvider.sendTransaction(
JSON.stringify(bundleToDto(aggregatedBundle)),
);

// Assert
await expect(result()).to.rejectedWith(
Error,
"Can only operate on single operations. Call provider.sendTransactionBatch instead",
);
});
});
29 changes: 26 additions & 3 deletions contracts/clients/test/BlsSigner.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { expect } from "chai";
import { ethers } from "ethers";
import { BigNumber, ethers } from "ethers";

import { BlsProvider, BlsSigner } from "../src";
import { UncheckedBlsSigner } from "../src/BlsSigner";
Expand All @@ -17,8 +17,8 @@ let blsSigner: BlsSigner;
describe("BlsSigner", () => {
beforeEach(async () => {
aggregatorUrl = "http://localhost:3000";
verificationGateway = "mockVerificationGatewayAddress";
aggregatorUtilities = "mockAggregatorUtilitiesAddress";
verificationGateway = "0xC8CD2BE653759aed7B0996315821AAe71e1FEAdF";
aggregatorUtilities = "0xC8CD2BE653759aed7B0996315821AAe71e1FEAdF";
rpcUrl = "http://localhost:8545";
network = {
name: "localhost",
Expand Down Expand Up @@ -94,4 +94,27 @@ describe("BlsSigner", () => {
// Assert
expect(connect).to.throw(Error, "cannot alter JSON-RPC Signer connection");
});

it("should throw error for wrong chain id when validating batch options", async () => {
// Arrange
const invalidChainId = 123;
const batchOptions = {
gas: BigNumber.from("40000"),
maxPriorityFeePerGas: ethers.utils.parseUnits("0.5", "gwei"),
maxFeePerGas: ethers.utils.parseUnits("23", "gwei"),
nonce: 1,
chainId: invalidChainId,
accessList: [],
};

// Act
const result = async () =>
await blsSigner._validateBatchOptions(batchOptions);

// Assert
expect(result()).to.be.rejectedWith(
Error,
`Supplied chain ID ${invalidChainId} does not match the expected chain ID 1337`,
);
});
});
Loading
0