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

Use compression in aggregator #584

Merged
merged 8 commits into from
May 2, 2023

Conversation

voltrevo
Copy link
Collaborator

@voltrevo voltrevo commented Apr 24, 2023

Dependent PR

This PR depends on #586.

After that's merged, toggle the target branch back and forth or push an empty commit to fix the diff. (Preview of this PR's changes.)

(If you want, you can also just review+merge this one directly. Github will automerge the previous PRs.)

What is this PR doing?

Uses compression in aggregator. Reduces the data field when sending a single ETH transfer from 836 bytes down to 164 bytes.

How can these changes be manually tested?

(Replicating this test isn't required.)

Use Quill to do an ETH transfer and verify the transaction data is about 324 bytes. Here's what I got on arbitrum goerli:

Screen Shot 2023-04-24 at 3 33 07 pm

Explorer link

To reduce this further, use ./manualTests/registerWallet.ts to register the source BLS key and address, as well as the destination address. Verify that reduces the transaction data down to about 164 bytes:

Screen Shot 2023-04-24 at 3 33 17 pm

Explorer link

For comparison I used version f8a8c490 (git checkout f8a8c490) (this is right before the contract-updates merge, which naturally changes the contracts so main currently doesn't work with the existing deployment). Here's the transaction data from that one:

Screen Shot 2023-04-24 at 3 55 20 pm

Explorer link

Wait, wait, still 164 bytes? 😰

Yeah. That's just the data field too. If you include the full transaction data (including the envelope with the aggregator's signature and gas settings etc), then there's another 115 bytes or so (total is about 279 bytes).

Anyway, 164 bytes in the data field is a lot more than we need, and it's because there's still some cleanup to do. Here's the breakdown of those bytes:

0x

3a276523
  - method id of run()

0000000000000000000000000000000000000000000000000000000000000020
  - location of byte array for `stream` calldata argument

0000000000000000000000000000000000000000000000000000000000000056
  - `stream` is 86 bytes long
    (==0x56 but solidity abi uses an entire uint256 word for this)

01
  - one operation

00
  - use expander id 0 (fallback expander)

07
  - 0x07 = 0b111 - bit stream:
    - 1: Use registry for sendWallet's public key
    - 1: Include a tx.origin payment
    - 1: Use registry for recvWallet's address

000000
  - id of sender's bls public key

01
  - nonce

0cb730
  - 56,708 gas

02
  - two actions (send ETH and pay tx.origin)

7900
  - 0.0001 ETH

000001
  - id recipient's address

00
  - zero bytes for encodedFunction

3092cbb31e
  - pay 0.0000311872752 ETH to tx.origin

0b018b1989c5c62d43b0a0427f04781f2a4e201ab2c938ad23aa2d0a6c0a284a
03f37bd9fbdac1b34f3046363244c0e47a2a73add7cdfac41c2f134285256dfc
  - BLS signature

00000000000000000000
  - padding bytes from the solidity abi to make a multiple of 32 bytes

In summary:

  • 78 bytes of ABI overhead
  • 1 byte to say that there's one operation
  • 21 bytes for the actual operation (send ETH to recipient and pay tx.origin)
  • 64 bytes for the signature

We should be able to remove the ABI overhead by introducing another contract whose whole purpose is to call the expander with its raw argument.

Focusing on the positive, very small encodings for the actual operations have been achieved, and this means that the marginal data cost of each operation is this low number (20 bytes or so). This means you could add 100 transactions for 2100 bytes, so the whole transaction would be 2100+279=2379 bytes, or about 24 bytes per transaction. Then the marginal cost becomes dominant, BUT you need to wait for 100 transactions before you can submit.

Related improvements to work on:

  • Fix those 78 bytes of overhead
  • Round up to 3 significant figures for gas limit and tx.origin payment (would bring 21 bytes above down to 17)
  • Add registration functionality to Quill

Does this PR resolve or contribute to any issues?

Resolves #406.

Checklist

  • I have manually tested these changes
  • Post a link to the PR in the group chat

Guidelines

  • If your PR is not ready, mark it as a draft
  • The resolve conversation button is for reviewers, not authors
    • (But add a 'done' comment or similar)

@github-actions github-actions bot added aggregator Aggregator backend related clients contracts Smart contract related labels Apr 24, 2023
@voltrevo voltrevo force-pushed the bw-406-aggregator-compression branch from b1da6c7 to e42ccf2 Compare April 24, 2023 08:34
@voltrevo voltrevo marked this pull request as ready for review April 24, 2023 08:37
@blakecduncan blakecduncan changed the base branch from contract-updates to main May 2, 2023 11:26
@blakecduncan blakecduncan changed the base branch from main to contract-updates May 2, 2023 11:27
Copy link
Contributor

@blakecduncan blakecduncan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

Code all looks good, so gonna merge. Just had some questions for my clarity

const compressedBundle = await this.bundleCompressor.compress(bundle);

const [rawTx, rawCompressedTx] = await Promise.all([
this.verificationGateway.populateTransaction.processBundle(bundle).then(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need to populate the transaction with the VG and also with the bundle compressor? Or do we just do the VG one so that we can log out what the rawTx length is?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nah it's only for logging.

);

await receiptOf(
blsPublicKeyRegistry.register(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just for my understanding - We register a wallet with the registry because it allows us to compress the transaction even more. Is this the only way we can currently register a wallet? Asking just to check if a wallet would get registered on its own after its first transaction.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pretty much yeah. It doesn't happen automatically. We need to do something about that.

Also:

it allows us to compress the transaction even more

technically correct but I wouldn't phrase it that way. It's not 'even better', it's essential - otherwise your tx will be more expensive, not less.

@blakecduncan blakecduncan merged commit ffd7037 into contract-updates May 2, 2023
@blakecduncan blakecduncan deleted the bw-406-aggregator-compression branch May 2, 2023 14:41
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
aggregator Aggregator backend related clients contracts Smart contract related
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants