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

refactor: purging portal addresses #5842

Merged
merged 10 commits into from
Apr 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions avm-transpiler/src/opcodes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ pub enum AvmOpcode {
ADDRESS,
STORAGEADDRESS,
SENDER,
PORTAL,
FEEPERL1GAS,
FEEPERL2GAS,
FEEPERDAGAS,
Expand Down Expand Up @@ -102,7 +101,6 @@ impl AvmOpcode {
AvmOpcode::ADDRESS => "ADDRESS",
AvmOpcode::STORAGEADDRESS => "STORAGEADDRESS",
AvmOpcode::SENDER => "SENDER",
AvmOpcode::PORTAL => "PORTAL",
AvmOpcode::FEEPERL1GAS => "FEEPERL1GAS",
AvmOpcode::FEEPERL2GAS => "FEEPERL2GAS",
AvmOpcode::FEEPERDAGAS => "FEEPERDAGAS",
Expand Down
1 change: 0 additions & 1 deletion avm-transpiler/src/transpile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -744,7 +744,6 @@ fn handle_getter_instruction(
"avmOpcodeAddress" => AvmOpcode::ADDRESS,
"avmOpcodeStorageAddress" => AvmOpcode::STORAGEADDRESS,
"avmOpcodeSender" => AvmOpcode::SENDER,
"avmOpcodePortal" => AvmOpcode::PORTAL,
"avmOpcodeFeePerL1Gas" => AvmOpcode::FEEPERL1GAS,
"avmOpcodeFeePerL2Gas" => AvmOpcode::FEEPERL2GAS,
"avmOpcodeFeePerDaGas" => AvmOpcode::FEEPERDAGAS,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ enum class OpCode : uint8_t {
ADDRESS,
STORAGEADDRESS,
SENDER,
PORTAL,
FEEPERL1GAS,
FEEPERL2GAS,
FEEPERDAGAS,
Expand Down
3 changes: 1 addition & 2 deletions docs/docs/developers/aztecjs/guides/call_view_function.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ Call the `simulate` function on the typescript contract wrapper like this:
#include_code simulate_function yarn-project/end-to-end/src/composed/docs_examples.test.ts typescript

:::info Note

- If the simulated function is `unconstrained` you will get a properly typed value.
- If the simulated function is `public` or `private` it will return a Field array of size 4.
:::
:::
Original file line number Diff line number Diff line change
Expand Up @@ -88,14 +88,12 @@ Its arguments are `PXE` client and contract constructor arguments.

Additionally the `.send()` method can have a few optional arguments too, which are specified in an optional object:

- `portalContract?: EthAddress`: The L1 portal address to link the contract to. See the section on [Portals to learn more about them](../writing_contracts/portals/portals.md).
- `contractAddressSalt?: Fr`: A salt which is one of the inputs when computing a contract address of the contract to be deployed.
By default is set to a random value.
Set it, if you need a deterministic contract address (same functionality as Ethereum's `CREATE2` opcode).

```ts
const tx = ExampleContract.deploy(pxe).send({
portalContract: EthAddress.from("0x1234..."),
contractAddressSalt: new Fr(3n),
});
```
Expand Down
23 changes: 8 additions & 15 deletions docs/docs/developers/contracts/references/history_lib_reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -133,18 +133,11 @@ This proves that a contract exists in, ie had been deployed before or in, a cert

`prove_contract_inclusion_at` takes 7 parameters:

| Name | Type | Description |
| ----------------------- | -------------- | -------------------------------------------------- |
| deployer_public_key | GrumpkinPoint | Public key of the contract deployer |
| contract_address_salt | Field | Unique identifier for the contract's address |
| function_tree_root | Field | Root of the contract's function tree |
| constructor_hash | Field | Hash of the contract's constructor |
| portal_contract_address | EthAddress | Ethereum address of the associated portal contract |
| block_number | u32 | Block number for proof verification |
| context | PrivateContext | Private context |

If there is no associated portal contract, you can use a zero Ethereum address:

```ts
new EthAddress(Buffer.alloc(EthAddress.SIZE_IN_BYTES));
```
| Name | Type | Description |
| --------------------- | -------------- | -------------------------------------------- |
| deployer_public_key | GrumpkinPoint | Public key of the contract deployer |
| contract_address_salt | Field | Unique identifier for the contract's address |
| function_tree_root | Field | Root of the contract's function tree |
| constructor_hash | Field | Hash of the contract's constructor |
| block_number | u32 | Block number for proof verification |
| context | PrivateContext | Private context |
Original file line number Diff line number Diff line change
Expand Up @@ -91,10 +91,9 @@ Unencrypted events are events which can be read by anyone.
They can be emitted by both public and private functions.

:::danger

- Emitting unencrypted events from private function is a significant privacy leak and it should be considered by the developer whether it is acceptable.
- Unencrypted events are currently **NOT** linked to the contract emitting them, so it is practically a [`debug_log`](../oracles/main.md#a-few-useful-inbuilt-oracles).
:::
:::

### Call emit_unencrypted_log

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,7 @@ The call context contains information about the current call being made:

- This value is the address of the current context's contract address. This value will be the value of the current contract that is being executed except for when the current call is a delegate call (Warning: This is yet to be implemented). In this case the value will be that of the sending contract.

3. Portal Contract Address
- This value stores the current contract's linked [portal contract](../portals/portals.md) address. As a quick recap, this value is the value of the contracts related ethereum l1 contract address, and will be the recipient of any messages that are created by this contract.
4. Flags
3. Flags
- Furthermore there are a series of flags that are stored within the application context:
- is_delegate_call: Denotes whether the current call is a delegate call. If true, then the storage contract address will be the address of the sender.
- is_static_call: This will be set if and only if the current call is a static call. In a static call, state changing altering operations are not allowed.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,9 @@ title: How to deploy a contract with a Portal
---

- Deploy to L1 using Viem, Foundry or your preferred tool;
- Deploy to L2 passing in the address of the L1 portal as its portal contract;
- Deploy to L2 and supply the L1 portal as an argument so you can store it in the contract;
```typescript
const deploymentTx = Contract.deploy(wallet).send({
portalContract: tokenPortalAddress,
});
const deploymentTx = Contract.deploy(wallet, tokenPortalAddress).send();
```
- Initialize l1 with l2 address for access control.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@
title: Portals
---

A portal is the point of contact between L1 and a specific contract on Aztec. For applications such as token bridges, this is the point where the tokens are held on L1 while used in L2.
A portal is a point of contact between L1 and a contract on Aztec. For applications such as token bridges, this is the point where the tokens are held on L1 while used in L2.

As outlined in [Communication](../../../../learn/concepts/communication/cross_chain_calls.md), an Aztec L2 contract is linked to _ONE_ L1 address at time of deployment (specified by the developer). This L1 address is the only address that can send messages to that specific L2 contract, and the only address that can receive messages sent from the L2 contract to L1. Note, that a portal don't actually need to be a contract, it could be any address on L1. We say that an Aztec contract is attached to a portal.
As outlined in [Communication](../../../../learn/concepts/communication/cross_chain_calls.md), an Aztec L2 contract is linked to _ONE_ L1 address at time of deployment (specified by the developer). This L1 address is the only address that can send messages to that specific L2 contract, and the only address that can receive messages sent from the L2 contract to L1. Note, that a portal doesn't actually need to be a contract, it could be any address on L1.
2 changes: 1 addition & 1 deletion docs/docs/developers/debugging/aztecnr-errors.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ To address the error. find the line in the contract that is throwing the error a

This error occurs when you are trying to interact with a smart contract via an Private Execution Environment (PXE) that does not have the necessary information to execute a transaction.

To execute a transaction, the PXE needs to know the complete address of a contract, portal address (if portal is used) and contract artifacts.
To execute a transaction, the PXE needs to know the complete address of a contract and contract artifacts.

To address the error, add the contract to the PXE by calling [`pxe.addContracts(...)`](../../apis/pxe/interfaces/PXE.md#addcontracts).

Expand Down
13 changes: 7 additions & 6 deletions docs/docs/developers/tutorials/token_portal/minting_on_aztec.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,13 @@ The `claim_public` function enables anyone to consume the message on the user's
**What’s happening here?**

1. We first recompute the L1->L2 message content by calling `get_mint_public_content_hash()`. Note that the method does exactly the same as what the TokenPortal contract does in `depositToAztecPublic()` to create the content hash.
2. We then attempt to consume the L1->L2 message by passing the `msg_key`, the content hash, and the "secret". Since we are depositing to Aztec publicly, this secret is public, anyone can know this and is usually 0.
- `context.consume_l1_to_l2_message()` takes in the content_hash and secret to recreate the original message. The L1 to L2 message consists of:
- Sender - who on L1 sent the message + chain ID of L1. The context variable knows the portal address on L1 and adds that
- Recipient - i.e. this aztec contract address which is consuming the message + the current version of the aztec rollup.
- The content - which is reconstructed in the `get_mint_public_content_hash()`
- Note that the `content_hash` requires `to`, `amount` and `canceller`. If a malicious user tries to mint tokens to their address by changing the to address, the content hash will be different to what the token portal had calculated on L1 and the `msg_Key` will also be different, thus preventing the L1->L2 message from being consumed. This is why we add these parameters into the content.
2. We then attempt to consume the L1->L2 message. Since we are depositing to Aztec publicly, all of the inputs are public.
- `context.consume_l1_to_l2_message()` takes in the few parameters:
- `content_hash`: The content - which is reconstructed in the `get_mint_public_content_hash()`
- `secret`: The secret used for consumption, often 0 for public messages
- `sender`: Who on L1 sent the message. Which should match the stored `portal_address` in our case as we only want to allow messages from a specific sender.
- `message_leaf_index`: The index in the message tree of the message.
- Note that the `content_hash` requires `to` and `amount`. If a malicious user tries to mint tokens to their address by changing the to address, the content hash will be different to what the token portal had calculated on L1 and thus not be in the tree, failing the consumption. This is why we add these parameters into the content.
3. Then we call `Token::at(storage.token.read()).mint_public()` to mint the tokens to the to address.

## Private flow
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ The `exit_to_l1_public` function enables anyone to withdraw their L2 tokens back

1. Like with our deposit function, we need to create the L2 to L1 message. The content is the _amount_ to burn, the recipient address, and who can execute the withdraw on the L1 portal on behalf of the user. It can be `0x0` for anyone, or a specified address.
2. `context.message_portal()` passes this content to the [kernel circuit](../../../learn/concepts/circuits/kernels/public_kernel.md) which creates the proof for the transaction. The kernel circuit then adds the sender (the L2 address of the bridge + version of aztec) and the recipient (the portal to the L2 address + the chain ID of L1) under the hood, to create the message which gets added as part of the transaction data published by the sequencer and is stored in the outbox for consumption.
3. Finally, you also burn the tokens on L2! Note that it burning is done at the end to follow the check effects interaction pattern. Note that the caller has to first approve the bridge contract to burn tokens on its behalf. Refer to [burn_public function on the token contract](../writing_token_contract.md#burn_public). The nonce parameter refers to the approval message that the user creates - also refer to [authorizing token spends here](../writing_token_contract.md#authorizing-token-spends).
3. The `context.message_portal()` takes the recipient and content as input, and will insert a message into the outbox. We set the recipient to be the portal address read from storage of the contract.
4. Finally, you also burn the tokens on L2! Note that it burning is done at the end to follow the check effects interaction pattern. Note that the caller has to first approve the bridge contract to burn tokens on its behalf. Refer to [burn_public function on the token contract](../writing_token_contract.md#burn_public). The nonce parameter refers to the approval message that the user creates - also refer to [authorizing token spends here](../writing_token_contract.md#authorizing-token-spends).
- We burn the tokens from the `msg_sender()`. Otherwise, a malicious user could burn someone else’s tokens and mint tokens on L1 to themselves. One could add another approval flow on the bridge but that might make it complex for other applications to call the bridge.

## Withdrawing Privately
Expand Down Expand Up @@ -58,7 +59,7 @@ Before we can compile and use the contract, we need to add two additional functi

We need a function that lets us read the token value. Paste this into `main.nr`:

#include_code read_token /noir-projects/noir-contracts/contracts/token_bridge_contract/src/main.nr rust
#include_code get_token /noir-projects/noir-contracts/contracts/token_bridge_contract/src/main.nr rust

## Compile code

Expand Down
28 changes: 27 additions & 1 deletion docs/docs/misc/migration_notes.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,33 @@ Aztec is in full-speed development. Literally every version breaks compatibility

## 0.36.0

## [Aztec.nr & js] Portal addresses

Deployments have been modified. No longer are portal addresses treated as a special class, being immutably set on creation of a contract. They are no longer passed in differently compared to the other variables and instead should be implemented using usual storage by those who require it. One should use the storage that matches the usecase - likely shared storage to support private and public.

This means that you will likely add the portal as a constructor argument
Comment on lines +14 to +15
Copy link
Contributor

Choose a reason for hiding this comment

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

I'd add this here:

struct Storage {
+   portal_address: SharedImmutable<AztecAddress>,
}

Can't do a proper gh suggestion since the code formatting screws up with the suggestion formatting 🤦

Copy link
Contributor Author

Choose a reason for hiding this comment

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

If done in GH, you can write "suggestion" as the language.


```diff
- fn constructor(token: AztecAddress) {
- storage.token.write(token);
- }
+ struct Storage {
...
+ portal_address: SharedImmutable<AztecAddress>,
+ }
+ fn constructor(token: AztecAddress, portal_address: EthAddress) {
+ storage.token.write(token);
+ storage.portal_address.initialize(portal_address);
+ }
```

And read it from storage whenever needed instead of from the context.

```diff
- context.this_portal_address(),
+ storage.portal_address.read_public(),
```

### [Aztec.nr] Oracles

Oracle `get_nullifier_secret_key` was renamed to `get_app_nullifier_secret_key` and `request_nullifier_secret_key` function on PrivateContext was renamed as `request_app_nullifier_secret_key`.
Expand Down Expand Up @@ -101,7 +128,6 @@ and change the call to `get_portal_address`
+ let portal_address = SomeContract::at(contract_address).get_portal_address().call(&mut context);
```


### [Aztec.nr] Required gas limits for public-to-public calls

When calling a public function from another public function using the `call_public_function` method, you must now specify how much gas you're allocating to the nested call. This will later allow you to limit the amount of gas consumed by the nested call, and handle any out of gas errors.
Expand Down
2 changes: 1 addition & 1 deletion docs/docs/protocol-specs/contract-deployment/classes.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ Read the following discussions for additional context:
- [Abstracting contract deployment](https://forum.aztec.network/t/proposal-abstracting-contract-deployment/2576)
- [Implementing contract upgrades](https://forum.aztec.network/t/implementing-contract-upgrades/2570)
- [Contract classes, upgrades, and default accounts](https://forum.aztec.network/t/contract-classes-upgrades-and-default-accounts/433)
:::
:::

## `ContractClass`

Expand Down
6 changes: 1 addition & 5 deletions docs/docs/protocol-specs/contract-deployment/instances.md
Original file line number Diff line number Diff line change
Expand Up @@ -110,16 +110,13 @@ fn deploy (
salt: Field,
contract_class_id: Field,
initialization_hash: Field,
portal_contract_address: Field,
public_keys_hash: Field,
universal_deploy?: boolean,
)
let contract_class_registerer: Contract = ContractClassRegisterer::at(CONTRACT_CLASS_REGISTERER_ADDRESS);

assert(nullifier_exists(silo(contract_class_id, contract_class_registerer.address)));

assert(is_valid_eth_address(portal_contract_address));

let deployer: Address = if universal_deploy { 0 } else { msg_sender };
let version: Field = 1;

Expand All @@ -129,13 +126,12 @@ fn deploy (
deployer,
contract_class_id,
initialization_hash,
portal_contract_address,
public_keys_hash
);

emit_nullifier(address);

emit_unencrypted_event(ContractInstanceDeployed::new(address, version, salt, contract_class_id, initialization_hash, portal_contract_address, public_keys_hash));
emit_unencrypted_event(ContractInstanceDeployed::new(address, version, salt, contract_class_id, initialization_hash, public_keys_hash));
```

> See [address](../addresses-and-keys/address.md) for `address_crh`.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ From distributed systems, the _security_ of a protocol or system is defined by:

- **Liveness**: Eventually something good will happen.
- **Safety**: Nothing bad will happen.
:::
:::

In the context of blockchain, this _security_ is defined by the confirmation rule, while this can be chosen individually by the user, our validating light node (L1 bridge) can be seen as a user, after all, it's "just" another node.
For the case of a validity proof based blockchain, a good confirmation rule should satisfy the following sub-properties (inspired by [Sreeram's framing](https://twitter.com/sreeramkannan/status/1683735050897207296)):
Expand Down
6 changes: 2 additions & 4 deletions docs/docs/protocol-specs/decentralization/block-production.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,11 @@ We should probably introduce the PXE somewhere
| RAM | 32gb | 64gb |

:::info Estimates

- **CPU**: Help
- **Network**: 40KB for a transaction with proof (see [P2P network](./p2p-network.md#network-bandwidth)). Assuming gossiping grows the data upload/download 10x, ~400KB per tx. With 10 tx/s that's 4MB/s or 32mb/s.
- **Storage**: [~1548 bytes per transaction](../data-publication-and-availability/index.md#aztec-specific-data) + tree overhead, ~ 0.4 TB per year.
- **RAM**: Help
:::
:::

### Sequencers

Expand Down Expand Up @@ -106,14 +105,13 @@ Anyone ->> Network: eligible as a sequencer
## Block production

:::danger **TODO**

- The diagram needs to be updated with respect to "VRF".
- In **Prover commitment** phase, it is not said what the signature is used for. I'm expecting that it is used to allow the prover to publish the message on behalf of the sequencer, but it is not made clear.
- In **Backup** phase, would be useful if we add a comment on the duration
- In Diagram
- add a dedicated timeline from the block production's PoV
- get rid of "pre-confirmed"
:::
:::

![Governance Summary Image](/img/protocol-specs/decentralization/Aztec-Block-Production-1.png)

Expand Down
Loading
Loading