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 #186 from web3well/add-receipts
Browse files Browse the repository at this point in the history
Add receipts
  • Loading branch information
jacque006 authored Apr 15, 2022
2 parents c8ebbc3 + 45ae166 commit 3dcae29
Show file tree
Hide file tree
Showing 37 changed files with 416 additions and 423 deletions.
7 changes: 4 additions & 3 deletions aggregator/deps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ export { delay } from "https://deno.land/[email protected]/async/delay.ts";
export { parse as parseArgs } from "https://deno.land/[email protected]/flags/mod.ts";
export { exists } from "https://deno.land/[email protected]/fs/mod.ts";
export { dirname } from "https://deno.land/[email protected]/path/mod.ts";
export { oakCors } from "https://deno.land/x/[email protected]/mod.ts";

import { config as dotEnvConfig } from "https://deno.land/x/[email protected]/mod.ts";
export { dotEnvConfig };
Expand Down Expand Up @@ -48,7 +49,7 @@ export type {
PublicKey,
Signature,
VerificationGateway,
} from "https://esm.sh/bls-wallet-clients@0.5.4-f2bad77";
} from "https://esm.sh/bls-wallet-clients@0.6.0-6abef92";

export {
Aggregator as AggregatorClient,
Expand All @@ -58,10 +59,10 @@ export {
getConfig,
MockERC20__factory,
VerificationGateway__factory,
} from "https://esm.sh/bls-wallet-clients@0.5.4-f2bad77";
} from "https://esm.sh/bls-wallet-clients@0.6.0-6abef92";

