diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 8dc9456..3dfa516 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -5,4 +5,4 @@ updates: schedule: interval: weekly time: "10:00" - open-pull-requests-limit: 10 + open-pull-requests-limit: 0 diff --git a/README.md b/README.md index b1ee916..6f8794b 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # aleo-devnode -A standalone Aleo development node for local testing and development. +The devnode is a standalone Aleo development node for local testing and development. Unlike a production node, it **does not verify proofs**. This means transactions can be built with placeholder proofs (for executions) and placeholder verifying keys (for deployments and upgrades), making quick local iteration and fast end-to-end testing by bypassing proof generation when creating a transaction. ## Build @@ -32,6 +32,32 @@ The node starts a REST API on `http://127.0.0.1:3030` by default and automatical | `-s, --storage [DIR]` | in-memory | Persist the ledger to disk at `DIR` (default: `devnode/`) | | `-c, --clear-storage` | off | Clear the storage directory before starting (requires `-s`) | +### Pre-funded accounts + +The built-in genesis block seeds 50 accounts with funds for testing. The first five are: + +| # | Address | Private Key | +|---|---------|-------------| +| 0 | `aleo1rhgdu77hgyqd3xjj8ucu3jj9r2krwz6mnzyd80gncr5fxcwlh5rsvzp9px` | `APrivateKey1zkp8CZNn3yeCseEtxuVPbDCwSyhGW6yZKUYKfgXmcpoGPWH` | +| 1 | `aleo1s3ws5tra87fjycnjrwsjcrnw2qxr8jfqqdugnf0xzqqw29q9m5pqem2u4t` | `APrivateKey1zkp2RWGDcde3efb89rjhME1VYA8QMxcxep5DShNBR6n8Yjh` | +| 2 | `aleo1ashyu96tjwe63u0gtnnv8z5lhapdu4l5pjsl2kha7fv7hvz2eqxs5dz0rg` | `APrivateKey1zkp2GUmKbVsuc1NSj28pa1WTQuZaK5f1DQJAT6vPcHyWokG` | +| 3 | `aleo12ux3gdauck0v60westgcpqj7v8rrcr3v346e4jtq04q7kkt22czsh808v2` | `APrivateKey1zkpBjpEgLo4arVUkQmcLdKQMiAKGaHAQVVwmF8HQby8vdYs` | +| 4 | `aleo1p9sg8gapg22p3j42tang7c8kqzp4lhe6mg77gx32yys2a5y7pq9sxh6wrd` | `APrivateKey1zkp3J6rRrDEDKAMMzSQmkBqd3vPbjp4XTyH7oMKFn7eVFwf` | + +> ⚠️ These are development keys. Never use them in production. + +To list all 50 accounts: + +```sh +aleo-devnode accounts +``` + +If you are using a custom genesis block, query block 0 to inspect funded accounts: + +```sh +curl http://127.0.0.1:3030/testnet/block/0 +``` + ### Advance the ledger manually When running with `--manual-block-creation`, use `advance` to create blocks explicitly: @@ -60,6 +86,28 @@ This persists the ledger to a `devnode/` directory. To start fresh: aleo-devnode start --private-key APrivateKey1zkp8CZNn3yeCseEtxuVPbDCwSyhGW6yZKUYKfgXmcpoGPWH --storage --clear-storage ``` +## Building transactions for devnode + +### Leo CLI + +Add the appropriate flag when building transactions against a devnode: + +| Command | Flag | Description | +|---------|------|-------------| +| `leo execute` | `--skip-execute-proof` | Skips execution proof generation | +| `leo deploy` | `--skip-deploy-certificate` | Skips verifying key certificate for deployment | +| `leo upgrade` | `--skip-deploy-certificate` | Skips verifying key certificate for upgrade | + +### JavaScript/TypeScript SDK + +Use the dedicated devnode transaction builder methods in [`ProgramManager`](https://github.com/ProvableHQ/sdk/blob/5a50b6f5a7f23ff48933557dfdc51315912e79ba/sdk/src/program-manager.ts): + +| Method | Description | +|--------|-------------| +| [`buildDevnodeExecutionTransaction`](https://github.com/ProvableHQ/sdk/blob/5a50b6f5a7f23ff48933557dfdc51315912e79ba/sdk/src/program-manager.ts#L3425) | Builds an execution transaction with a placeholder proof | +| [`buildDevnodeDeploymentTransaction`](https://github.com/ProvableHQ/sdk/blob/5a50b6f5a7f23ff48933557dfdc51315912e79ba/sdk/src/program-manager.ts#L3598) | Builds a deployment transaction with a placeholder verifying key | +| [`buildDevnodeUpgradeTransaction`](https://github.com/ProvableHQ/sdk/blob/5a50b6f5a7f23ff48933557dfdc51315912e79ba/sdk/src/program-manager.ts#L3735) | Builds an upgrade transaction with a placeholder verifying key | + ## Snapshots Snapshots capture the ledger state at a specific block height and can be restored later. They require persistent storage (`--storage`). @@ -141,6 +189,7 @@ Key endpoints: | `POST` | `/testnet/block/create` | Create blocks (body: `{"num_blocks": N}`, optional) | | `GET` | `/testnet/program/{id}` | Get a deployed program | | `GET` | `/testnet/program/{id}/mapping/{name}/{key}` | Get a mapping value | +| `GET` | `/testnet/program/{id}/mapping/{name}?all=true` | Get all key-value pairs in a mapping | | `POST` | `/testnet/snapshot` | Take a snapshot (body: `{"name": "optional"}`) | | `GET` | `/testnet/snapshots` | List available snapshots | | `POST` | `/testnet/shutdown` | Gracefully shut down the node | diff --git a/src/accounts.rs b/src/accounts.rs new file mode 100644 index 0000000..d5d5277 --- /dev/null +++ b/src/accounts.rs @@ -0,0 +1,95 @@ +// Copyright (C) 2019-2026 Provable Inc. +// This file is part of the Leo library. + +// The Leo library is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// The Leo library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with the Leo library. If not, see . + +use anyhow::Result; +use clap::Parser; + +/// All 50 pre-funded development accounts for the built-in genesis block (address, private_key). +pub const FUNDED_ACCOUNTS: &[(&str, &str)] = &[ + ("aleo1rhgdu77hgyqd3xjj8ucu3jj9r2krwz6mnzyd80gncr5fxcwlh5rsvzp9px", "APrivateKey1zkp8CZNn3yeCseEtxuVPbDCwSyhGW6yZKUYKfgXmcpoGPWH"), + ("aleo1s3ws5tra87fjycnjrwsjcrnw2qxr8jfqqdugnf0xzqqw29q9m5pqem2u4t", "APrivateKey1zkp2RWGDcde3efb89rjhME1VYA8QMxcxep5DShNBR6n8Yjh"), + ("aleo1ashyu96tjwe63u0gtnnv8z5lhapdu4l5pjsl2kha7fv7hvz2eqxs5dz0rg", "APrivateKey1zkp2GUmKbVsuc1NSj28pa1WTQuZaK5f1DQJAT6vPcHyWokG"), + ("aleo12ux3gdauck0v60westgcpqj7v8rrcr3v346e4jtq04q7kkt22czsh808v2", "APrivateKey1zkpBjpEgLo4arVUkQmcLdKQMiAKGaHAQVVwmF8HQby8vdYs"), + ("aleo1p9sg8gapg22p3j42tang7c8kqzp4lhe6mg77gx32yys2a5y7pq9sxh6wrd", "APrivateKey1zkp3J6rRrDEDKAMMzSQmkBqd3vPbjp4XTyH7oMKFn7eVFwf"), + ("aleo1l4z0j5cn5s6u6tpuqcj6anh30uaxkdfzatt9seap0atjcqk6nq9qnm9eqf", "APrivateKey1zkp6w2DLUBBAGTHUK4JWqFjEHvqhTAWDB5Ex3XNGByFsWUh"), + ("aleo1aukf3jeec42ssttmq964udw0efyzt77hc4ne93upsu2plgz0muqsg62t68", "APrivateKey1zkpEBzoLNhxVp6nMPoCHGRPudASsbCScHCGDe6waPRm87V1"), + ("aleo1y4s2sjw03lkg3htlcpg683ec2j9waprljc657tfu4wl6sd67juqqvrg04a", "APrivateKey1zkpBZ9vQGe1VtpSXnhyrzp9XxMfKtY3cPopFC9ZB6EYFays"), + ("aleo1xh2lnryvtzxcvlz8zzgranu6yldaq5257cac44de4v0aasgu45yq3yk3yv", "APrivateKey1zkpHqcqMzArwGX3to2x1bDVFDxo7uEWL4FGVKnstphnybZq"), + ("aleo19ljgqpwy98l9sz4f6ly028rl8j8r4grlnetp9e2nwt2xwyfawuxq5yd0tj", "APrivateKey1zkp6QYrYZGxnDmwvQSg7Nw6Ye6WUeXHvs3wtj5Xa9LArc7p"), + ("aleo1s2tyzgqr9p95sxtj9t0s38cmz9pa26edxp4nv0s8mk3tmdzmqgzsctqhxg", "APrivateKey1zkp9AZwPkk4gYUCRtkaX5ZSfBymToB7azBJHmJkSvfyfcn4"), + ("aleo1sufp275hshd7srrkxwdf7yczmc89em6e5ly933ftnaz64jlq8qysnuz88d", "APrivateKey1zkp2jCDeE8bPnKXKDrXcKaGQRVfoZ1WFUiVorbTwDrEv6Cg"), + ("aleo1mwcjkpm5hpqapnsyddnwtmd873lz2kpp6uqayyuvstr4ky2ycv9sglne5m", "APrivateKey1zkp7St3ztS3cag91PpyQbBffTc8YLmigCGB97Sf6bkQwvpg"), + ("aleo1khukq9nkx5mq3eqfm5p68g4855ewqwg7mk0rn6ysfru73krvfg8qfvc4dt", "APrivateKey1zkpGcGacddZtDLRc8RM4cZb6cm3GoUwpJjSCQcf2mfeY6Do"), + ("aleo1masuagxaduf9ne0xqvct06gpf2tmmxzcgq5w2el3allhu9dsv5pskk7wvm", "APrivateKey1zkp4ZXEtPR4VY7vjkCihYcSZxAn68qhr6gTdw8br95vvPFe"), + ("aleo10w89dpq8tqzeghq35nxtk2k66pskxm8vhrdl3vx6r4j9hkgf2qqs3936q6", "APrivateKey1zkpH7XEPZDUrEBnMtq1JyCR6ipwjFQ5jiHnTCe7Z7heyxff"), + ("aleo1sfu3p7g8rppusft8re7v88ujjhz5sx6pwc5609vdgnr0pdmhkyyqrrsjkm", "APrivateKey1zkpA9S3Epe8mzDnMuAXBmdxyRXgB8yp7PuMrs2teh8xNcVe"), + ("aleo1ry0wc384qthrdna5xtzsjqvxg42zwfezpna6keeqa6netv3qmyxszhh8z8", "APrivateKey1zkp5neB5iVnXMTrR6y8P6wndGE9xWhQzBf3Qoht9yQ17a5o"), + ("aleo1ps4dhhfn5vgfj9lyjra2xnv9a8cc2a2l9jnr585h6tvj4gnlqgfqyszcv3", "APrivateKey1zkp4u1cUbvkC2r3n3Gz3eNzth1TvffGbFeLgaYyk8efsT4e"), + ("aleo15a34a3dtpj879frvndndp0605vqnxsfdedwyrtu5u6xfd7fv5ufqryavc4", "APrivateKey1zkpBs9zc9FChKZAkoHsf1TERcd9EQhe43NS1xuNSnyJSH1K"), + ("aleo1mpn4enrfm2dqjg8lqh09t2zcatkujq3qr3kq8kcnrd7uaqrc3c9qngcp5l", "APrivateKey1zkp3sh4dSfCXd9g86DGHx6PAQG7WrMxE8bMbJxCrpPKSUw3"), + ("aleo1axy39ux5lhaypf039zp7fuhg57qkfqtafu2fa3e2vwgqugeq05qsm2kfl4", "APrivateKey1zkpApK3vKdDDwbf62K5Mh7JsPNksud3ypZEXvuoYPcazStS"), + ("aleo1zzpl369camggvj5qm2nhnpfhe3epcera3xvdra4ze7scg35zmuzsl7kwyh", "APrivateKey1zkp2uS6cU4M4J8z2fE3uMuQHkg87AgrMnDQ8NZzGAnpiEXm"), + ("aleo1j2fhcu3qkvn4k0vrf53jmuv8d0fz5guz9tzdy0egjjjttdhsxszqfdfwfk", "APrivateKey1zkp8za2Nc39VHQFzBQFH6rhKuB9LqPaoVw1SgUPG8pSGAAn"), + ("aleo1jqfyapkxkx3hk05mjzky9cqxjr5yz33fwfqujpd0uy5zxxwfkvqskcffhq", "APrivateKey1zkp4JjfHAVD9d6S9n8FYpVnapkJ3yfiyPaQNnAqsuexUQcU"), + ("aleo1sap6x2ndmmwm8t6z568hc33u8ayynw2ha9u9pck7wvrrd0e7k58sty954x", "APrivateKey1zkpFT2mMYvZ7TPzjkCGH5F64itzRBwjscqqqezx6AaPnqxF"), + ("aleo19afl0wwru8ws7g7c727j27x0e8r7sa5gkjz6jv37sr4ujlm5sqzs2qt8wz", "APrivateKey1zkpJcSh3d66dxtTvaA1b9P9xAdUXMKnWsQSkhmZRDpEUJYr"), + ("aleo1ypkmme72un8k4dzaj0z6ha2skz9adskscwf75eul27j5e7lu6s9q0pu9qx", "APrivateKey1zkpAy7c3uea5yuvjkuN9eqGSoBJDHpE33yCe5qu7u2JbVmZ"), + ("aleo1av8367kf2dre7mwpuyhcg7wrhtvs27usa53fn8uwmd5x7r2gsyrs9084ge", "APrivateKey1zkp3GUSi7FQW7FgLyPp77A45CvDjZFwdqgWzLzkxbB3GXKD"), + ("aleo1y7swdgs3zav50a0r0sx8us4tqycp67kc9ypnml5eqjfpypk7cgqszf6dvn", "APrivateKey1zkp5rtsaS8tZwZVrf5PwQwnfvcm7Q4UntrcXXiwYTMRuz9T"), + ("aleo16dyj3gxptzm5vgfyxlv2s6869ftfdxwpl2hm9r09uqk69kcjwvfqqpu2pm", "APrivateKey1zkpDPHco2BZh95YCD2eZc44LZ8YfuZq85qfULBVgUB6SouE"), + ("aleo1ftv0e670e2nezrdajxg947vn3el4cgjt47nghleuw5a7dja9dyrszr5jhp", "APrivateKey1zkp2jaPbqqFLXiTr92CSDEqevwzaVsj4MbC43apRKFXnWSd"), + ("aleo1d7wfgrgtk75g8m08d7f8jmyk6f8kg9w8jpm7l97hyx0kf6l8asrsdnhzzz", "APrivateKey1zkpEycEZpddReHV4UExGpWSQZUCau2g6K2HP1jQnCSPUAL9"), + ("aleo1hcaq72hw8tf7ms4qfppefklwdr32ud3nngu88wnx6dq67dzgl58scpsg8v", "APrivateKey1zkp9gJgMLBiVKVRSSqbRDQFcKm84sQbJF9wqWzcSnXVw1we"), + ("aleo1szkl7zn07mgd44qpg43wk3sd5emggc3w5frd3wwms9c4rwklygzs7mn4x9", "APrivateKey1zkp7jX54qsuFZ5Ks2DJhPzx6io2EM2CZhTYA3XU2XfXt2rr"), + ("aleo1sekqksjqnmhpyca5juxxghrujck8dm9lrhp70nrsp9a7hd4sxczswyrnjj", "APrivateKey1zkpDyVQ7mGpb48oS44Zee1gPvA19ng98S2MRCCCcsh7Av8r"), + ("aleo18y86x2qvjsg0tay6fj9cjqejhvv45wnd53a66tax6j3zrxu9gupsh7e86v", "APrivateKey1zkp5grVqsMuASdVowmgsK5CCBjz9dAqAw2K1szc4jPC15EN"), + ("aleo1rnhvu0f4m6ymwegyemqyt7hfsqqaqxpn29l7jafvyuw60nz9ygysu0jn23", "APrivateKey1zkp5s39kX98KZmm4vdfhHuWhMbP5mVCREFRZuT9GGduzb6x"), + ("aleo192e2mn3lmav8csm0krjn0va5v9nur6pr03y8vepe09xc5qummvxq338czu", "APrivateKey1zkp642Mn8JgLFC4C5JGdy73VMg5skFoAj5dmaxKs2zTnDbN"), + ("aleo1mjwjwe67rzs7w08psynya7pc3q4shpyggz92xksy4rumfzfmdc9qnrk4pl", "APrivateKey1zkpFisano5hmJvALiVkgVcxVRL61aS8jz2CwFeAQQS9j6Qu"), + ("aleo1ffdnchytga8nuzg557h8cx0h89xlddxhucxdphtg8k8v8tn7zuysxa893d", "APrivateKey1zkp6gB8LRzRs1chkWMnk7ffAytADkdZEDxggqEEAdV1qQBC"), + ("aleo16w6zw8glrj08psy5nwumsed7kmxwxk8paq2d92m7dk2uerwzuqqsvkamnk", "APrivateKey1zkp7mXyitjWX5hXUznSKpfEMUqdMVzCwG728Nzf1R1axRzL"), + ("aleo1dfystswcj4j0k8nckast6ylexrwuhv42ysldx7x03q0uch259ypsfml8h7", "APrivateKey1zkp6WadY8WbPq2or8YMJDFyS9c6HHyoJEif567i4SqVv2h8"), + ("aleo1j97mw86ytd6v6zl76qju6dm9ee3t0zjdsaydph7dtweusm6vavqsmswgzg", "APrivateKey1zkpJMcEf79UR7n2W5rzLrkeg1hTrWHQyNJcvKmhsJWkzTsN"), + ("aleo17g5m4scr8x8yndx6spsmnu5wk45sgwe4w2la8gnxu0zjn7cfssxq2sxsef", "APrivateKey1zkpEe33jVdjakXiQcKfJUf9fyVaTMxHJcuipXmAWgy55TFQ"), + ("aleo1hkuf3ypfym59m23c8jmw97yxpldsk2ycc9rc2x0eaaxd9x6fmvqqpfg08d", "APrivateKey1zkpGTtLxB3mUbew6mkP3D7tqVveVEZYYKmgVun1CyXJcXmF"), + ("aleo1e9xrl7ummq63d6zay60w5klqkfhya5kwcwa757hqzgujkk9ddcgqnufluq", "APrivateKey1zkp7aPCqYDux1n8DdLGPFNqkoHjSjpkoSaiVpKcf4Xpgz3B"), + ("aleo1u44retdlrhptya55qgxly0um6ydajrz2mhthxtyukzekctxtag9sdcy0cm", "APrivateKey1zkpDbTD13qeLjMA6ympzFFo1Z2mnUHg8DRAaSKE7qCWW79f"), + ("aleo1wqcgpvt58d03nl34vhx3kc0v4jh04f6alvt5s38q3jhdq3shqcxq6g5v70", "APrivateKey1zkpBfe9853NcMnagBeYpimPrT5ZN8fYi8aMv45rxkxbm7Gn"), + ("aleo1s77df89g2km8urqvanvthhuxyw9d32plmjvewthm7cjhnezxtygq78mrdn", "APrivateKey1zkpG22T5KZGDE54HmVCp91vhzNrzb7HihynmUyZ4DX9Ngj2"), +]; + +/// List all pre-funded accounts for the built-in genesis block. +#[derive(Parser, Debug)] +#[group(id = "accounts_args")] +pub struct Accounts; + +impl Accounts { + pub fn execute(self) -> Result<()> { + let sep = "═".repeat(70); + println!("{sep}"); + println!(" Pre-funded Accounts ({} total — built-in genesis only)", FUNDED_ACCOUNTS.len()); + println!("{sep}"); + for (i, (address, private_key)) in FUNDED_ACCOUNTS.iter().enumerate() { + println!(" ({i}) {address}"); + println!(" {private_key}"); + println!(); + } + println!("⚠ These are development keys. Never use them in production."); + println!(" Using a custom genesis? Query block 0: GET http://localhost:3030/testnet/block/0"); + println!("{sep}"); + Ok(()) + } +} diff --git a/src/main.rs b/src/main.rs index dd1d17b..f448f94 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,6 +3,7 @@ // // Licensed under the GNU General Public License v3.0. +mod accounts; mod advance; mod logger; mod rest; @@ -29,6 +30,11 @@ enum DevnodeCommands { #[clap(flatten)] command: restore::Restore, }, + #[clap(name = "accounts", about = "List all pre-funded development accounts for the built-in genesis block")] + Accounts { + #[clap(flatten)] + command: accounts::Accounts, + }, } /// A standalone Aleo development node. @@ -58,5 +64,6 @@ fn run(cli: Cli) -> Result<()> { } DevnodeCommands::Advance { command } => command.execute(), DevnodeCommands::Restore { command } => command.execute(), + DevnodeCommands::Accounts { command } => command.execute(), } } diff --git a/src/start.rs b/src/start.rs index ca2a532..32e8034 100644 --- a/src/start.rs +++ b/src/start.rs @@ -92,6 +92,7 @@ async fn start_devnode(command: Start, private_key: Option) -> Result<() "/resources/genesis_8d710d7e2_40val_snarkos_dev_network.bin" )))? }; + let manual_block_creation = command.manual_block_creation; match command.storage { Some(path) => { if command.clear_storage && path.exists() { @@ -116,7 +117,7 @@ async fn start_devnode(command: Start, private_key: Option) -> Result<() tokio::task::spawn_blocking(move || Ledger::load(genesis_block, storage_mode)) .await .map_err(|e| anyhow::anyhow!("Failed to load ledger: {e}"))??; - run_devnode(socket_addr, ledger, command.manual_block_creation, private_key, Some(path)).await? + run_devnode(socket_addr, ledger, manual_block_creation, private_key, Some(path)).await? } None => { let storage_mode = StorageMode::new_test(None); @@ -124,7 +125,7 @@ async fn start_devnode(command: Start, private_key: Option) -> Result<() tokio::task::spawn_blocking(move || Ledger::load(genesis_block, storage_mode)) .await .map_err(|e| anyhow::anyhow!("Failed to load ledger: {e}"))??; - run_devnode(socket_addr, ledger, command.manual_block_creation, private_key, None).await? + run_devnode(socket_addr, ledger, manual_block_creation, private_key, None).await? } }