diff --git a/CHANGELOG.md b/CHANGELOG.md index 60876bb..e6cbf96 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,27 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. +### [0.0.1-alpha.5](https://github.com/DIG-Network/clvm-execution-env/compare/v0.0.1-alpha.4...v0.0.1-alpha.5) (2024-09-29) + + +### Bug Fixes + +* param name ([fa39ebd](https://github.com/DIG-Network/clvm-execution-env/commit/fa39ebda5afe2930b3d159c01f9e73477d0652f0)) + +### [0.0.1-alpha.4](https://github.com/DIG-Network/clvm-execution-env/compare/v0.0.1-alpha.3...v0.0.1-alpha.4) (2024-09-29) + + +### Bug Fixes + +* ports ([5f3be33](https://github.com/DIG-Network/clvm-execution-env/commit/5f3be33690a26fb512e751f42cd60facf400cf4e)) + +### [0.0.1-alpha.3](https://github.com/DIG-Network/clvm-execution-env/compare/v0.0.1-alpha.2...v0.0.1-alpha.3) (2024-09-29) + + +### Features + +* add working brun runner ([2efcf20](https://github.com/DIG-Network/clvm-execution-env/commit/2efcf208bff33d17e1b9a15d12b008212ad39154)) + ### 0.0.1-alpha.2 (2024-09-29) diff --git a/Dockerfile b/Dockerfile index 570c9a1..5163f16 100644 --- a/Dockerfile +++ b/Dockerfile @@ -26,31 +26,27 @@ RUN curl -fsSL https://deb.nodesource.com/setup_20.x | bash - && \ # Verify Node.js and npm installation RUN node -v && npm -v -# Install Chia dev tools -RUN git clone https://github.com/Chia-Network/chia-dev-tools.git /chia-dev-tools && \ - cd /chia-dev-tools && \ - python3 -m venv venv && \ - . ./venv/bin/activate && \ - pip install --upgrade pip && \ - pip install . +# Install Chia Dev Tools from PyPI globally so 'run' and 'brun' are available system-wide +RUN python3 -m pip install --upgrade pip && \ + python3 -m pip install --extra-index-url https://pypi.chia.net/simple/ chia-dev-tools # Set working directory to /usr/src/app for the Express app WORKDIR /usr/src/app -# Copy package.json and package-lock.json first to leverage Docker caching +# Copy package.json and package-lock.json for dependency installation COPY package*.json ./ # Install npm dependencies for the Express server RUN npm install -# Copy the rest of the application (TypeScript files, config, etc.) +# Copy the rest of the application files COPY . . # Build the TypeScript project RUN npm run build -# Expose the necessary ports for Chia and the Express server -EXPOSE 8444 8555 3000 +# Expose the necessary ports for the CLVM server +EXPOSE 4363 -# Set the command to start the Express server +# Command to start the Express server CMD ["npm", "start"] diff --git a/README.md b/README.md index 1bdf187..6902bf5 100644 --- a/README.md +++ b/README.md @@ -1 +1,128 @@ -# clvm-execution-env +Here's the updated README with the `clsp` field in place of `clvm_code`, reflecting the correct behavior of the API. + +--- + +### CLVM Execution Environment + +This project provides a Dockerized Node.js Express server that accepts Chialisp (CLSP) code and parameters via a `POST` request, compiles the code into CLVM bytecode using Chia Dev Tools, and then runs the bytecode on the Chialisp Virtual Machine (CLVM) using `brun`. + +### Table of Contents +- [Features](#features) +- [Getting Started](#getting-started) +- [Requirements](#requirements) +- [Installation](#installation) +- [Usage](#usage) +- [API Endpoint](#api-endpoint) +- [Environment Variables](#environment-variables) +- [Contributing](#contributing) + +### Features +- Compile Chialisp code dynamically using `run`. +- Execute compiled Chialisp code on the CLVM using `brun`. +- Accept input via a REST API endpoint. +- Built with Node.js, TypeScript, and Express. +- Containerized for easy deployment with Docker. + +### Getting Started + +These instructions will get you a copy of the project up and running on your local machine for development and testing purposes. + +### Requirements + +- [Docker](https://www.docker.com/get-started) +- [Node.js](https://nodejs.org/en/) (Optional for development purposes) + +### Installation + +1. **Clone the repository**: + ```bash + git clone + cd clvm-execution-env + ``` + +2. **Build the Docker container**: + Make sure Docker is installed and running on your machine, then build the Docker image using the provided Dockerfile. + ```bash + docker build -t clvm-execution-env . + ``` + +3. **Run the Docker container**: + Once the image is built, you can run the container using the following command: + ```bash + docker run -p 3000:3000 clvm-execution-env + ``` + + This will expose the service on port `3000` of your local machine. + +### Usage + +Once the container is running, you can make `POST` requests to the API endpoint to compile and execute Chialisp code. + +### API Endpoint + +#### `POST /run-chialisp` + +This endpoint accepts Chialisp (CLSP) code and parameters in the request body and returns the result of running the compiled CLVM bytecode using `brun`. + +- **Endpoint**: `/run-chialisp` +- **Method**: `POST` +- **Content-Type**: `application/json` + +##### Request Body Format: + +```json +{ + "clsp": "(mod (number) (defun factorial (number) (if (> number 1) (* number (factorial (- number 1))) 1)) (factorial number))", + "params": ["5"] +} +``` + +- `clsp`: The Chialisp code (CLSP) to be compiled and run. +- `params`: (Optional) The parameters to pass to the compiled CLVM code, formatted as an array of strings. + +##### Example Request: + +```bash +curl -X POST http://localhost:3000/run-chialisp \ +-H "Content-Type: application/json" \ +-d '{ + "clsp": "(mod (number) (defun factorial (number) (if (> number 1) (* number (factorial (- number 1))) 1)) (factorial number))", + "params": ["5"] +}' +``` + +##### Example Response: + +```json +{ + "result": "120" +} +``` + +### Environment Variables + +You can customize the behavior of the container using environment variables. The following environment variables are supported: + +| Variable | Default | Description | +| ------------- | ------- | ------------------------------------------------- | +| `PORT` | `3000` | The port on which the Express server will listen. | + +### Contributing + +If you wish to contribute to this project: + +1. Fork the repository. +2. Create a feature branch (`git checkout -b feature/your-feature`). +3. Commit your changes (`git commit -am 'Add some feature'`). +4. Push to the branch (`git push origin feature/your-feature`). +5. Open a pull request. + +Feel free to open issues to report bugs or request features. + +### License + +This project is licensed under the MIT License. See the `LICENSE` file for details. + +--- + +Now, the `clsp` field correctly indicates that the API accepts and runs Chialisp code. Let me know if you need any other changes or additions! \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 8167698..03f9acd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "clvm-execution-env", - "version": "0.0.1-alpha.2", + "version": "0.0.1-alpha.5", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "clvm-execution-env", - "version": "0.0.1-alpha.2", + "version": "0.0.1-alpha.5", "license": "ISC", "dependencies": { "body-parser": "^1.20.3", diff --git a/package.json b/package.json index f235c1a..a4510ff 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "clvm-execution-env", - "version": "0.0.1-alpha.2", + "version": "0.0.1-alpha.5", "description": "CLVM Execution Env for DIG Network", "main": "dist/index.js", "scripts": { diff --git a/src/index.ts b/src/index.ts index 7c28f48..9438180 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,21 +1,21 @@ import express, { Request, Response, NextFunction } from 'express'; import bodyParser from 'body-parser'; import { exec } from 'child_process'; -import tmp from 'tmp'; -import fs from 'fs-extra'; -import path from 'path'; +import { promisify } from 'util'; // Create an instance of Express const app = express(); -const port = 3000; +const port = process.env.PORT || 4363; + +// Promisify the exec function to use async/await +const execPromise = promisify(exec); // Middleware to parse JSON body app.use(bodyParser.json()); /** - * POST /run-clvm - * Accepts CLVM code and its parameters, executes it using chia dev tools, - * and returns the result. + * POST /run-chialisp + * Accepts Chialisp code, runs it directly using `run` and `brun` in one line. * * Body: * { @@ -23,49 +23,45 @@ app.use(bodyParser.json()); * "params": ["param1", "param2"] * } */ - // @ts-ignore -app.post('/run-clvm', (req: Request, res: Response, next: NextFunction) => { - const { clvm_code, params }: { clvm_code: string; params?: string[] } = req.body; +app.post('/run-chialisp', async (req: Request, res: Response, next: NextFunction) => { + let { clsp, params }: { clsp: string; params?: string[] } = req.body; - if (!clvm_code) { - return res.status(400).json({ error: 'CLVM code is required' }); + if (!clsp) { + return res.status(400).json({ error: 'Chialisp code is required' }); } - // Create a temporary directory with auto-cleanup after 5 minutes - const tempDir = tmp.dirSync({ prefix: 'clvm-', unsafeCleanup: true }); + // Unescape internal quotes in the Chialisp code + clsp = clsp.replace(/\\"/g, '"'); + + // Log the incoming Chialisp code + console.log(`Received Chialisp code: ${clsp}`); try { - // Path to the temporary CLVM file - const clvmFilePath = path.join(tempDir.name, 'temp.clvm'); - const clvmArgs = params ? params.join(' ') : ''; + // Construct the one-liner command using `run` and `brun` + const clvmArgs = params ? `(${params.join(' ')})` : 'nil'; // Wrap params in parentheses + const command = `brun "$(run "${clsp}")" "${clvmArgs}"`; + + console.log(`Executing command: ${command}`); - // Write the CLVM code to the temporary file - fs.writeFileSync(clvmFilePath, clvm_code); + // Execute the one-liner `brun "$(run ...)"` command + const { stdout, stderr } = await execPromise(command); - // Command to run CLVM using chia dev tools - const command = `run -i ${clvmFilePath} ${clvmArgs}`; + if (stderr) { + console.error(`CLVM execution errors: ${stderr}`); + } - // Execute the CLVM command using child_process - exec(command, { cwd: '/chia-dev-tools/venv/bin' }, (error, stdout, stderr) => { - // Cleanup the temporary directory - tempDir.removeCallback(); + // Trim the output of CLVM execution to remove any trailing newlines or spaces + const trimmedResult = stdout.trim(); - if (error) { - console.error(`Error executing CLVM: ${error.message}`); - return res.status(500).json({ error: 'Error running CLVM' }); - } + // Log the result + console.log(`CLVM execution result: ${trimmedResult}`); - if (stderr) { - console.error(`stderr: ${stderr}`); - } + // Send back the result of the CLVM execution + return res.json({ result: trimmedResult }); - // Send back the result of the CLVM execution - return res.json({ result: stdout }); - }); } catch (err) { console.error(`An error occurred: ${err}`); - tempDir.removeCallback(); // Ensure cleanup on error return res.status(500).json({ error: 'An internal server error occurred' }); } });