Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: initial is_valid eip1271 style wallet + minimal test changes #1935

Merged
merged 12 commits into from
Sep 6, 2023

Conversation

LHerskind
Copy link
Contributor

@LHerskind LHerskind commented Sep 1, 2023

Fixes #1913. For more information see the issue.

  • Creates a new account contract that:
    • Adds support for the is_valid function
    • Uses oracle to get signatures for entrypoint and is_valid auth data

Checklist:

Remove the checklist to signal you've completed it. Enable auto-merge if the PR is ready to merge.

  • If the pull request requires a cryptography review (e.g. cryptographic algorithm implementations) I have added the 'crypto' tag.
  • I have reviewed my diff in github, line by line and removed unexpected formatting changes, testing logs, or commented-out code.
  • Every change is related to the PR description.
  • I have linked this pull request to relevant issues (if any exist).

Copy link
Collaborator

@PhilWindle PhilWindle left a comment

Choose a reason for hiding this comment

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

Should we remove the code references to Eip1271? I realise that's the inspiration behind it but it's an Ethereum reference.

@iAmMichaelConnor
Copy link
Contributor

Should we remove the code references to Eip1271? I realise that's the inspiration behind it but it's an Ethereum reference.

Removing the EIP references would be my preference too. Is there a short, descriptive name that can replace "EIP1271"?

@LHerskind
Copy link
Contributor Author

Should we remove the code references to Eip1271? I realise that's the inspiration behind it but it's an Ethereum reference.

Removing the EIP references would be my preference too. Is there a short, descriptive name that can replace "EIP1271"?

Ye, we can do that. So we have https://github.com/AztecProtocol/AZIPs repo for stuff like this. I can make an actual azip for it and then simply name it based on that instead.

@spalladino
Copy link
Collaborator

spalladino commented Sep 4, 2023

I'd vote for not using an EIP nor an AZIP identifier. We're early enough (and this would be core enough) that we should refer to it by name, and not by a made up number that makes understanding more difficult to an incoming dev (which is something that really sucks about Ethereum).

Maybe just s/Eip1271Witness/AuthWitness/g..?

@LHerskind
Copy link
Contributor Author

I'd vote for not using an EIP nor an AZIP identifier. We're early enough (and this would be core enough) that we should refer to it by name, and not by a made up number that makes understanding more difficult to an incoming dev (which is something that really sucks about Ethereum).

I'm fine with using the auth witness. Will change the naming.

Copy link
Collaborator

@spalladino spalladino left a comment

Choose a reason for hiding this comment

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

Awesome work. Left a few comments to discuss.

Comment on lines 13 to 18
/**
* Add a eip1271 witness to the database.
* @param messageHash - The message hash.
* @param witness - An array of field elements representing the eip1271 witness.
*/
addEip1271Witness(messageHash: Fr, witness: Fr[]): Promise<void>;
Copy link
Collaborator

Choose a reason for hiding this comment

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

I was going to make a sarcastic comment about how important it is that we have mandatory comments, but I've also been guilty of doing this kind of stuff :-P

