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: add basic cli #85

Merged
merged 25 commits into from
Jun 12, 2024
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
ed751b4
dev: add cli packages
zmalatrax Jun 10, 2024
c5c9f36
feat: add basic cli
zmalatrax Jun 10, 2024
4088eb1
dev: remove figlet
zmalatrax Jun 10, 2024
4a6c28c
feat: add error handling and flag conflicts
zmalatrax Jun 10, 2024
de6bbd9
doc: add telegram group to README
zmalatrax Jun 10, 2024
25b0d68
chore: downgrade trunk check to python 3.10 for consistency with test…
zmalatrax Jun 11, 2024
f754906
doc: add CLI usage to README
zmalatrax Jun 11, 2024
99c6a17
chore: move Usage after Cairo presentation
zmalatrax Jun 11, 2024
58fc3f5
doc: add cli usage example
zmalatrax Jun 11, 2024
09fc201
doc: add state of builtins implem
zmalatrax Jun 11, 2024
8186a76
fix: use Op1Src enum for instruction initialization
zmalatrax Jun 11, 2024
b73bd21
chore: remove unused local variable
zmalatrax Jun 11, 2024
154af96
feat: add package build script
zmalatrax Jun 11, 2024
66a76ee
chore: add types to print trace variables
zmalatrax Jun 11, 2024
5b16fbf
chore: remove empty cli file
zmalatrax Jun 11, 2024
492d497
chore: rename memory error to avoid export conflicts
zmalatrax Jun 11, 2024
3c52fd4
feat: add build script with type declaration transforms
zmalatrax Jun 11, 2024
8fe8a74
refactor: export argument json validation to argument argParser
zmalatrax Jun 11, 2024
c7b20f3
doc: update doc for local dependency use
zmalatrax Jun 11, 2024
69e279a
feat: rename cli to cairo
zmalatrax Jun 11, 2024
0edccba
refactor: rename relocateOffset to offset
zmalatrax Jun 11, 2024
df4caab
doc: use updated cli command name
zmalatrax Jun 11, 2024
ca9bf65
chore: remove unused scripts
zmalatrax Jun 12, 2024
673c17e
chore: format RunOptions
zmalatrax Jun 12, 2024
65f51df
refactor: wrap cli action in a global try catch clause
zmalatrax Jun 12, 2024
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
8 changes: 4 additions & 4 deletions .github/workflows/trunk-check.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,13 @@ jobs:

steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4

# Adding cairo-format
- name: Set up Python 3.11
uses: actions/setup-python@v4
- name: Set up Python 3.10
uses: actions/setup-python@v5
with:
python-version: '3.11'
python-version: '3.10'
cache: pip
- run: pip install cairo-lang

Expand Down
50 changes: 45 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
# TypeScript Cairo VM
# Cairo VM Typescript

<div align="center">
<h1><code>TypeScript Cairo VM</code></h1>
<h1><code>Cairo VM TypeScript</code></h1>

<strong>An implementation of the Cairo VM in TypeScript, focusing on
education</strong>

