Skip to content
This repository has been archived by the owner on Sep 30, 2024. It is now read-only.

Commit

Permalink
Merge pull request #222 from getwax/wax-221-inpage-bls
Browse files Browse the repository at this point in the history
Add BLS to compression plugin, use in in-page demo
  • Loading branch information
JohnGuilding authored Mar 27, 2024
2 parents c1c1e05 + a013e30 commit f547b9a
Show file tree
Hide file tree
Showing 33 changed files with 1,408 additions and 157 deletions.
3 changes: 3 additions & 0 deletions packages/demos/inpage/.eslintrc.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -123,5 +123,8 @@ module.exports = {
'consistent-return': 'off',
'no-plusplus': 'off',
'no-bitwise': 'off',
'@typescript-eslint/no-unsafe-argument': 'off',
'@typescript-eslint/no-unsafe-assignment': 'off',
'@typescript-eslint/no-unsafe-return': 'off',
},
};
2 changes: 1 addition & 1 deletion packages/demos/inpage/demo/ChooseAccountPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ const ChooseAccountPage = () => {
<ul style={{ textAlign: 'left' }}>
<li>L2 Cost Savings</li>
<li>Multi-Action</li>
<li>ECDSA (BLS Future)</li>
<li>BLS</li>
<li>(Built in Safe)</li>
</ul>
</div>
Expand Down
3 changes: 3 additions & 0 deletions packages/demos/inpage/hardhat/contracts/imports.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ pragma solidity ^0.8.0;

import {EntryPoint} from "account-abstraction/contracts/core/EntryPoint.sol";
import {SimpleAccountFactory} from "account-abstraction/contracts/samples/SimpleAccountFactory.sol";
import {BLSSignatureAggregator} from "account-abstraction/contracts/samples/bls/BLSSignatureAggregator.sol";
import {UserOperation} from "account-abstraction/contracts/interfaces/UserOperation.sol";

import {Safe} from "../lib/plugins/lib/safe-contracts/contracts/Safe.sol";
import {SafeECDSAFactory} from "../lib/plugins/src/safe/SafeECDSAFactory.sol";
Expand All @@ -12,4 +14,5 @@ import {SafeCompressionPlugin} from "../lib/plugins/src/safe/SafeCompressionPlug
import {FallbackDecompressor} from "../lib/compression/src/decompressors/FallbackDecompressor.sol";
import {AddressRegistry} from "../lib/compression/src/AddressRegistry.sol";
import {HandleOpsCaller} from "../lib/compression/src/HandleOpsCaller.sol";
import {HandleAggregatedOpsCaller} from "../lib/compression/src/HandleAggregatedOpsCaller.sol";
import {SafeECDSARecoveryPlugin} from "../lib/plugins/src/safe/SafeECDSARecoveryPlugin.sol";
1 change: 1 addition & 0 deletions packages/demos/inpage/lib-ts/deterministic-deployer
1 change: 1 addition & 0 deletions packages/demos/inpage/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
},
"dependencies": {
"@s-libs/micro-dash": "^16.0.0",
"@thehubbleproject/bls": "^0.5.1",
"@types/color": "^3.0.3",
"color": "^4.2.3",
"ethers": "^6.6.4",
Expand Down
40 changes: 35 additions & 5 deletions packages/demos/inpage/src/WaxInPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ import makeLocalWaxStorage, { WaxStorage } from './WaxStorage';
import {
AddressRegistry,
AddressRegistry__factory,
BLSOpen__factory,
BLSSignatureAggregator,
BLSSignatureAggregator__factory,
ERC20Mock,
ERC20Mock__factory,
EntryPoint,
Expand All @@ -28,9 +31,6 @@ import {
SimpleAccountFactory,
SimpleAccountFactory__factory,
} from '../hardhat/typechain-types';
import SafeSingletonFactory, {
SafeSingletonFactoryViewer,
} from './SafeSingletonFactory';
import ReusablePopup from './ReusablePopup';
import AdminPopup, { AdminPurpose } from './AdminPopup';
import waxPrivate from './waxPrivate';
Expand All @@ -47,6 +47,9 @@ import SafeCompressionAccountWrapper from './accounts/SafeCompressionAccountWrap
import { hexLen } from './helpers/encodeUtils';
import JsonRpcError from './JsonRpcError';
import measureCalldataGas from './measureCalldataGas';
import DeterministicDeployer, {
DeterministicDeploymentViewer,
} from '../lib-ts/deterministic-deployer/DeterministicDeployer';

type Config = {
logRequests?: boolean;
Expand Down Expand Up @@ -82,6 +85,7 @@ export type Contracts = {
addressRegistry: AddressRegistry;
safeECDSARecoveryPlugin: SafeECDSARecoveryPlugin;
testToken: ERC20Mock;
blsSignatureAggregator: BLSSignatureAggregator;
};

export default class WaxInPage {
Expand Down Expand Up @@ -185,7 +189,10 @@ export default class WaxInPage {
await this.ethereum.request({ method: 'eth_chainId' }),
);

const viewer = new SafeSingletonFactoryViewer(this.ethersProvider, chainId);
const viewer = new DeterministicDeploymentViewer(
this.ethersProvider,
chainId,
);

const assumedEntryPoint = viewer.connectAssume(EntryPoint__factory, []);

Expand All @@ -194,6 +201,8 @@ export default class WaxInPage {
[],
);

const assumedBlsOpen = viewer.connectAssume(BLSOpen__factory, []);

const contracts: Contracts = {
greeter: viewer.connectAssume(Greeter__factory, ['']).connect(runner),
entryPoint: assumedEntryPoint,
Expand All @@ -217,6 +226,15 @@ export default class WaxInPage {
[],
),
testToken: viewer.connectAssume(ERC20Mock__factory, []),
blsSignatureAggregator: viewer.connectAssume(
DeterministicDeployer.link(BLSSignatureAggregator__factory, [
{
'account-abstraction/contracts/samples/bls/lib/BLSOpen.sol:BLSOpen':
await assumedBlsOpen.getAddress(),
},
]),
[],
),
};

if (this.#contractsDeployed) {
Expand All @@ -234,7 +252,7 @@ export default class WaxInPage {

const wallet = await this.requestAdminAccount('deploy-contracts');

const factory = await SafeSingletonFactory.init(wallet);
const factory = await DeterministicDeployer.init(wallet);

const entryPoint = await factory.connectOrDeploy(EntryPoint__factory, []);

Expand All @@ -243,6 +261,8 @@ export default class WaxInPage {
[],
);

const blsOpen = await factory.connectOrDeploy(BLSOpen__factory, []);

const deployments: {
[C in keyof Contracts]: () => Promise<Contracts[C]>;
} = {
Expand All @@ -265,6 +285,16 @@ export default class WaxInPage {
safeECDSARecoveryPlugin: () =>
factory.connectOrDeploy(SafeECDSARecoveryPlugin__factory, []),
testToken: () => factory.connectOrDeploy(ERC20Mock__factory, []),
blsSignatureAggregator: async () =>
factory.connectOrDeploy(
DeterministicDeployer.link(BLSSignatureAggregator__factory, [
{
'account-abstraction/contracts/samples/bls/lib/BLSOpen.sol:BLSOpen':
await blsOpen.getAddress(),
},
]),
[],
),
};

for (const deployment of Object.values(deployments)) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import { ethers } from 'ethers';
import { ethers, getBytes, keccak256, solidityPacked } from 'ethers';
import { z } from 'zod';
import { signer as hubbleBlsSigner } from '@thehubbleproject/bls';
import {
SafeCompressionPlugin,
SafeCompressionPlugin__factory,
} from '../../hardhat/typechain-types';
import EthereumRpc from '../EthereumRpc';
import IAccount from './IAccount';
import WaxInPage from '..';
import { SafeCompressionFactory } from '../../hardhat/typechain-types/lib/packages/plugins/src/SafeCompressionFactory';
import { SafeCompressionFactory } from '../../hardhat/typechain-types/lib/plugins/src/safe/SafeCompressionFactory';
import receiptOf from '../helpers/receiptOf';
import {
encodeBitStack,
Expand All @@ -18,6 +19,7 @@ import {
hexLen,
lookupAddress,
} from '../helpers/encodeUtils';
import getBlsUserOpHash from '../helpers/getBlsUserOpHash';

export const SafeCompressionAccountData = z.object({
type: z.literal('SafeCompressionAccount'),
Expand Down Expand Up @@ -73,6 +75,8 @@ export default class SafeCompressionAccountWrapper implements IAccount {
const createArgs = [
contracts.safe,
contracts.entryPoint,
contracts.blsSignatureAggregator,
(await getBlsSigner(wallet.privateKey)).pubkey,
contracts.fallbackDecompressor,
wallet,
0,
Expand Down Expand Up @@ -175,11 +179,36 @@ export default class SafeCompressionAccountWrapper implements IAccount {
}

async sign(
_userOp: EthereumRpc.UserOperation,
userOpHash: string,
userOp: EthereumRpc.UserOperation,
_userOpHash: string,
): Promise<string> {
const ownerWallet = new ethers.Wallet(this.privateKey);
const blsSigner = await getBlsSigner(this.privateKey);
const provider = this.waxInPage.ethersProvider;
const contracts = await this.waxInPage.getContracts();

return await ownerWallet.signMessage(ethers.getBytes(userOpHash));
const blsUserOpHash = getBlsUserOpHash(
(await provider.getNetwork()).chainId,
await contracts.blsSignatureAggregator.getAddress(),
blsSigner.pubkey,
userOp,
);

return solidityPacked(['uint256[2]'], [blsSigner.sign(blsUserOpHash)]);
}
}

async function getBlsSigner(ecdsaPrivateKey: string) {
// Note: The BLS library we use implements key derivation that allows this
// to work, so it's the simplest way to get a BLS private key in our
// context, but there should be a standard around this.
const blsPrivateKey = ecdsaPrivateKey;

const domain = getBytes(
keccak256(new TextEncoder().encode('eip4337.bls.domain')),
);

const signerFactory = await hubbleBlsSigner.BlsSignerFactory.new();
const blsSigner = signerFactory.getSigner(domain, blsPrivateKey);

return blsSigner;
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
import EthereumRpc from '../EthereumRpc';
import IAccount from './IAccount';
import WaxInPage from '..';
import { SafeECDSAFactory } from '../../hardhat/typechain-types/lib/packages/plugins/src/SafeECDSAFactory';
import { SafeECDSAFactory } from '../../hardhat/typechain-types/lib/plugins/src/safe/SafeECDSAFactory';
import receiptOf from '../helpers/receiptOf';
import { executeContractCallWithSigners } from './execution';
import assert from '../helpers/assert';
Expand Down
Loading

0 comments on commit f547b9a

Please sign in to comment.