-
Notifications
You must be signed in to change notification settings - Fork 266
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
refactor: Update function selector computation #2001
Conversation
95a0115
to
330ae13
Compare
@@ -29,6 +29,7 @@ export const ONE_ACVM_FIELD: ACVMField = `0x${'00'.repeat(Fr.SIZE_IN_BYTES - 1)} | |||
* The supported oracle names. | |||
*/ | |||
type ORACLE_NAMES = | |||
| 'computeSelector' |
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.
despite the convinience, computing the selector is something that should be done at compile time, and not at runtime. A malicious app could alter the source code / calls being made without changing the verification key.
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.
In the sandbox a malicious actor can do whatever they want. Calling other functions are also done through oracles where it could just return success independent of what happens. This is essentially just a helper to compute an input to another function that is completely controlled by a possibly malicious app so not sure it changes much there 🤷
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 may be missing something, but I agree with @Maddiaa0 on this one. Calling other functions as you say can also return anything, but we then have a kernel circuit that ensures that the oracle behaved properly. But it's true it doesn't affect the security of sandbox as it is today.
I'm fine merging this, but we should add an issue to replace it with a Noir-only implementation in the future (ie before testnet).
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 suppose if the sought-after pattern is to have the selector be a parameter to the function, then an oracle is ok. It would be akin to this Solidity pseudocode (because I've forgotten how to write solidity):
function do_an_arbitrary_call(bytes4 selector) {
address contract_address = 0x1234...;
call(contract_address, selector);
}
But if a user actually wants to always call a specific selector, then an oracle call is dangerous, because it isn't constrained:
function do_a_specific_call() {
address contract_address = 0x1234...;
bytes4 selector = 0x12345678; // this cannot be achieved with an oracle call
call(contract_address, selector);
}
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.
Allowing users to take over control flow is almost always a death-sin in solidity. I agree with both @spalladino and @Maddiaa0 that having an oracle is horrible, but since you can take over whenever through some of the other execution it seemed like a solution that was usable for this problem. #1550 should get rid of it, it is just used temporarily because it is too shit to compute selectors by hand when you want self-calls etc.
330ae13
to
d391150
Compare
@@ -29,6 +29,7 @@ export const ONE_ACVM_FIELD: ACVMField = `0x${'00'.repeat(Fr.SIZE_IN_BYTES - 1)} | |||
* The supported oracle names. | |||
*/ | |||
type ORACLE_NAMES = | |||
| 'computeSelector' |
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 may be missing something, but I agree with @Maddiaa0 on this one. Calling other functions as you say can also return anything, but we then have a kernel circuit that ensures that the oracle behaved properly. But it's true it doesn't affect the security of sandbox as it is today.
I'm fine merging this, but we should add an issue to replace it with a Noir-only implementation in the future (ie before testnet).
let abi: FunctionAbiWithDebugMetadata | undefined = undefined; | ||
|
||
// Brute force | ||
for (let i = 1; i < 5; i++) { |
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 believe we got a MAX_NOTE_FIELDS_LENGTH
constant we could use here instead of the 5
export const computeNoteHashAndNullifierSignature = 'compute_note_hash_and_nullifier(Field,Field,Field,[Field;3])'; | ||
|
||
export const computeNoteHashAndNullifierSelector = FunctionSelector.fromSignature(computeNoteHashAndNullifierSignature); |
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 we remove these, given they are replaced by the loop?
@@ -88,6 +88,7 @@ describe('e2e_lending_contract', () => { | |||
stableCoin: NativeTokenContract, | |||
account: Account, | |||
) => { | |||
await sleep(5000); |
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.
Is this needed? If so, let's add a comment on why.
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.
Ah, no was when debugging and thinking it was due to race-conditions, will remove it.
// If you are debugging, can be useful to uncomment the following line. | ||
// console.log(`Function selector for ${signature} is ${selector}`); |
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.
Why not use a debug logger, so it can be turned on with an env var? Even better, we can have our users turn that on without having to change the code.
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.
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.
It probably breaks if you add it as an instance variable, but you can always create a new one as a local variable for this function and then ditch it.
export class FunctionSignatureDecoder { | ||
constructor(private name: string, private parameters: ABIParameter[]) {} |
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 know this is a matter of personal preference, but I prefer to export plain functions rather than classes with a "do" method. A user of this API just wants to decodeFunctionSignature(name, parameters)
, and doesn't care about the FunctionSignatureDecoder
that's doing the job.
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.
Added decodeFunctionSignature
to handle it
@@ -355,7 +337,7 @@ contract NativeToken { | |||
// Note 2: Having it in all the contracts gives us the ability to compute the note hash and nullifier differently for different kind of notes. | |||
unconstrained fn compute_note_hash_and_nullifier(contract_address: Field, nonce: Field, storage_slot: Field, preimage: [Field; VALUE_NOTE_LEN]) -> [Field; 4] { | |||
let note_header = NoteHeader { contract_address, nonce, storage_slot }; | |||
if (storage_slot == 2) { | |||
if (storage_slot == 3) { |
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.
Curious how you found this
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.
Had failures because of missing compute_note_hash_and_nullifier
so debugged from there and saw that the slot did not match what was in storage. The actual issue was then the different selectors 😬 leading to the loop.
* @returns The function signature. | ||
*/ | ||
public decode(): string { | ||
const hmm = this.parameters.map(param => this.decodeParameter(param.type)); |
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.
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.
guy skibbidy
cb42729
to
6732d6f
Compare
@@ -815,7 +819,7 @@ describe('Private Execution test suite', () => { | |||
); | |||
|
|||
expect(result.enqueuedPublicFunctionCalls).toHaveLength(1); | |||
expect(result.enqueuedPublicFunctionCalls[0]).toEqual(publicCallRequest); | |||
expect(result.enqueuedPublicFunctionCalls[0].toBuffer()).toEqual(publicCallRequest.toBuffer()); |
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.
For some reason, the toEqual
was failing with the objects directly, even though they serialise to the same values 🤷
ffe1078
to
92c0b18
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>
Fixed #1990. Also adds an oracle to more easily compute selectors from inside the contracts for improved devex.
Checklist:
Remove the checklist to signal you've completed it. Enable auto-merge if the PR is ready to merge.