Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
a3f0e0e
chore(docs): alpha-testnet versioning
signorecello Mar 25, 2025
1494310
trying to get previews back
signorecello Mar 25, 2025
bde446e
Merge remote-tracking branch 'origin' into zkpedro/docs_versioning
signorecello Mar 25, 2025
c7ad4cf
nit
signorecello Mar 25, 2025
6cce9ee
nit
signorecello Mar 26, 2025
8506555
nit
signorecello Mar 26, 2025
1ba25e1
nit
signorecello Mar 26, 2025
f5bc77d
trigger cache
signorecello Mar 26, 2025
599f031
trigger cache
signorecello Mar 26, 2025
62d5665
nit!
signorecello Mar 26, 2025
f41bfd5
nit
signorecello Mar 26, 2025
39614fa
moving tip to alpha testnet 3
signorecello Mar 26, 2025
35899ad
Merge remote-tracking branch 'origin' into zkpedro/docs_versioning
signorecello Mar 26, 2025
4e685ec
trigger CI
signorecello Mar 26, 2025
01666c0
Merge branch 'master' into zkpedro/docs_versioning
signorecello Mar 26, 2025
957b2f9
tsx stuff
signorecello Mar 26, 2025
7237d27
removing banner at the top for alpha-testnet
signorecello Mar 26, 2025
1ef7321
fix import macros
signorecello Mar 26, 2025
913af1c
fix import macros
signorecello Mar 26, 2025
678f8b7
moving to alpha testnet 4
signorecello Mar 27, 2025
e9b7ce1
Merge remote-tracking branch 'origin' into zkpedro/docs_versioning
signorecello Mar 27, 2025
43a049b
making versioned_docs rebuild cache too
signorecello Mar 27, 2025
6a73e60
fix static links creeping in from master
signorecello Mar 27, 2025
9789fff
too much cleaning
signorecello Mar 27, 2025
7588078
defaulting to master for undefined commit_tag (ex. this branch)
signorecello Mar 27, 2025
8ebf71d
Merge branch 'master' into zkpedro/docs_versioning
signorecello Apr 2, 2025
b756631
updating to latest versions
signorecello Apr 2, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
28 changes: 28 additions & 0 deletions .github/workflows/release-please.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,31 @@ jobs:
token: ${{ secrets.AZTEC_BOT_GITHUB_TOKEN }}
command: manifest
default-branch: ${{ env.BRANCH_NAME }}

update-docs:
name: Update docs
needs: [release-please]
if: ${{ needs.release-please.outputs.release-pr }}
runs-on: ubuntu-latest

steps:
- name: Checkout release branch
uses: actions/checkout@v4
with:
ref: ${{ env.BRANCH_NAME }}
token: ${{ secrets.AZTEC_BOT_GITHUB_TOKEN }}

- name: Cut a new version
working-directory: ./docs
run: yarn version ${{ env.BRANCH_NAME }}

- name: Configure git
run: |
git config --global user.email "tech@aztecprotocol.com"
git config --global user.name "AztecBot"

- name: Commit new documentation version
run: |
git add .
git commit -m "chore(docs): cut new docs version for tag ${{ env.BRANCH_NAME }}"
git push
2 changes: 2 additions & 0 deletions docs/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,5 @@ yarn-error.log*
/docs/developers/reference/smart_contract_reference/aztec-nr
/docs/docs/protocol-specs/public-vm/gen
test-results

versions.json
16 changes: 3 additions & 13 deletions docs/bootstrap.sh
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ cmd=${1:-}
hash=$(
cache_content_hash \
.rebuild_patterns \
$(find docs -type f -name "*.md" -exec grep '^#include_code' {} \; | \
awk '{ gsub("^/", "", $3); print "^" $3 }' | sort -u)
$(find docs versioned_docs -type f -name "*.md*" -exec grep '^#include_code' {} \; |
awk '{ print "^" $1 }' | sort -u)
)