[Github](https://github.com/kkrt-labs/cairo-vm-ts)
[Github](https://github.com/kkrt-labs/cairo-vm-ts) ·
[Telegram](https://t.me/cairovmts)

<sub>Built with 🥕 by <a href="https://twitter.com/KakarotZkEvm">KKRT
Labs</a></sub>
Expand Down Expand Up @@ -92,13 +93,39 @@ performance and safety. While the ones of our TypeScript implementation is
- Deliberate design choices to further improve readability and simplicity
- Extensive documentation: JSDoc, diagrams, explainers, etc.

## Usage

### CLI

You can install the CLI `cairo-vm-ts` by doing the following:

1. Clone this repo: `git clone [email protected]:kkrt-labs/cairo-vm-ts.git`
2. Go to the cloned directory: `cd cairo-vm-ts`
3. Install the dependencies: `bun install`
4. Register the package as a _linkable_ package: `bun link`
5. Link the package: `bun link cairo-vm-ts`

zmalatrax marked this conversation as resolved.
Show resolved Hide resolved
Example usage:

```bash
cairo-vm-ts run fibonacci.json --export-memory fib_mem.bin --print-memory --print-output
```
zmalatrax marked this conversation as resolved.
Show resolved Hide resolved

### As a dependency

No package release has been done yet.

You can still add it as a dependency by cloning the repo and creating a symlink
of the repo inside your project. Follow the same steps as in [CLI](#cli), adding
the flag `--save` to the last command: `bun link --save cairo-vm-ts`

## State of the VM

| Goals | Done? |
| ---------------------------- | ------- |
| Run basic Cairo Zero program | &#9745; |
| Run basic Cairo program | &#9744; |
| Add [builtins](#builtins) | &#9744; |
| Add [builtins](#builtins) | &#9745; |
| Add [hints](#hints) | &#9744; |
| Run StarkNet contracts | &#9744; |
| Benchmark against other VMs | &#9744; |
Expand All @@ -107,7 +134,20 @@ performance and safety. While the ones of our TypeScript implementation is

### Builtins

<!-- Add a table with the builtin list and state done/to be done -->
| Builtin | Done? |
| -------------------------------------------------------------------- | ------- |
| [Output](https://github.com/kkrt-labs/cairo-vm-ts/issues/65) | &#9745; |
| [Pedersen](https://github.com/kkrt-labs/cairo-vm-ts/issues/70) | &#9745; |
| [Range Check](https://github.com/kkrt-labs/cairo-vm-ts/issues/68) | &#9745; |
| [ECDSA](https://github.com/kkrt-labs/cairo-vm-ts/issues/67) | &#9745; |
| [Bitwise](https://github.com/kkrt-labs/cairo-vm-ts/issues/62) | &#9745; |
| [EcOp](https://github.com/kkrt-labs/cairo-vm-ts/issues/66) | &#9745; |
| [Keccak](https://github.com/kkrt-labs/cairo-vm-ts/issues/69) | &#9745; |
| [Poseidon](https://github.com/kkrt-labs/cairo-vm-ts/issues/71) | &#9745; |
| [Range Check 96](https://github.com/kkrt-labs/cairo-vm-ts/issues/81) | &#9745; |
| Segment Arena | &#9744; |
| AddMod | &#9744; |
| MulMod | &#9744; |

### Hints

Expand Down
143 changes: 143 additions & 0 deletions bin/cli.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
#! /usr/bin/env bun

import * as fs from 'fs';
import { Command, Option } from '@commander-js/extra-typings';

import { consola } from 'consola';
import { parseProgram } from 'vm/program';
import { CairoRunner, RunOptions } from 'runners/cairoRunner';

consola.options = {
...consola.options,
formatOptions: {
date: false,
},
};

const VERSION_CLI = '0.1.0';

const program = new Command().name('cairo-vm-ts').version(VERSION_CLI);
zmalatrax marked this conversation as resolved.
Show resolved Hide resolved

program
.command('run', { isDefault: true })
.description('Run a compiled Cairo program')
.argument('<program.json>', 'path to Cairo compilation artifacts')
.option('--no-relocate', 'do not relocate memory')
.addOption(
new Option(
'--offset <OFFSET>',
'start address of the relocated memory\nStarkWare verifier expects offset to be 1'
)
.default(0, '0')
.argParser(parseInt)
)
.option(
'--export-trace <TRACE_FILENAME>',
'export the trace, little-endian encoded'
)
.option(
'--export-memory <MEMORY_FILENAME>',
'export the relocated memory, little-endian encoded'
)
.option('--print-trace', 'print the trace')
.option('--print-memory', 'print the non-relocated memory')
.option('--print-relocated-memory', 'print the relocated memory')
.option('--print-output', 'print the output segment')
.action(async (path, options) => {
if (!path.match(/\.json$/)) throw new Error('Provided file is not a JSON');
zmalatrax marked this conversation as resolved.
Show resolved Hide resolved

const {
relocate,
offset,
exportMemory,
exportTrace,
printOutput,
printMemory,
printRelocatedMemory,
printTrace,
} = options;

if (
(!relocate && !!offset) ||
(!relocate && exportMemory) ||
(!relocate && printRelocatedMemory)
) {
consola.error(
"option '--no-relocate' cannot be used with options '--offset <OFFSET>', '--export-memory <MEMORY_FILENAME>' or '--print-relocated-memory'"
);
process.exit(1);
}

consola.info(`Cairo VM TS ${VERSION_CLI} - Execution Mode`);

const program = parseProgram(fs.readFileSync(path, 'utf-8'));
const runner = new CairoRunner(program);
const config: RunOptions = {
relocate: relocate,
relocateOffset: offset,
zmalatrax marked this conversation as resolved.
Show resolved Hide resolved
};
try {
runner.run(config);
} catch (err) {
consola.fail('Execution failed!');
throw err;
}
consola.success('Execution finished!');

if (exportMemory) {
consola.info('Exporting memory...');
try {
runner.exportMemory(exportMemory, offset);
} catch (err) {
consola.fail(
`Failed to export memory to ${exportMemory} with offset ${offset}`
);
consola.error(err);
process.exit(1);
}
consola.success(`Memory exported to ${exportMemory}`);
}
if (exportTrace) {
consola.info('Exporting trace...');
try {
runner.exportTrace(exportTrace);
} catch (err) {
consola.fail(`Failed to export trace to ${exportTrace}`);
throw err;
}
consola.success(`Trace exported to ${exportTrace}`);
}

if (printMemory) consola.log(runner.vm.memory.toString());
if (printRelocatedMemory) consola.log(runner.vm.relocatedMemoryToString());
if (printTrace)
consola.log(
'\nTRACE:',
runner.vm.trace
.map((entry, index) =>
[
`\nSTEP: ${index}`,
`pc: ${entry.pc.toString()}`,
`ap: ${entry.ap.toString()}`,
`fp: ${entry.fp.toString()}\n`,
].join('\n')
)
.join('\n')
);
if (printOutput) {
const output = runner.getOutput();
if (output.length) {
consola.log('Program output: ');
output.forEach((value) => consola.log(value.toString()));
} else {
consola.log('Output segment is empty');
}
}
});

program.addHelpText(
'beforeAll',
'\nGitHub: https://github.com/kkrt-labs/cairo-vm-ts\nTelegram: https://t.me/cairovmts\n'
);
program.showHelpAfterError();
program.parse();
Binary file modified bun.lockb
Binary file not shown.
6 changes: 6 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,14 @@
"printWidth": 80
},
"dependencies": {
"@commander-js/extra-typings": "^12.1.0",
"@noble/curves": "^1.4.0",
"@scure/starknet": "^1.0.0",
"commander": "^12.1.0",
"consola": "^3.2.3",
"zod": "canary"
},
"bin": {
"cairo-vm-ts": "./bin/cli.ts"
}
}
File renamed without changes.
3 changes: 3 additions & 0 deletions src/errors/cairoRunner.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
class CairoRunnerError extends Error {}

export class EmptyRelocatedMemory extends CairoRunnerError {}
6 changes: 5 additions & 1 deletion src/runners/cairoRunner.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import * as fs from 'fs';

import { EmptyRelocatedMemory } from 'errors/cairoRunner';

import { Relocatable } from 'primitives/relocatable';
import { VirtualMachine } from 'vm/virtualMachine';
import { Program } from 'vm/program';
import { VirtualMachine } from 'vm/virtualMachine';
import { getBuiltin } from 'builtins/builtin';

/**
Expand Down Expand Up @@ -91,6 +93,8 @@ export class CairoRunner {
* @dev DataView must be used to enforce little-endianness
*/
exportMemory(filename: string = 'encoded_memory', offset: number = 0) {
if (!this.vm.relocatedMemory.length) throw new EmptyRelocatedMemory();

const buffer = new ArrayBuffer(this.vm.relocatedMemory.length * 5 * 8);
const view = new DataView(buffer);

Expand Down
Loading