// Workaround for esbuild's export-star bug
import blsWalletClients from "https://esm.sh/bls-wallet-clients@0.5.4-f2bad77";
import blsWalletClients from "https://esm.sh/bls-wallet-clients@0.6.0-6abef92";
const {
bundleFromDto,
bundleToDto,
Expand Down
6 changes: 3 additions & 3 deletions aggregator/manualTests/addDemoTx.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ const bundle = wallet.sign({

console.log("sending", bundle);

const failures = await client.add(bundle);
if (failures.length) {
throw new Error(failures.join(", "));
const res = await client.add(bundle);
if ("failures" in res) {
throw new Error(res.failures.join(", "));
}
6 changes: 3 additions & 3 deletions aggregator/manualTests/addDummyTx.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ const bundle: Bundle = {

console.log("sending", bundle);

const failures = await client.add(bundle);
if (failures.length) {
throw new Error(failures.join(", "));
const res = await client.add(bundle);
if ("failures" in res) {
throw new Error(res.failures.join(", "));
}
9 changes: 5 additions & 4 deletions aggregator/manualTests/mint1ViaAggregator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import {
MockERC20__factory,
} from "../deps.ts";

import assert from "../src/helpers/assert.ts";
import getNetworkConfig from "../src/helpers/getNetworkConfig.ts";
import * as env from "../test/env.ts";
import TestBlsWallets from "./helpers/TestBlsWallets.ts";
Expand Down Expand Up @@ -40,10 +39,12 @@ console.log({ feeEstimation });

console.log("Sending mint bundle to aggregator");

const failures = await client.add(bundle);
assert(failures.length === 0, failures.map((f) => f.description).join(", "));
const res = await client.add(bundle);
if ("failures" in res) {
throw new Error(res.failures.map((f) => f.description).join(", "));
}

console.log("Success response from aggregator");
console.log("Success response from aggregator", res.hash);

while (true) {
const balance = (await testErc20.balanceOf(wallet.address));
Expand Down
25 changes: 25 additions & 0 deletions aggregator/manualTests/send1Wei.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#!/usr/bin/env -S deno run --unstable --allow-net --allow-env --allow-read

import { ethers } from "../deps.ts";
import * as env from "../src/env.ts";
import AdminWallet from "../src/chain/AdminWallet.ts";

const provider = new ethers.providers.JsonRpcProvider(env.RPC_URL);

const adminWallet = AdminWallet(provider);
const to = ethers.constants.AddressZero;

console.log("sending 1 wei");
console.log(`${adminWallet.address} -> ${to}`);

const txn = await adminWallet.sendTransaction({
value: "0x01",
to,
});

console.log(`txn hash ${txn.hash}`);
console.log("waiting ...");

await txn.wait();

console.log("done");
4 changes: 2 additions & 2 deletions aggregator/manualTests/throughput.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,8 +107,8 @@ pollingLoop(() => {
}],
});

client.add(bundle).then((failures) => {
if (failures.length > 0) {
const res = client.add(bundle).then((failures) => {
if ("failures" in res) {
console.log({ failures });
}

Expand Down
2 changes: 1 addition & 1 deletion aggregator/programs/dropTables.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#!/usr/bin/env -S deno run --allow-net --unstable --allow-read
#!/usr/bin/env -S deno run --unstable --allow-net --allow-read --allow-env

// Useful for when breaking database changes are made.

Expand Down
2 changes: 1 addition & 1 deletion aggregator/programs/showTables.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#!/usr/bin/env -S deno run --allow-net --unstable --allow-read
#!/usr/bin/env -S deno run --unstable --allow-net --allow-read --unstable

import { BigNumber } from "../deps.ts";
import createQueryClient from "../src/app/createQueryClient.ts";
Expand Down
7 changes: 3 additions & 4 deletions aggregator/src/app/AppEvent.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import { HTTPMethods } from "../../deps.ts";

type RowId = number | undefined;

type AppEvent = (
| { type: "listening"; data: { port: number } }
| { type: "db-query"; data: { sql: string; params: unknown[] } }
Expand All @@ -18,15 +16,16 @@ type AppEvent = (
error: Error;
};
}
| { type: "submission-sent"; data: { rowIds: RowId[] } }
| { type: "submission-sent"; data: { hash: string } }
| {
type: "submission-confirmed";
data: { rowIds: RowId[]; blockNumber: number };
data: { hash: string; bundleHashes: string[], blockNumber: number };
}
| { type: "warning"; data: string }
| {
type: "bundle-added";
data: {
hash: string;
publicKeyShorts: string[];
};
}
Expand Down
23 changes: 19 additions & 4 deletions aggregator/src/app/BundleRouter.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Router } from "../../deps.ts";
import failRequest from "./helpers/failRequest.ts";
import BundleHandler from "./helpers/BundleHandler.ts";
import nil from "../helpers/nil.ts";

import BundleService from "./BundleService.ts";

Expand All @@ -10,15 +11,29 @@ export default function BundleRouter(bundleService: BundleService) {
router.post(
"bundle",
BundleHandler(async (ctx, bun) => {
const failures = await bundleService.add(bun);
const result = await bundleService.add(bun);

if (failures.length > 0) {
return failRequest(ctx, failures);
if ("failures" in result) {
return failRequest(ctx, result.failures);
}

ctx.response.body = { failures: [] };
ctx.response.body = result;
}),
);

router.get(
"bundleReceipt/:hash",
async (ctx) => {
const receipt = await bundleService.lookupReceipt(ctx.params.hash!);

if (receipt === nil) {
ctx.response.status = 404;
return;
}

ctx.response.body = receipt;
},
);

return router;
}
82 changes: 63 additions & 19 deletions aggregator/src/app/BundleService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {
BlsWalletSigner,
Bundle,
delay,
ethers,
QueryClient,
} from "../../deps.ts";

Expand All @@ -16,10 +17,13 @@ import * as env from "../env.ts";
import runQueryGroup from "./runQueryGroup.ts";
import EthereumService from "./EthereumService.ts";
import AppEvent from "./AppEvent.ts";
import BundleTable, { BundleRow } from "./BundleTable.ts";
import BundleTable, { BundleRow, makeHash } from "./BundleTable.ts";
import countActions from "./helpers/countActions.ts";
import plus from "./helpers/plus.ts";
import AggregationStrategy from "./AggregationStrategy.ts";
import nil from "../helpers/nil.ts";

export type AddBundleResponse = { hash: string } | { failures: TransactionFailure[] };

export default class BundleService {
static defaultConfig = {
Expand All @@ -34,6 +38,12 @@ export default class BundleService {
unconfirmedActionCount = 0;
unconfirmedRowIds = new Set<number>();

// TODO (merge-ok) use database table in the future to persist
confirmedBundles = new Map<string, {
bundle: Bundle,
receipt: ethers.ContractReceipt,
}>();

submissionTimer: SubmissionTimer;
submissionsInProgress = 0;

Expand Down Expand Up @@ -104,7 +114,7 @@ export default class BundleService {
);

const actionCount = eligibleRows
.filter((r) => !this.unconfirmedRowIds.has(r.id!))
.filter((r) => !this.unconfirmedRowIds.has(r.id))
.map((r) => countActions(r.bundle))
.reduce(plus, 0);

Expand All @@ -126,15 +136,19 @@ export default class BundleService {
);
}

async add(bundle: Bundle): Promise<TransactionFailure[]> {
async add(
bundle: Bundle,
): Promise<AddBundleResponse> {
if (bundle.operations.length !== bundle.senderPublicKeys.length) {
return [
{
type: "invalid-format",
description:
"number of operations does not match number of public keys",
},
];
return {
failures: [
{
type: "invalid-format",
description:
"number of operations does not match number of public keys",
},
],
};
}

const signedCorrectly = this.blsWalletSigner.verify(bundle);
Expand All @@ -151,11 +165,14 @@ export default class BundleService {
failures.push(...await this.ethereumService.checkNonces(bundle));

if (failures.length > 0) {
return failures;
return { failures };
}

return await this.runQueryGroup(async () => {
const hash = makeHash();

await this.bundleTable.add({
hash,
bundle,
eligibleAfter: await this.ethereumService.BlockNumber(),
nextEligibilityDelay: BigNumber.from(1),
Expand All @@ -164,16 +181,35 @@ export default class BundleService {
this.emit({
type: "bundle-added",
data: {
hash,
publicKeyShorts: bundle.senderPublicKeys.map(toShortPublicKey),
},
});

this.addTask(() => this.tryAggregating());

return [];
return { hash };
});
}

// TODO (merge-ok) Remove lint ignore when this hits db
// deno-lint-ignore require-await
async lookupReceipt(hash: string) {
const confirmation = this.confirmedBundles.get(hash);

if (!confirmation) {
return nil;
}

const receipt = confirmation.receipt;

return {
transactionIndex: receipt.transactionIndex,
blockHash: receipt.blockHash,
blockNumber: receipt.blockNumber,
};
}

async runSubmission() {
this.submissionsInProgress++;

Expand All @@ -187,7 +223,7 @@ export default class BundleService {

// Exclude rows that are already pending.
eligibleRows = eligibleRows.filter(
(row) => !this.unconfirmedRowIds.has(row.id!),
(row) => !this.unconfirmedRowIds.has(row.id),
);

const { aggregateBundle, includedRows, failedRows } = await this
Expand Down Expand Up @@ -224,7 +260,7 @@ export default class BundleService {
await this.bundleTable.remove(row);
}

this.unconfirmedRowIds.delete(row.id!);
this.unconfirmedRowIds.delete(row.id);
}

async submitAggregateBundle(
Expand All @@ -250,22 +286,30 @@ export default class BundleService {
this.unconfirmedBundles.add(aggregateBundle);

for (const row of includedRows) {
this.unconfirmedRowIds.add(row.id!);
this.unconfirmedRowIds.add(row.id);
}

this.addTask(async () => {
try {
const recpt = await this.ethereumService.submitBundle(
const receipt = await this.ethereumService.submitBundle(
aggregateBundle,
Infinity,
300,
);

for (const row of includedRows) {
this.confirmedBundles.set(row.hash, {
bundle: row.bundle,
receipt,
});
}

this.emit({
type: "submission-confirmed",
data: {
rowIds: includedRows.map((row) => row.id),
blockNumber: recpt.blockNumber,
hash: receipt.transactionHash,
bundleHashes: includedRows.map((row) => row.hash),
blockNumber: receipt.blockNumber,
},
});

Expand All @@ -275,7 +319,7 @@ export default class BundleService {
this.unconfirmedBundles.delete(aggregateBundle);

for (const row of includedRows) {
this.unconfirmedRowIds.delete(row.id!);
this.unconfirmedRowIds.delete(row.id);
}
}
});
Expand Down
Loading

0 comments on commit 3dcae29

Please sign in to comment.