diff --git a/documentation/guides/02_dependencies.md b/documentation/guides/02_dependencies.md index 5f2391b75..b32527731 100644 --- a/documentation/guides/02_dependencies.md +++ b/documentation/guides/02_dependencies.md @@ -1,41 +1,34 @@ --- -id: dependencies +id: dependencies title: Dependency Management sidebar_label: Dependency Management --- [general tags]: # (guides, dependency, dependency_management, imports, program) -## Leo Imports -In your `main.leo` file, specify any imported dependencies using the `import` keyword before the program declaration: -```leo -import credits.aleo; +Leo programs can import functionality from other programs. Any imported programs are referred to as dependencies. There are two types of dependencies: -program test.aleo { -... -} -``` +- **Network dependencies**: Programs already deployed on the Aleo network, fetched as pre-compiled bytecode. +- **Local dependencies**: Code on your filesystem; either Leo code compiled from source, or Aleo Instructions code. -From the root of your Leo program directory, use the `leo add` command to update the `program.json` manifest to add dependencies. +## Adding Dependencies -## Deployed Programs -When adding a deployed program as a dependency to your program, such as the `credits.aleo`, use the following command:: +### Network Dependencies -``` -leo add credits.aleo +To add a program already deployed on the Aleo network as a dependency: +```bash +leo add credits.aleo --network ``` or -``` -leo add credits +```bash +leo add credits --network ``` -If you are deploying to mainnet, you will need to specify mainnet imports using the `--network` flag as follows: - -``` +For mainnet dependencies: +```bash leo add credits --network mainnet ``` -For the first imported dependency, a new `dependencies` field will be added to the 'package.json` manifest: - +This adds an entry to your `program.json`: ```json { "program": "your_program.aleo", @@ -53,38 +46,121 @@ For the first imported dependency, a new `dependencies` field will be added to t } ``` -Dependencies can be removed using the `leo remove` command: +### Local Dependencies + +To add a Leo package or Aleo Instructions file from your local filesystem as a dependency: ```bash -leo remove credits.aleo +leo add my_library.aleo --local ``` -## Local Development -When deploying to a local devnet, specify the path for the local dependency as follows: - -``` -leo add program_name.aleo --local ./path_to_dependency -``` -The dependencies section in the `program.json` manifest should include the path: +This records the path in `program.json`: ```json { - "program": "your_program.aleo", - "version": "0.0.0", - "description": "", - "license": "MIT", "dependencies": [ { - "name": "local_dependency.aleo", + "name": "my_library.aleo", "location": "local", "network": null, - "path": "./path" + "path": "./path/to/my_library" } ] -} +} +``` + +Local dependencies are compiled from source whenever you build. They never require network access. + +## Removing Dependencies +```bash +leo remove credits.aleo +``` + +## Using Dependencies + +In your `main.leo` file, import dependencies before the program declaration: +```leo +import credits.aleo; +import my_library.aleo; + +program my_program.aleo { + // ... +} +``` + +## Dependency Resolution Process + +When you run a Leo command, dependencies are resolved as follows: + +1. **Read `program.json`** to find declared dependencies +2. **For each dependency:** + - **Local**: Read the Leo source from the specified path and compile it, or use Aleo Instructions file + - **Network**: Fetch the bytecode from the Aleo network (or cache) +3. **Resolve transitive dependencies** - if your dependency imports other programs, those are fetched too +4. **Topologically sort** all programs so dependencies are processed before dependents + +### Caching Behavior + +Network dependencies are cached locally at `~/.aleo/registry/{network}/{program_name}/{edition}/` to avoid repeated downloads. + +Different commands handle caching differently: + +| Command | Cache Behavior | +|---------|---------------| +| `leo build` | Uses cache | +| `leo run` | Uses cache | +| `leo execute` | Always fetches fresh | +| `leo deploy` | Always fetches fresh | +| `leo upgrade` | Always fetches fresh | +| `leo synthesize` | Always fetches fresh | + +Commands that generate proofs (`execute`, `deploy`, `upgrade`, `synthesize`) always fetch fresh bytecode because proofs include commitments to the exact bytecode of dependencies. Using stale cached bytecode would produce invalid proofs if a dependency has been upgraded on-chain. + +To force a fresh fetch during `build` or `run`: +```bash +leo build --no-cache ``` -## Recursive Deployment -When deploying a program that uses local dependencies, use the following command: +## Program Editions + +An **edition** is the version number of a deployed program on the Aleo network: +- **Edition 0:** Initial deployment +- **Edition 1:** First upgrade +- **Edition 2:** Second upgrade +- ...and so on + +By default, Leo fetches the **latest** edition of a network dependency. To pin to a specific edition: +```bash +leo add some_program.aleo --edition 3 +``` + +This records the pinned edition in the manifest: +```json +{ + "name": "some_program.aleo", + "location": "network", + "network": "testnet", + "path": null, + "edition": 3 +} +``` + +**When to pin editions:** +- When you need reproducible builds +- When a dependency upgrade would break your program +- When you want to avoid unexpected behavior changes + +**Note:** Local dependencies don't have editions - they're always compiled from your current source code. + +## Deploying Programs with Dependencies + +### Recursive Deployment + +When deploying a program that has local dependencies, use: ```bash leo deploy --recursive ``` -All local dependency will be deployed in order, followed by the main program. Deployed dependencies will be skipped. \ No newline at end of file + +This deploys all local dependencies in topological order, then deploys your main program. Dependencies already deployed on-chain are skipped. + +### Network Dependencies at Deploy Time + +When you deploy, Leo fetches fresh bytecode for all network dependencies to ensure your deployment transaction references the current on-chain editions. If a network dependency is at edition 0 and lacks a constructor (required since the V8 consensus upgrade), Leo will error with a clear message explaining that the dependency needs to be upgraded on-chain first.