-
Notifications
You must be signed in to change notification settings - Fork 234
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
Conversation
ce23746
to
f4e3715
Compare
There was a problem hiding this 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.
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. |
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 |
I'm fine with using the auth witness. Will change the naming. |
There was a problem hiding this 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.
/** | ||
* 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>; |
There was a problem hiding this comment.
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
public getEip1271Witness(messageHash: Fr): Promise<Fr[]> { | ||
return Promise.resolve(this.eip1271Witnesses[messageHash.toString()]); |
There was a problem hiding this comment.
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.
async signAndAddEip1271Witness(messageHash: Buffer): Promise<void> { | ||
const witness = await this.accountImpl.createEip1271Witness(messageHash); | ||
await this.rpc.addEip1271Witness(Fr.fromBuffer(messageHash), witness); | ||
return Promise.resolve(); | ||
} |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
const { account: a, wallet: w } = await walletSetup( | ||
context.aztecRpcServer, | ||
encryptionPrivateKey, | ||
getAccountContract(encryptionPrivateKey), | ||
); | ||
account = a; | ||
wallet = w; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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]); |
There was a problem hiding this comment.
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
#[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); | ||
} |
There was a problem hiding this comment.
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 { |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.
createTxExecutionRequest(executions: FunctionCall[], _opts: CreateTxRequestOpts = {}): Promise<TxExecutionRequest> { | ||
throw new Error(`Not implemented, use createTxExecutionRequestWithWitness instead`); | ||
} |
There was a problem hiding this comment.
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.
ace2841
to
685a5ca
Compare
There was a problem hiding this 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 |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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.
685a5ca
to
84c7a0e
Compare
let witness = get_auth_witness(message_hash); | ||
assert(recover_address(message_hash, witness) == context.this_address()); |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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.
createTxExecutionRequest(executions: FunctionCall[], _opts: CreateTxRequestOpts = {}): Promise<TxExecutionRequest> { | ||
throw new Error(`Not implemented, use createTxExecutionRequestWithWitness instead`); | ||
} |
There was a problem hiding this comment.
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..?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Created #2043
5d9dda5
to
a4ebc27
Compare
🤖 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>
* 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.
Fixes #1913. For more information see the issue.
is_valid
functionChecklist:
Remove the checklist to signal you've completed it. Enable auto-merge if the PR is ready to merge.