Comment on lines 43 to 44
public getEip1271Witness(messageHash: Fr): Promise<Fr[]> {
return Promise.resolve(this.eip1271Witnesses[messageHash.toString()]);
Copy link
Collaborator

Choose a reason for hiding this comment

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

What should we return if there's no value for this key? If it's undefined (what I'd go with) we need to adjust the return type here.

Comment on lines 157 to 161
async signAndAddEip1271Witness(messageHash: Buffer): Promise<void> {
const witness = await this.accountImpl.createEip1271Witness(messageHash);
await this.rpc.addEip1271Witness(Fr.fromBuffer(messageHash), witness);
return Promise.resolve();
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

Should we return the signed message as well? I'm thinking this could be used for "exporting" the 12721 auth message and sharing it with another user who embeds it in their tx.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

You could use the sign for that, get the sig, then on the other side he recreate it 🤷 but I follow what you are saying, might be fine to add to retrieve directly.

Comment on lines 41 to 47
const { account: a, wallet: w } = await walletSetup(
context.aztecRpcServer,
encryptionPrivateKey,
getAccountContract(encryptionPrivateKey),
);
account = a;
wallet = w;
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
const { account: a, wallet: w } = await walletSetup(
context.aztecRpcServer,
encryptionPrivateKey,
getAccountContract(encryptionPrivateKey),
);
account = a;
wallet = w;
({ account, wallet } = await walletSetup(
context.aztecRpcServer,
encryptionPrivateKey,
getAccountContract(encryptionPrivateKey),
));

So you don't need the intermediate vars

GENERATOR_INDEX__SIGNATURE_PAYLOAD
)[0];

let _callStackItem0 = context.call_private_function(from, 0x29d25ca9, [message_field]);
Copy link
Collaborator

Choose a reason for hiding this comment

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

Add a comment on what 0x29d25ca9 is

Comment on lines 14 to 25
#[aztec(private)]
fn entrypoint(
payload: pub EntrypointPayload,
) {
let message_hash: Field = pedersen_with_separator(
payload.serialize(),
GENERATOR_INDEX__SIGNATURE_PAYLOAD
)[0];
let eip_witness = get_eip_1271_witness(message_hash);
assert(recover_address(message_hash, eip_witness) == context.this_address());
payload.execute_calls(&mut context);
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

Absolutely love how this turned out

* the note encryption key, relying on a single private key for both encryption and authentication.
* Extended to pull verification data from the oracle instead of passed as arguments.
*/
export class Eip1271AccountContract implements AccountContract {
Copy link
Collaborator

Choose a reason for hiding this comment

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

I'm curious how you found this abstraction to implement your own account contract..? Was it easy, confusing..? Anything you'd change?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Getting the abis in there was initially a pain. The copy script apparently adds _ before numbers, so that was a little funky.

It felt a bit clunky with the AuthWitnessAccountContract and then the entrypoints without the access to rpc and wallet without access to the keys, so the AuthWitnessAccountEntrypoint ended up looking a little odd as I needed the keys to sign and then passing that sig back such that the wallet could insert it into the RPC. Were thinking that throwing the rpc in there seemed the nicest way to keep it with same interface, but then the wallet bleeds into entrypoints, ended up with the separate wallet to handle the flow which don't seem like the cleanest, but needed a way to also insert into the db without a payload for the approvals etc.

Comment on lines 95 to 97
createTxExecutionRequest(executions: FunctionCall[], _opts: CreateTxRequestOpts = {}): Promise<TxExecutionRequest> {
throw new Error(`Not implemented, use createTxExecutionRequestWithWitness instead`);
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

Not a fan of this since it breaks composability (though I'm fine with it until we further refine all this 1271 story). I'd extend the TxExecutionRequest to also contain a set of MessageWithAuthWitness (where a MessageWithAuthWitness is just key+value, ie message+witness), so that when it's run through the simulator, it picks witnesses from there and only uses the db as fallback.

This should allow us to remove the new wallet type also.

Copy link
Member

@Maddiaa0 Maddiaa0 left a comment

Choose a reason for hiding this comment

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

Overall looks good to me, small comment

to,
amount
],
GENERATOR_INDEX__SIGNATURE_PAYLOAD
Copy link
Member

Choose a reason for hiding this comment

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

Im not sure I like that generator indexes are exposed directly to the programmer. I feel like there should be a helper function that takes in an array of inputs with a selector or something to abstract this from them.

It feels like a certain footgun

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ideally it should not be this generator at all. Think it is better with a separate generator such that payloads and other signatures don't sit in the same domain.

Comment on lines 22 to 23
let witness = get_auth_witness(message_hash);
assert(recover_address(message_hash, witness) == context.this_address());
Copy link
Collaborator

Choose a reason for hiding this comment

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

I'm guessing you cannot call is_valid directly to be inlined because it's already an external function, so it is initialising its own PrivateContext, right?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Will create an inner function that they are both calling, a little clunky, but should work fine for adding a public is valid later on as well.

Comment on lines +95 to +97
createTxExecutionRequest(executions: FunctionCall[], _opts: CreateTxRequestOpts = {}): Promise<TxExecutionRequest> {
throw new Error(`Not implemented, use createTxExecutionRequestWithWitness instead`);
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

Can you create an issue to track this, so we remove it eventually..?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Created #2043

@LHerskind LHerskind enabled auto-merge (squash) September 6, 2023 08:22
@LHerskind LHerskind merged commit f264c54 into master Sep 6, 2023
2 checks passed
@LHerskind LHerskind deleted the lh/1913-eip1271 branch September 6, 2023 09:16
spypsy pushed a commit that referenced this pull request Sep 6, 2023
🤖 I have created a new Aztec Packages release
---


##
[0.1.0-alpha60](v0.1.0-alpha59...v0.1.0-alpha60)
(2023-09-06)


### Features

* Goblin recursive verifier
([#1822](#1822))
([f962cb6](f962cb6))
* initial `is_valid` eip1271 style wallet + minimal test changes
([#1935](#1935))
([f264c54](f264c54))


### Bug Fixes

* benchmark git repo
([#2041](#2041))
([3c696bb](3c696bb))
* cli canary & deployment
([#2053](#2053))
([1ddd24a](1ddd24a))
* **rpc:** Fixes getNodeInfo serialisation
([#1991](#1991))
([0a29fa8](0a29fa8))


### Miscellaneous

* **circuits:** - use msgpack for cbind routines of native private
kernel circuits
([#1938](#1938))
([3dc5c07](3dc5c07))
* **docs:** API docs stucture
([#2014](#2014))
([9aab9dd](9aab9dd))
* Update function selector computation
([#2001](#2001))
([e07ea1a](e07ea1a))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
codygunton added a commit that referenced this pull request Jan 23, 2024
* Transport #1935 from monorepo.
Respond go Luke's PR review:
* Remove patch artifacts.; Delete unneeded sumcheck_types folder.; Note memory inefficiency of folding.; intebers ~> integers; Rename BarycentricData tests.; Fix bad find&replace in test names.; Removed unneeded include.; Git rid of UnivariateClass hack.; Move BarycentricData out of relations.; Restore health space between blocks.; Add all univariates to transcript.; Fix typo.; Revised comment around polynomial_cache.; Initialize target_total_sum.; edge_extensions ~> extended_edges; Fr ~> FF; Add comments to two sumcheck_round functions.; Fixed typo.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Archived in project
Development

Successfully merging this pull request may close these issues.

EIP-1271 like functionality
5 participants