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(e2e): shielding and unshielding #915

Merged
merged 33 commits into from
Jul 5, 2023
Merged

feat(e2e): shielding and unshielding #915

merged 33 commits into from
Jul 5, 2023

Conversation

Maddiaa0
Copy link
Member

@Maddiaa0 Maddiaa0 commented Jun 27, 2023

Description

part of #878

  • re-rolls noir sha256 stuff, as loops dont harm compile time anymore!
  • Moves public -> private stuff into the non native token as shielding and unshielding
  • Moves misc test stuff in public -> private into the test contract
  • Creates e2e test for shielding and un shielding again

Please provide a paragraph or two giving a summary of the change, including relevant motivation and context.

Checklist:

  • I have reviewed my diff in github, line by line.
  • Every change is related to the PR description.
  • I have linked this pull request to the issue(s) that it resolves.
  • There are no unexpected formatting changes, superfluous debug logs, or commented-out code.
  • The branch has been merged or rebased against the head of its merge target.
  • I'm happy for the PR to be merged at the reviewer's next convenience.

@Maddiaa0 Maddiaa0 changed the title feat: shielding and unshielding feat(e2e): shielding and unshielding Jun 27, 2023
@rahul-kothari
Copy link
Contributor

Btw this might help reduce some copy pasta - #916

@Maddiaa0 Maddiaa0 marked this pull request as ready for review June 27, 2023 23:54
import { DebugLogger } from '@aztec/foundation/log';
import { pointToPublicKey, setup } from './utils.js';
import { expectStorageSlot, pointToPublicKey, setup } from './utils.js';
Copy link
Contributor

Choose a reason for hiding this comment

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

could we rename this function to expectL2StorageSlotValue to make it clearer?