if semver check $REF_NAME; then
Expand All @@ -27,13 +27,8 @@ function build_and_preview {
if cache_download docs-$hash.tar.gz; then
return
fi
rm -rf \
processed-docs \
processed-docs-cache \
docs/reference/developer_references/aztecjs \
docs/reference/developer_references/smart_contract_reference/aztec-nr
npm_install_deps
denoise "yarn docusaurus clear && yarn preprocess && yarn typedoc && scripts/move_processed.sh && yarn docusaurus build"
denoise "yarn build"
cache_upload docs-$hash.tar.gz build

if [ "${CI:-0}" -eq 1 ] && [ "$(arch)" == "amd64" ]; then
Expand All @@ -44,11 +39,6 @@ function build_and_preview {

# If we're an AMD64 CI run and have a PR, do a preview release.
function release_preview {
if [ -z "${NETLIFY_SITE_ID:-}" ] || [ -z "${NETLIFY_AUTH_TOKEN:-}" ]; then
echo "No netlify credentials available, skipping release preview."
return
fi

echo_header "docs release preview"

# Deploy and capture exit code and output.
Expand Down
2 changes: 1 addition & 1 deletion docs/docs/aztec/concepts/accounts/keys.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ To spend a note, the user computes a nullifier corresponding to this note. A nul

Address keys are used for account [address derivation](../accounts/index.md).

<Image img={require("/img/address_derivation.png")} />
<Image img={require("@site/static/img/address_derivation.png")} />

Address keys are a pair of keys `AddressPublicKey` and `address_sk` where `address_sk` is a scalar defined as `address_sk = pre_address + ivsk` and `AddressPublicKey` is an elliptic curve point defined as `AddressPublicKey = address_sk * G`. This is useful for encrypting notes for the recipient with only their address.

Expand Down
8 changes: 4 additions & 4 deletions docs/docs/aztec/concepts/advanced/authwit.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ When building DeFi or other smart contracts, it is often desired to interact wit

In the EVM world, this is often accomplished by having the user `approve` the protocol to transfer funds from their account, and then calling a `deposit` function on it afterwards.

<Image img={require("/img/authwit.png")} />
<Image img={require("@site/static/img/authwit.png")} />

This flow makes it rather simple for the application developer to implement the deposit function, but does not come without its downsides.

Expand All @@ -30,7 +30,7 @@ This can lead to a series of issues though, eg:

To avoid this, many protocols implement the `permit` flow, which uses a meta-transaction to let the user sign the approval off-chain, and pass it as an input to the `deposit` function, that way the user only has to send one transaction to make the deposit.

<Image img={require("/img/authwit2.png")} />
<Image img={require("@site/static/img/authwit2.png")} />

This is a great improvement to infinite approvals, but still has its own sets of issues. For example, if the user is using a smart-contract wallet (such as Argent or Gnosis Safe), they will not be able to sign the permit message since the usual signature validation does not work well with contracts. [EIP-1271](https://eips.ethereum.org/EIPS/eip-1271) was proposed to give contracts a way to emulate this, but it is not widely adopted.

Expand Down Expand Up @@ -90,7 +90,7 @@ This can be read as "defi is allowed to call token transfer function with the ar

With this out of the way, let's look at how this would work in the graph below. The exact contents of the witness will differ between implementations as mentioned before, but for the sake of simplicity you can think of it as a signature, which the account contract can then use to validate if it really should allow the action.

<Image img={require("/img/authwit3.png")} />
<Image img={require("@site/static/img/authwit3.png")} />

:::info Static call for AuthWit checks
The call to the account contract for checking authentication should be a static call, meaning that it cannot change state or make calls that change state. If this call is not static, it could be used to re-enter the flow and change the state of the contract.
Expand All @@ -104,7 +104,7 @@ The above flow could be re-entered at token transfer. It is mainly for show to i

As noted earlier, we could use the ERC20 standard for public. But this seems like a waste when we have the ability to try righting some wrongs. Instead, we can expand our AuthWit scheme to also work in public. This is actually quite simple, instead of asking an oracle (which we can't do as easily because not private execution) we can just store the AuthWit in a shared registry, and look it up when we need it. While this needs the storage to be updated ahead of time (can be same tx), we can quite easily do so by batching the AuthWit updates with the interaction - a benefit of Account Contracts. A shared registry is used such that execution from the sequencers point of view will be more straight forward and predictable. Furthermore, since we have the authorization data directly in public state, if they are both set and unset (authorized and then used) in the same transaction, there will be no state effect after the transaction for the authorization which saves gas ⛽.

<Image img={require("/img/authwit4.png")} />
<Image img={require("@site/static/img/authwit4.png")} />

### Replays

Expand Down
56 changes: 42 additions & 14 deletions docs/docs/aztec/concepts/advanced/storage/indexed_merkle_tree.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,17 @@ Currently the only feasible way to get privacy in public blockchains is via a UT

A classic merkle tree:

<Image img={require("/img/indexed-merkle-tree/normal-merkle-tree.png")} />
<Image
img={require("@site/static/img/indexed-merkle-tree/normal-merkle-tree.png")}
/>

To destroy state, the concept of a "nullifier" tree is introduced. Typically represented as a sparse Merkle Tree, the structure is utilized to store notes deterministically linked to values in the append-only tree of encrypted notes.

A sparse merkle tree (not every leaf stores a value):

<Image img={require("/img/indexed-merkle-tree/sparse-merkle-tree.png")} />
<Image
img={require("@site/static/img/indexed-merkle-tree/sparse-merkle-tree.png")}
/>

In order to spend / modify a note in the private state tree, one must create a nullifier for it, and prove that the nullifier does not already exist in the nullifier tree. As nullifier trees are modeled as sparse merkle trees, non membership checks are (conceptually) trivial.

Expand Down Expand Up @@ -132,23 +136,33 @@ A visual aid for insertion is presented below:

1. Initial state

<Image img={require("/img/indexed-merkle-tree/index-merkle-tree-1.png")} />
<Image
img={require("@site/static/img/indexed-merkle-tree/index-merkle-tree-1.png")}
/>

2. Add a new value $v=30$

<Image img={require("/img/indexed-merkle-tree/index-merkle-tree-2.png")} />
<Image
img={require("@site/static/img/indexed-merkle-tree/index-merkle-tree-2.png")}
/>

3. Add a new value $v=10$

<Image img={require("/img/indexed-merkle-tree/index-merkle-tree-3.png")} />
<Image
img={require("@site/static/img/indexed-merkle-tree/index-merkle-tree-3.png")}
/>

4. Add a new value $v=20$

<Image img={require("/img/indexed-merkle-tree/index-merkle-tree-4.png")} />
<Image
img={require("@site/static/img/indexed-merkle-tree/index-merkle-tree-4.png")}
/>

5. Add a new value $v=50$

<Image img={require("/img/indexed-merkle-tree/index-merkle-tree-5.png")} />
<Image
img={require("@site/static/img/indexed-merkle-tree/index-merkle-tree-5.png")}
/>

By studying the transitions between each diagram you can see how the pointers are updated between each insertion.

Expand Down Expand Up @@ -193,31 +207,45 @@ In the following example we insert a subtree of size 4 into our tree at step 4.

1. Prepare to insert subtree $[35,50,60,15]$

<Image img={require("/img/indexed-merkle-tree/subtree-insert-1.png")} />
<Image
img={require("@site/static/img/indexed-merkle-tree/subtree-insert-1.png")}
/>

2. Update low nullifier for new nullifier $35$.

<Image img={require("/img/indexed-merkle-tree/subtree-insert-2.png")} />
<Image
img={require("@site/static/img/indexed-merkle-tree/subtree-insert-2.png")}
/>

3. Update low nullifier for new nullifier $50$. (Notice how the low nullifier exists within our pending insertion subtree, this becomes important later).

<Image img={require("/img/indexed-merkle-tree/subtree-insert-3.png")} />
<Image
img={require("@site/static/img/indexed-merkle-tree/subtree-insert-3.png")}
/>

4. Update low nullifier for new nullifier $60$.

<Image img={require("/img/indexed-merkle-tree/subtree-insert-4.png")} />
<Image
img={require("@site/static/img/indexed-merkle-tree/subtree-insert-4.png")}
/>

5. Update low nullifier for new nullifier $15$.

<Image img={require("/img/indexed-merkle-tree/subtree-insert-5.png")} />
<Image
img={require("@site/static/img/indexed-merkle-tree/subtree-insert-5.png")}
/>

6. Update pointers for new nullifier $15$.

<Image img={require("/img/indexed-merkle-tree/subtree-insert-6.png")} />
<Image
img={require("@site/static/img/indexed-merkle-tree/subtree-insert-6.png")}
/>

7. Insert subtree.

<Image img={require("/img/indexed-merkle-tree/subtree-insert-7.png")} />
<Image
img={require("@site/static/img/indexed-merkle-tree/subtree-insert-7.png")}
/>

### Performance gains from subtree insertion

Expand Down
6 changes: 3 additions & 3 deletions docs/docs/aztec/concepts/communication/cross_chain_calls.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ A "portal" refers to the part of an application residing on L1, which is associa

In a logical sense, a Message Box functions as a one-way message passing mechanism with two ends, one residing on each side of the divide, i.e., one component on L1 and another on L2. Essentially, these boxes are utilized to transmit messages between L1 and L2 via the rollup contract. The boxes can be envisaged as multi-sets that enable the same message to be inserted numerous times, a feature that is necessary to accommodate scenarios where, for instance, "deposit 10 eth to A" is required multiple times. The diagram below provides a detailed illustration of how one can perceive a message box in a logical context.

<Image img={require("/img/com-abs-5.png")} />
<Image img={require("@site/static/img/com-abs-5.png")} />

- Here, a `sender` will insert a message into the `pending` set, the specific constraints of the actions depend on the implementation domain, but for now, say that anyone can insert into the pending set.
- At some point, a rollup will be executed, in this step messages are "moved" from pending on Domain A, to ready on Domain B. Note that consuming the message is "pulling & deleting" (or nullifying). The action is atomic, so a message that is consumed from the pending set MUST be added to the ready set, or the state transition should fail. A further constraint on moving messages along the way, is that only messages where the `sender` and `recipient` pair exists in a leaf in the contracts tree are allowed!
Expand All @@ -78,7 +78,7 @@ By instead pulling, we can have the "message" be something that is derived from

To support messages in both directions we require two of these message boxes (one in each direction). However, due to the limitations of each domain, the message box for sending messages into the rollup and sending messages out are not fully symmetrical. In reality, the setup looks closer to the following:

<Image img={require("/img/com-abs-6.png")} />
<Image img={require("@site/static/img/com-abs-6.png")} />

:::info
The L2 -> L1 pending messages set only exist logically, as it is practically unnecessary. For anything to happen to the L2 state (e.g., update the pending messages), the state will be updated on L1, meaning that we could just as well insert the messages directly into the ready set.
Expand Down Expand Up @@ -149,4 +149,4 @@ To make it possible to hide when a specific message is consumed, the `L1ToL2Msg`

The following diagram shows the overall architecture, combining the earlier sections.

<Image img={require("/img/com-abs-7.png")} />
<Image img={require("@site/static/img/com-abs-7.png")} />
2 changes: 1 addition & 1 deletion docs/docs/aztec/concepts/storage/notes.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ Rather than storing entire notes in a data tree, note commitments (hashes of the

When a note is updated, Aztec nullifies the original commitment in the note hash tree by creating a nullifier from the note data, and may create a new note with the updated information, encrypted to a new owner if necessary. This helps to decouple actions of creating, updating and deleting private state.

<Image img={require("/img/public-and-private-state-diagram.png")} />
<Image img={require("@site/static/img/public-and-private-state-diagram.png")} />

Notes are comparable to cash, with some slight differences. When you want to spend \$3.50 USD in real life, you give your \$5 note to a cashier who will keep \$3.50 and give you separate notes that add up to \$1.50. Using private notes on Aztec, when you want to spend a \$5 note, you nullify it and create a \$1.5 note with yourself as the owner and a \$3.5 note with the recipient as the owner. Only you and the recipient are aware of \$3.5 transaction, they are not aware that you "split" the \$5 note.

Expand Down
4 changes: 2 additions & 2 deletions docs/docs/aztec/concepts/transactions.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ The introduction of the Private eXecution Environment (PXE) provides a safe envi

The accompanying diagram illustrates the flow of interactions between a user, their wallet, the PXE, the node operators (sequencers / provers), and the L1 chain.

<Image img={require("/img/transaction-lifecycle.png")} />
<Image img={require("@site/static/img/transaction-lifecycle.png")} />

1. **The user initiates a transaction** – In this example, the user decides to privately send 10 DAI to gudcause.eth. After inputting the amount and the receiving address, the user clicks the confirmation button on their wallet.

Expand All @@ -45,7 +45,7 @@ _The sequencer has passed the transaction information – proofs of correct exec

Transactions on Aztec start with a call from Aztec.js, which creates a request containing transaction details. This request moves to the Private Execution Environment (PXE) which simulates and processes it. Then the PXE interacts with the Aztec Node which uses the sequencer to ensure that all the transaction details are enqueued properly. The sequencer then submits the block to the rollup contract, and the transaction is successfully mined.

<a href="https://raw.githubusercontent.com/AztecProtocol/aztec-packages/835b87ead8e031ea78952f75c61b0526da290f54/docs/static/img/sandbox_sending_a_tx.png"><img src="/img/sandbox_sending_a_tx.png" alt="Sending a transaction" /></a>
<a href="https://raw.githubusercontent.com/AztecProtocol/aztec-packages/835b87ead8e031ea78952f75c61b0526da290f54/docs/static/img/sandbox_sending_a_tx.png"><img src="@site/static/img/sandbox_sending_a_tx.png" alt="Sending a transaction" /></a>

See [this diagram](https://raw.githubusercontent.com/AztecProtocol/aztec-packages/2fa143e4d88b3089ebbe2a9e53645edf66157dc8/docs/static/img/sandbox_sending_a_tx.svg) for a more detailed overview of the transaction execution process. It highlights 3 different types of transaction execution: contract deployments, private transactions and public transactions.

Expand Down
4 changes: 2 additions & 2 deletions docs/docs/aztec/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ Aztec is a privacy-first Layer 2 on Ethereum. It supports smart contracts with b

## High level view

<Image img={require("/img/aztec-high-level.png")} />
<Image img={require("@site/static/img/aztec-high-level.png")} />

1. A user interacts with Aztec through Aztec.js (like web3js or ethersjs)
2. Private functions are executed in the PXE, which is client-side
Expand Down Expand Up @@ -46,7 +46,7 @@ Private state works with UTXOs, which are chunks of data that we call notes. To

Public state works similarly to other chains like Ethereum, behaving like a public ledger. Public data is stored in a public data tree.

![Public vs private state](../../static/img/public-and-private-state-diagram.png)
![Public vs private state](@site/static/img/public-and-private-state-diagram.png)

Aztec [smart contract](./smart_contracts_overview.md) developers should keep in mind that different data types are used when manipulating private or public state. Working with private state is creating commitments and nullifiers to state, whereas working with public state is directly updating state.

Expand Down
2 changes: 1 addition & 1 deletion docs/docs/aztec/smart_contracts/functions/context.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ The call context contains information about the current call being made:

> The graphic below illustrates how the message sender changes throughout the kernel circuit iterations.

<img src="/img/context/sender_context_change.png" />
<img src="@site/static/img/context/sender_context_change.png" />

2. Storage contract address

Expand Down
Loading