-
Notifications
You must be signed in to change notification settings - Fork 294
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: add inclusion check l1->l2 #4141
Changes from 5 commits
5d98cbe
9cd9fcf
abbe958
00122a4
f68a2d6
a2a9faf
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
import { Note, PackedArguments, TxExecutionRequest } from '@aztec/circuit-types'; | ||
import { L1ToL2Message, Note, PackedArguments, TxExecutionRequest } from '@aztec/circuit-types'; | ||
import { | ||
BlockHeader, | ||
CallContext, | ||
|
@@ -81,7 +81,7 @@ describe('Private Execution test suite', () => { | |
l1ToL2Messages: L1_TO_L2_MSG_TREE_HEIGHT, | ||
}; | ||
|
||
const trees: { [name: keyof typeof treeHeights]: AppendOnlyTree } = {}; | ||
let trees: { [name: keyof typeof treeHeights]: AppendOnlyTree } = {}; | ||
const txContextFields: FieldsOf<TxContext> = { | ||
isContractDeploymentTx: false, | ||
isFeePaymentTx: false, | ||
|
@@ -138,7 +138,7 @@ describe('Private Execution test suite', () => { | |
await trees[name].appendLeaves(leaves.map(l => l.toBuffer())); | ||
|
||
// Update root. | ||
const newRoot = trees[name].getRoot(false); | ||
const newRoot = trees[name].getRoot(true); | ||
const prevRoots = blockHeader.toBuffer(); | ||
const rootIndex = name === 'noteHash' ? 0 : 32 * 3; | ||
const newRoots = Buffer.concat([prevRoots.subarray(0, rootIndex), newRoot, prevRoots.subarray(rootIndex + 32)]); | ||
|
@@ -160,6 +160,7 @@ describe('Private Execution test suite', () => { | |
}); | ||
|
||
beforeEach(() => { | ||
trees = {}; | ||
oracle = mock<DBOracle>(); | ||
oracle.getSecretKey.mockImplementation((contractAddress: AztecAddress, pubKey: PublicKey) => { | ||
if (pubKey.equals(ownerCompleteAddress.publicKey)) { | ||
|
@@ -453,53 +454,250 @@ describe('Private Execution test suite', () => { | |
}); | ||
}); | ||
|
||
it('Should be able to consume a dummy cross chain message', async () => { | ||
const bridgedAmount = 100n; | ||
describe('L1 to L2', () => { | ||
const artifact = getFunctionArtifact(TestContractArtifact, 'consume_mint_private_message'); | ||
const canceller = EthAddress.random(); | ||
let bridgedAmount = 100n; | ||
|
||
const secretForL1ToL2MessageConsumption = new Fr(1n); | ||
const secretHashForRedeemingNotes = new Fr(2n); | ||
const canceller = EthAddress.random(); | ||
const preimage = buildL1ToL2Message( | ||
getFunctionSelector('mint_private(bytes32,uint256,address)').substring(2), | ||
[secretHashForRedeemingNotes, new Fr(bridgedAmount), canceller.toField()], | ||
contractAddress, | ||
secretForL1ToL2MessageConsumption, | ||
); | ||
let secretForL1ToL2MessageConsumption = new Fr(1n); | ||
|
||
let ccMsgRecipient: AztecAddress | undefined; | ||
let ccMsgSender: EthAddress | undefined; | ||
let messageKey: Fr | undefined; | ||
|
||
let preimage: L1ToL2Message; | ||
|
||
let args: Fr[]; | ||
|
||
// WE likely need to | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. half comment? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ye, will delete it. |
||
|
||
// stub message key | ||
const messageKey = Fr.random(); | ||
const tree = await insertLeaves([messageKey], 'l1ToL2Messages'); | ||
beforeEach(() => { | ||
bridgedAmount = 100n; | ||
secretForL1ToL2MessageConsumption = new Fr(2n); | ||
|
||
oracle.getL1ToL2Message.mockImplementation(async () => { | ||
return Promise.resolve({ | ||
message: preimage.toFieldArray(), | ||
index: 0n, | ||
siblingPath: (await tree.getSiblingPath(0n, false)).toFieldArray(), | ||
ccMsgRecipient = undefined; | ||
ccMsgSender = undefined; | ||
messageKey = undefined; | ||
}); | ||
|
||
const computePreimage = () => | ||
buildL1ToL2Message( | ||
getFunctionSelector('mint_private(bytes32,uint256,address)').substring(2), | ||
[secretHashForRedeemingNotes, new Fr(bridgedAmount), canceller.toField()], | ||
ccMsgRecipient ?? contractAddress, | ||
secretForL1ToL2MessageConsumption, | ||
); | ||
|
||
const computeArgs = () => | ||
encodeArguments(artifact, [ | ||
secretHashForRedeemingNotes, | ||
bridgedAmount, | ||
canceller.toField(), | ||
messageKey ?? preimage.hash(), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nice! Think previously this was just There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ye, there were no real check seeing that what you were requesting was also what it responded with. So you could ask for key a and it give you b and it did not check it. |
||
secretForL1ToL2MessageConsumption, | ||
]); | ||
|
||
const mockOracles = async () => { | ||
const tree = await insertLeaves([messageKey ?? preimage.hash()], 'l1ToL2Messages'); | ||
oracle.getL1ToL2Message.mockImplementation(async () => { | ||
return Promise.resolve({ | ||
message: preimage.toFieldArray(), | ||
index: 0n, | ||
siblingPath: (await tree.getSiblingPath(0n, false)).toFieldArray(), | ||
}); | ||
}); | ||
}; | ||
|
||
it('Should be able to consume a dummy cross chain message', async () => { | ||
preimage = computePreimage(); | ||
|
||
args = computeArgs(); | ||
|
||
await mockOracles(); | ||
// Update state | ||
oracle.getBlockHeader.mockResolvedValue(blockHeader); | ||
|
||
const result = await runSimulator({ | ||
contractAddress, | ||
artifact, | ||
args, | ||
portalContractAddress: ccMsgSender ?? preimage.sender.sender, | ||
txContext: { version: new Fr(1n), chainId: new Fr(1n) }, | ||
}); | ||
|
||
// Check a nullifier has been inserted | ||
const newNullifiers = sideEffectArrayToValueArray( | ||
nonEmptySideEffects(result.callStackItem.publicInputs.newNullifiers), | ||
); | ||
|
||
expect(newNullifiers).toHaveLength(1); | ||
}); | ||
|
||
const args = [ | ||
secretHashForRedeemingNotes, | ||
bridgedAmount, | ||
canceller.toField(), | ||
messageKey, | ||
secretForL1ToL2MessageConsumption, | ||
]; | ||
const result = await runSimulator({ | ||
contractAddress, | ||
artifact, | ||
args, | ||
portalContractAddress: preimage.sender.sender, | ||
txContext: { version: new Fr(1n), chainId: new Fr(1n) }, | ||
it('Message not matching requested key', async () => { | ||
messageKey = Fr.random(); | ||
|
||
preimage = computePreimage(); | ||
|
||
args = computeArgs(); | ||
|
||
await mockOracles(); | ||
// Update state | ||
oracle.getBlockHeader.mockResolvedValue(blockHeader); | ||
|
||
await expect( | ||
runSimulator({ | ||
contractAddress, | ||
artifact, | ||
args, | ||
portalContractAddress: ccMsgSender ?? preimage.sender.sender, | ||
txContext: { version: new Fr(1n), chainId: new Fr(1n) }, | ||
}), | ||
).rejects.toThrowError('Message not matching requested key'); | ||
}); | ||
|
||
// Check a nullifier has been inserted | ||
const newNullifiers = sideEffectArrayToValueArray( | ||
nonEmptySideEffects(result.callStackItem.publicInputs.newNullifiers), | ||
); | ||
it('Invalid membership proof', async () => { | ||
preimage = computePreimage(); | ||
|
||
expect(newNullifiers).toHaveLength(1); | ||
args = computeArgs(); | ||
|
||
await mockOracles(); | ||
|
||
await expect( | ||
runSimulator({ | ||
contractAddress, | ||
artifact, | ||
args, | ||
portalContractAddress: ccMsgSender ?? preimage.sender.sender, | ||
txContext: { version: new Fr(1n), chainId: new Fr(1n) }, | ||
}), | ||
).rejects.toThrowError('Message not in state'); | ||
}); | ||
|
||
it('Invalid recipient', async () => { | ||
ccMsgRecipient = AztecAddress.random(); | ||
|
||
preimage = computePreimage(); | ||
|
||
args = computeArgs(); | ||
|
||
await mockOracles(); | ||
// Update state | ||
oracle.getBlockHeader.mockResolvedValue(blockHeader); | ||
|
||
await expect( | ||
runSimulator({ | ||
contractAddress, | ||
artifact, | ||
args, | ||
portalContractAddress: ccMsgSender ?? preimage.sender.sender, | ||
txContext: { version: new Fr(1n), chainId: new Fr(1n) }, | ||
}), | ||
).rejects.toThrowError('Invalid recipient'); | ||
}); | ||
|
||
it('Invalid sender', async () => { | ||
ccMsgSender = EthAddress.random(); | ||
preimage = computePreimage(); | ||
|
||
args = computeArgs(); | ||
|
||
await mockOracles(); | ||
// Update state | ||
oracle.getBlockHeader.mockResolvedValue(blockHeader); | ||
|
||
await expect( | ||
runSimulator({ | ||
contractAddress, | ||
artifact, | ||
args, | ||
portalContractAddress: ccMsgSender ?? preimage.sender.sender, | ||
txContext: { version: new Fr(1n), chainId: new Fr(1n) }, | ||
}), | ||
).rejects.toThrowError('Invalid sender'); | ||
}); | ||
|
||
it('Invalid chainid', async () => { | ||
preimage = computePreimage(); | ||
|
||
args = computeArgs(); | ||
|
||
await mockOracles(); | ||
// Update state | ||
oracle.getBlockHeader.mockResolvedValue(blockHeader); | ||
|
||
await expect( | ||
runSimulator({ | ||
contractAddress, | ||
artifact, | ||
args, | ||
portalContractAddress: ccMsgSender ?? preimage.sender.sender, | ||
txContext: { version: new Fr(1n), chainId: new Fr(2n) }, | ||
}), | ||
).rejects.toThrowError('Invalid Chainid'); | ||
}); | ||
|
||
it('Invalid version', async () => { | ||
preimage = computePreimage(); | ||
|
||
args = computeArgs(); | ||
|
||
await mockOracles(); | ||
// Update state | ||
oracle.getBlockHeader.mockResolvedValue(blockHeader); | ||
|
||
await expect( | ||
runSimulator({ | ||
contractAddress, | ||
artifact, | ||
args, | ||
portalContractAddress: ccMsgSender ?? preimage.sender.sender, | ||
txContext: { version: new Fr(2n), chainId: new Fr(1n) }, | ||
}), | ||
).rejects.toThrowError('Invalid Version'); | ||
}); | ||
|
||
it('Invalid content', async () => { | ||
preimage = computePreimage(); | ||
|
||
bridgedAmount = bridgedAmount + 1n; // Invalid amount | ||
args = computeArgs(); | ||
|
||
await mockOracles(); | ||
// Update state | ||
oracle.getBlockHeader.mockResolvedValue(blockHeader); | ||
|
||
await expect( | ||
runSimulator({ | ||
contractAddress, | ||
artifact, | ||
args, | ||
portalContractAddress: ccMsgSender ?? preimage.sender.sender, | ||
txContext: { version: new Fr(1n), chainId: new Fr(1n) }, | ||
}), | ||
).rejects.toThrowError('Invalid Content'); | ||
}); | ||
|
||
it('Invalid Secret', async () => { | ||
preimage = computePreimage(); | ||
|
||
secretForL1ToL2MessageConsumption = Fr.random(); | ||
args = computeArgs(); | ||
|
||
await mockOracles(); | ||
// Update state | ||
oracle.getBlockHeader.mockResolvedValue(blockHeader); | ||
|
||
await expect( | ||
runSimulator({ | ||
contractAddress, | ||
artifact, | ||
args, | ||
portalContractAddress: ccMsgSender ?? preimage.sender.sender, | ||
txContext: { version: new Fr(1n), chainId: new Fr(1n) }, | ||
}), | ||
).rejects.toThrowError('Invalid message secret'); | ||
}); | ||
}); | ||
|
||
it('Should be able to consume a dummy public to private message', async () => { | ||
|
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 is cc?
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.
cross-chain