@@ -244,15 +244,15 @@ export function delay(ms: number): Promise<void> {
*/
export async function calculateStorageSlot(slot: bigint, key: Fr): Promise<Fr> {
Copy link
Contributor

Choose a reason for hiding this comment

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

can we rename this to calculateL2StorageSlotValue

secretHash: Field,
_padding: [Field; abi::MAX_ARGS - 2]
) {
// Create a commitment to the amount
Copy link
Contributor

Choose a reason for hiding this comment

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

Shouldn't we ensure that amount <= public_balances[msg.sender]?

Copy link
Member Author

Choose a reason for hiding this comment

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

That would leak the sender, also the amount is being minted from private, the hope is that this function would only be callable by a private function where this has been constrained in private

Copy link
Contributor

Choose a reason for hiding this comment

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

Aggreing with rahul, its a public function, so you are already leaking and with the current balance being in public, how would it be constrained by the private function?

Seems like it is just a mint function right now as it effectively creates a commitment you can use for minting but it don't burn anything so just inflate supply.

initialContext.args = initialContext.args.push_array([amount, owner.x, owner.y]);

let sender_balance = balances.at(owner.x);
let (mut context, (note1, note2)) = sender_balance.get_2(initialContext);
Copy link
Contributor

Choose a reason for hiding this comment

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

for my understanding, why do we get 2 notes?

Copy link
Member Author

Choose a reason for hiding this comment

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

again this is arbitrary until we can have generics and slices

note2.validate(owner);

let sum = note1.value + note2.value;
assert(sum as u64 >= amount as u64);
Copy link
Contributor

Choose a reason for hiding this comment

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

I saw as u120 in other noir files fwiw

Copy link
Member Author

Choose a reason for hiding this comment

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

Its arbitrary however i can increase it

hash_bytes[321] = callerOnL1_bytes[29];
hash_bytes[322] = callerOnL1_bytes[30];
hash_bytes[323] = callerOnL1_bytes[31];

Copy link
Member Author

Choose a reason for hiding this comment

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

Copy link
Contributor

Choose a reason for hiding this comment

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

As above, they don't need individual loops all of them as it is the same range 🤷

context = sender_balance.insert(context, change_note);
assert(emit_encrypted_log(inputs.call_context.storage_contract_address, sender_balance.storage_slot, change_note.owner, change_note) == 0);

let thisAddress = inputs.call_context.storage_contract_address;
Copy link
Member Author

Choose a reason for hiding this comment

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

@@ -511,7 +511,7 @@ WASM_EXPORT const char* abis__test_roundtrip_serialize_combined_accumulated_data

WASM_EXPORT const char* abis__test_roundtrip_serialize_signature(uint8_t const* input, uint32_t* size)
{
return as_string_output<NT::ecdsa_signature>(input, size);
return as_string_output<NT::schnorr_signature>(input, size);
Copy link
Contributor

Choose a reason for hiding this comment

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

why?

Copy link
Member Author

@Maddiaa0 Maddiaa0 Jul 3, 2023

Choose a reason for hiding this comment

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

This is just a merge commit i didnt do this (no idea why though)

hash_bytes[29 + 224] = fee_bytes[29];
hash_bytes[30 + 224] = fee_bytes[30];
hash_bytes[31 + 224] = fee_bytes[31];
for i in 0..32 {
Copy link
Contributor

Choose a reason for hiding this comment

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

jesseling-kronk-emperors-new-groove-its-all-coming-together-KEYEpIngcmXlHetDqz

But they don't need each their own loop, you could do it in the same one, same range for them all.

secretHash: Field,
_padding: [Field; abi::MAX_ARGS - 2]
) {
// Create a commitment to the amount
Copy link
Contributor

Choose a reason for hiding this comment

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

Aggreing with rahul, its a public function, so you are already leaking and with the current balance being in public, how would it be constrained by the private function?

Seems like it is just a mint function right now as it effectively creates a commitment you can use for minting but it don't burn anything so just inflate supply.

@@ -260,8 +260,8 @@ describe('ACIR public execution simulator', () => {
});

it('Should be able to create a commitment from the public context', async () => {
const publicToPrivateAbi = PublicToPrivateContractAbi.functions.find(f => f.name === 'mintFromPublicToPrivate')!;
const args = encodeArguments(publicToPrivateAbi, params);
const shieldAbi = NonNativeTokenContractAbi.functions.find(f => f.name === 'shield')!;
Copy link
Contributor

Choose a reason for hiding this comment

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

As noted later, this should handle the burning to not inflate.


await privateTx.isMined();
const privateReceipt = await privateTx.getReceipt();

expect(privateReceipt.status).toBe(TxStatus.MINED);
await expectBalance(owner, mintAmount);
}, 60_000);

// Unshield the tokens again, sending them to the same account, however this can be any account.
Copy link
Contributor

Choose a reason for hiding this comment

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

Before unshielding, can you add a test that check that the factual total supply is not inflated. Supply (private + public) should not increase.

await expectAztecStorageSlot(logger, aztecNode, contract, publicBalancesSlot, owner.toField(), 0n);

const balancesStorageSlot = new Fr(slot); // this value is manually set in the Noir contract
const mappingStorageSlot = new Fr(4n); // The pedersen domain separator for storage slot calculations.
const mappingStorageSlot = new Fr(slot); // this value is manually set in the Noir contract
const mappingStorageSlotSeparator = new Fr(4n); // The pedersen domain separator for storage slot calculations.
Copy link
Contributor

Choose a reason for hiding this comment

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

Do you know if this is a constant somewhere so we don't need a 4n to hold it together? 👀


const deployedContract = await deployContract();
await deployContract();
Copy link
Contributor

Choose a reason for hiding this comment

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

Before shielding, can you add a check to see that the supply matches the expected. Also should probably mint something, it seems strange that you can shield something, when there is nothing to shield.

hash_bytes[321] = callerOnL1_bytes[29];
hash_bytes[322] = callerOnL1_bytes[30];
hash_bytes[323] = callerOnL1_bytes[31];

Copy link
Contributor

Choose a reason for hiding this comment

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

As above, they don't need individual loops all of them as it is the same range 🤷

@Maddiaa0 Maddiaa0 requested a review from LHerskind July 4, 2023 17:34
Copy link
Contributor

@LHerskind LHerskind left a comment

Choose a reason for hiding this comment

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

For addUnshieldedBalance we need to think about access control. Right now, anyone can call it and mint tokens. We would need to have either be able to constrain that it could only be called by the contract itself, in which case msg.sender would need to be itself, but we don’t have that because it is a private function call. Think you need to insert a commitment and then spend that commitment as part of the public execution afterwards. Have similar issue in the lending for, access control is pain.

let sender_balance = public_balances.at(sender);
let current_sender_balance = sender_balance.read();

if (current_sender_balance as u120) > (amount as u120) {
Copy link
Contributor

Choose a reason for hiding this comment

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

When amount >= current_sender_balance seems like I would just create the commitment without spending any funds 😬

We should assert that current_sender_balance <= amount and then we can decrease afterwards.

Copy link
Member Author

Choose a reason for hiding this comment

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

ah good spot, this was lazy

@Maddiaa0 Maddiaa0 mentioned this pull request Jul 5, 2023
6 tasks
@Maddiaa0 Maddiaa0 changed the base branch from master to md/noir-libs July 5, 2023 10:00
@@ -148,7 +151,7 @@ TEST_F(base_rollup_tests, native_no_new_contract_leafs)
ASSERT_EQ(outputs.start_contract_tree_snapshot, expectedStartContractTreeSnapshot);
ASSERT_EQ(outputs.end_contract_tree_snapshot, expectedEndContractTreeSnapshot);
ASSERT_EQ(outputs.start_contract_tree_snapshot, emptyInputs.start_contract_tree_snapshot);
ASSERT_FALSE(builder.failed());
ASSERT_FALSE(builder.failed()) << builder.failure_msgs;
Copy link
Contributor

Choose a reason for hiding this comment

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

@jeanmon is this your << builder.failure_msgs? There is a few of them that have sneaked into the codebase, is this on purpose?

Copy link
Contributor

Choose a reason for hiding this comment

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

Yes this is on purpose. This the way gtest works (or at least my understanding of it) to log additional information when a test is failing.

Copy link
Contributor

Choose a reason for hiding this comment

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

@LHerskind Do you see any issue with this?

Copy link
Contributor

Choose a reason for hiding this comment

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

Were just that it is extra print things that we don't expect to normally need, but if only when it fails, think is probably fine 👍. Thanks for clarifying

Copy link
Contributor

Choose a reason for hiding this comment

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

Exactly.

Base automatically changed from md/noir-libs to master July 5, 2023 12:52
@Maddiaa0 Maddiaa0 enabled auto-merge (squash) July 5, 2023 12:55
@Maddiaa0 Maddiaa0 disabled auto-merge July 5, 2023 12:55
@Maddiaa0 Maddiaa0 enabled auto-merge (squash) July 5, 2023 13:02
@Maddiaa0 Maddiaa0 merged commit c1439a3 into master Jul 5, 2023
@Maddiaa0 Maddiaa0 deleted the md/878-unshield branch July 5, 2023 13:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants