fix: update function selector to be 4 bytes#293
Conversation
|
Just a couple of things, doesn't the TS pad the selector to 32 bytes? This is done in contract_tree.ts. However, we should switch it to use the new FunctionLeafPreImage type in TS for serialisation and then keep the 2 types (TS and C++) in sync. |
|
@PhilWindle I've added a commit that addresses your comment. |
| if (fnLeaf.length !== 32 + 1 + 32 + 32) throw new Error(`Invalid length for function leaf`); | ||
| export async function computeFunctionLeaf(wasm: CircuitsWasm, fnLeaf: FunctionLeafPreimage) { | ||
| const fnLeafBuf = fnLeaf.toBuffer(); | ||
| if (fnLeafBuf.length !== 32 + 1 + 32 + 32) throw new Error(`Invalid length for function leaf`); |
There was a problem hiding this comment.
Lets at least make '32 + 1 + 32 + 32' a static of FunctionLeafPreImage.
There was a problem hiding this comment.
so this was necessary before since we were using a plain buffer as input, think it could be removed now, right?
also it should be 4 + 1 + 32 + 32 now
|
Is 4 bytes sufficient for the selector? Ethereum uses it, but it is pretty easy to make collisions. How annoying devex would collisions give in our case? @iAmMichaelConnor or @kevaundray do you have input on this? |
I think 4 bytes is pretty small -- you only need 2^16 function signatures before you get a collision. If possible, I'd opt for 8 bytes so you need 2^32 function signatures for a collision |
| @@ -50,10 +51,13 @@ async function generateFunctionLeaves(functions: ContractFunctionDao[], wasm: Ci | |||
| const vkHash = await hashVKStr(f.verificationKey!, wasm); | |||
| const acirHash = keccak(Buffer.from(f.bytecode, 'hex')); | |||
| // TODO: selector is currently padded to 32 bytes in CBINDS, check this. | |||
There was a problem hiding this comment.
Lets remove this out of date comment
| return new FunctionLeafPreimage(reader.readBytes(4), reader.readBoolean(), reader.readFr(), reader.readFr()); | ||
| } | ||
|
|
||
| static verifyBufferSize(buffer: Buffer): boolean { |
There was a problem hiding this comment.
I don't think this is needed now is it? Let's remove it.
There was a problem hiding this comment.
It is being used abis.ts line 92. Can we remove that check too? I think its still necessary as we are using a plain buffer as the input?
There was a problem hiding this comment.
I guess I just find it a bit messy. What do you think of sanity checking the length of the buffer inside toBuffer and throwing if it's wrong? It should be impossible to construct an instance of this class such that toBuffer returns a buffer of the wrong size so I think it's fair to throw. Then everything is encapsulated in this class. And lets create a readonly field in the class with the expected length.
refactor: use single method to perform length check refactor: use single method to perform length check
2c7fd7d to
c3315d3
Compare
| const fnLeafBuf = fnLeaf.toBuffer(); | ||
| wasm.call('pedersen__init'); | ||
| return Fr.fromBuffer(await wasmAsyncCall(wasm, 'abis__compute_function_leaf', { toBuffer: () => fnLeaf }, 32)); | ||
| return Fr.fromBuffer(await wasmAsyncCall(wasm, 'abis__compute_function_leaf', { toBuffer: () => fnLeafBuf }, 32)); |
There was a problem hiding this comment.
We can just pass fnLeaf into here can't we?
Description
Serialisation issues were being caused by the function selector in the function tree leaf being 4 bytes in typescript and 32 bytes in the circuits. This pr fixes this
Checklist: