Workflow
Functional Requirements
krnl-node is a customized Geth (go-ethereum) node that includes a workflow engine enabling the execution of predefined workflows (DSL-based) similar to tools like n8n. Workflows consist of steps defined in a JSON DSL format and executed upon receiving a krnl_executeKernels request. DSLs are stored on IPFS and are mapped to users through a registry smart contract.
Workflow Execution Engine
The engine shall load and execute workflows defined as JSON objects conforming to a domain-specific language (DSL).
Extends from Azure/go-workflow
Define a custom DSL parser to convert your JSON DSL → go-workflow Workflow struct
A workflow JSON DSL includes:
version: semantic version of the DSL
steps: a list of steps to execute.
connections: a DAG defining control flow dependencies between steps.
Kernels and Step Types
Kernels (Executable components)
Web2 Kernel (type: Web2Kernel)
Executes an HTTP request to an external API.
Structured using OpenAPI-like parameters.
Input: HTTP method, URL, path, query, headers, body.
Output: JSON response body with executing status.
Read EVM Kernel (type: EVMReadKernel)
Executes an eth_call on a smart contract.
Input: contract address, method signature, function arguments.
Output: decoded call result.
Steps (Workflow logic units)
Execution
Web2 Kernel Adapter (Open API Specs Execution)
EVM Kernel Adapter (Solidity Execution)
Initializer: decode user input and do validation check
If Condition (type: IfCondition)
Evaluates one or more expressions using outputs from earlier steps.
Operators: eq, neq, lt, lte, gt, gte.
Output: boolean controlling downstream path.
Switch/Case (type: SwitchCase)
Evaluates a value against multiple case conditions.
Execute the first TRUE branch that matched the condition.
Operators: eq, neq, lt, lte, gt, gte.
Output: boolean controlling downstream path.
Data Transformation (type: DataTransform)
Transforms outputs from previous steps into a new structured object.
From Web2 to EVM data type
From EVM to EVM data type
Supports type casting, variable substitution, and static assignment.
Input: array of field assignments with type:
Usage of previous steps: ${stepID}.{input|output}.{fieldName} – {FieldType}.
Static field - {FieldType}.
For example:
EVM: (string, uint256, (bytes, bool))
Web2: (string, float, (string, bool))
Output: New structured object in Web2 or EVM data type
Variable Substitution
Variables in format $.
Resolved all previous steps execution.
Available in parameters, transformations, and conditions.
Execution Semantics
DAG-based traversal (no loop allowed).
Topological sort determines order.
Steps with no unmet dependencies execute concurrently using goroutines.
Final step must always be a DataTransformation into EVM compatible format
Users only provide the initial input; following inputs can use “${stepID}.{input|output}.{fieldName}” notation
The Last Step of Kernel need to be Data Transformation to aggregate the every desired output to settlement on smart contract reason is that with this we can eliminate the exceed output limit
Registry and Workflow Retrieval
Workflow DSL stored on IPFS and mapped on-chain by entryID in a registry smart contract
On krnl_executeKernels request, krnl-node fetches the IPFS hash from the registry using the entryID.
Signing
On completion, assemble:
User initial input.
Final output from workflow.
Pass to Signer for signature.
External Interface Requirements
User interfaces
React-flow-based interactive builder (future).
JSON DSL submitted via RPC (krnl_executeKernels)
Inputs passed inline as part of RPC payload
Hardware interfaces
Deployed on servers running krnl-node (customized Geth)
Min hardware: 4vCPU, 16GB RAM
Software interfaces
Base software: go-ethereum
Workflow engine: Azure/go-workflow
Custom step types implemented in Golang, extending Azure/go-workflow
Communication interfaces
Ethereum full nodes via JSON-RPC.
Web2 APIs via HTTPS.
EVM smart contracts via RPC.
Signer via RPC endpoint.
IPFS via HTTP gateway.
Registry contracts on Ethereum.
Non-Functional Requirements
Performance Requirements
Max concurrent workflows: 1000 (on 4vCPU | 16GB RAM node)
Max 10s timeout per step.
Max 30s for workflow execution
Max 10 steps per workflow
Concurrency for independent steps.
Web2 Kernel:
Max request body size: 30kb
Max response body size: 128kb
URL max length: 2048 characters
EVMReadKernel:
Security Requirements
Signing done on on-chain Signer (Confidential execution)
Enforce HTTPS.
Validate workflow DSL
Validate OpenAPI and ABI request and response.
Reliability
Fail fast on:
Valid workflow DSL
No infinite loops (acyclic DAG enforced)
Missing or malformed step definitions.
Maintainability
Modular kernel & step implementations.
DSL supports backward compatibility
Logging and tracing per workflow and step
Scalability
Concurrent step execution via goroutines.
Memory-safe step execution with constrained data sizes
Usability
DSL compatible with visual builder (for example: react-flow)
Human-readable error messages.
Logs available per step.
Debug mode for dry-run and troubleshooting.
Step outputs are easily traceable.
Risk assessment
DSL Parsing and Validation - High
Possible Technical Debt
The spec assumes DSL is clean and correct — but real-world users will send malformed or partially invalid JSON.
Parsing variable substitution ${stepID}.output.x could get tricky with deeply nested or optional data.
Missing Detail / Blocker
Is there a defined JSON Schema for the DSL?
How are cycles in the DAG detected?
Are default values or optional parameters supported in steps?
Suggestion: Add a JSON schema spec for DSL + error codes for common DSL validation issues.
Web2Kernel Execution (HTTP) - Medium
Possible Technical Debt
Supporting arbitrary Web2 APIs means supporting all edge cases of HTTP behavior: auth, timeouts, CORS, invalid TLS, streaming responses.
OpenAPI-style request specs can get very large or deeply nested.
Missing Detail / Blocker
Do you support retries or backoff logic?
What happens if a Web2 API returns a non-200 but valid JSON?
Do you validate the response format before passing to the next step?
Suggestion: Define how to handle different response types (JSON, HTML, empty body), auth methods, and error codes.
EVMReadKernel (eth_call) - Medium
Possible Technical Debt
Assumes ABI decoding is successful — but no fallback plan if wrong method signature or contract returns garbage.
Missing Detail / Blocker
How is ABI handled? Do you require ABI JSON? Just the method signature?
Is decoding strict (types must match exactly) or loose?
Suggestion: Document ABI expectations and edge cases (e.g., calling a method that returns nothing or reverts silently).
Concurrency & Execution Engine - High
Possible Technical Debt
Running 1000 workflows in parallel, each with multiple goroutines, could overwhelm memory/CPU quickly.
No mention of backpressure, circuit breakers, or rate-limiting for external API calls.
Missing Detail / Blocker
How are goroutines managed? Is there a worker pool?
How do you throttle Web2 or eth_call executions?
There is many concurrency happened for instance, read IPFS and HTTP request is 2 operation but happened in One Web2 Kernel
Suggestion: Consider a task queue with backpressure limits. Add system-wide config for throttling and load shedding.
Security Assumptions - High
Possible Technical Debt
Lots of trust on input: DSLs, Web2 URLs, ABI strings, etc.
The spec assumes only authenticated users can call krnl_executeKernels with accessToken, but doesn’t describe token validation or threat model.
Missing Detail / Blocker
Who signs the DSL? How is accessToken verified?
Could malicious DSLs DOS the system or leak sensitive info?
Suggestion: Define an auth model for users. Add WAF / rate limit / input sanitization.
Variable Substitution and Data Transform - High
Parser Specification
Variable Specification
Possible Technical Debt
Variable interpolation logic could be brittle if data is missing, types are mismatched, or paths are incorrect.
Type casting rules are not fully defined (e.g., from string to uint256 — is that base-10? base-16?).
Missing Detail / Blocker
Do you support optional chaining or fallback values (?., ||, etc.)?
Is type casting schema-driven or custom logic?
Suggestion: Define transformation grammar and runtime error behavior (e.g., what if a key is missing?).
Logging and Debug Mode - Medium
Possible Technical Debt
Logging everything for debugging might generate sensitive data or blow up disk space.
Missing Detail / Blocker
How are logs stored? How do you trace logs per workflow instance?
Is debug mode safe for prod?
Suggestion: Add a structured logging format (JSON, workflow ID-scoped) and retention policy.
Fail Fast vs Resilience - High
Possible Technical Debt
The system will “fail fast” — but not all errors are equal.
One Web2 timeout shouldn’t crash the entire workflow if it’s not on the critical path.
Missing Detail / Blocker
Can you mark steps as optional or fallback steps?
What retry strategy exists for recoverable failures?
Suggestion: Introduce per-step error policies: fail, retry, skip.
Signer and Final Output Format - High
Possible Technical Debt
The final DataTransform output is signed, but there’s no validation for format or gas cost considerations.
Missing Detail / Blocker
What if the final output exceeds calldata limits?
Who verifies the final output on-chain?
Suggestion: Add size limits and EVM data type validation rules for the final step.
Test Strategy and Linting - Medium
Possible Technical Debt
No mention of a DSL linter, step unit tests, or golden test cases for common workflows.
Suggestion: Add test harness + examples repo for:
Valid workflows
Malformed steps
Edge cases like missing outputs, invalid JSON
Last updated
Was this helpful?