Skip to content

Commit a346166

Browse files
authored
Merge pull request #370 from CashScript/next
v0.13
2 parents c8320cc + 8447e7a commit a346166

266 files changed

Lines changed: 9522 additions & 4002 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.cspell.json

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,13 +103,17 @@
103103
"locktimes",
104104
"lokad",
105105
"lshift",
106+
"LSHIFTNUM",
107+
"LSHIFTBIN",
106108
"mecenas",
107109
"meep",
108110
"minimaldata",
109111
"minimalif",
110112
"mocknet",
111113
"n",
114+
"narrowings",
112115
"noncompressed",
116+
"nonfinal",
113117
"nonschnorr",
114118
"nops",
115119
"notif",
@@ -154,6 +158,8 @@
154158
"ripemd",
155159
"rosco",
156160
"rshift",
161+
"RSHIFTBIN",
162+
"RSHIFTNUM",
157163
"sablier",
158164
"satoshis",
159165
"sats",
@@ -164,6 +170,7 @@
164170
"segwit",
165171
"setup",
166172
"sig",
173+
"sigchecks",
167174
"sighash",
168175
"signable",
169176
"sigs",
@@ -220,7 +227,9 @@
220227
"chaingraph",
221228
"cherian",
222229
"CSCriptNum",
230+
"deadbeefdeadbeefdeadbeefdeadbeefdeadbeef",
223231
"docu",
232+
"fflate",
224233
"fundme",
225234
"getblockcount",
226235
"getrawtransaction",
@@ -233,13 +242,16 @@
233242
"lichos",
234243
"mainnetjs",
235244
"maxdepth",
245+
"missingorspent",
236246
"moria",
237247
"networkprovider",
238248
"outputnulldata",
239249
"outputp",
240250
"pako",
251+
"paryonusd",
241252
"paytaca",
242253
"popd",
254+
"pusd",
243255
"pushd",
244256
"sendrawtransaction",
245257
"setfiletype",
@@ -250,6 +262,7 @@
250262
"txage",
251263
"txbytecode",
252264
"txhashoutputs",
265+
"txns",
253266
"txtime",
254267
"vite",
255268
"walletconnect",

.eslintrc.cjs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ module.exports = {
3131
'error',
3232
{ allowShortCircuit: true }
3333
],
34+
'@typescript-eslint/no-unused-vars': ['error', { argsIgnorePattern: '^_' }], // Ignore unused variables that start with an underscore
3435
'import/prefer-default-export': 0, // Useful when creating util files that may get expanded
3536
'import/no-extraneous-dependencies': 0, // This gives weird errors
3637
'no-bitwise': 0, // Need to use bitwise operators

.github/workflows/github-actions.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ jobs:
2626
- name: Setup node
2727
uses: actions/setup-node@v3
2828
with:
29-
node-version: 20
29+
node-version: 22
3030

3131
- name: Install dependencies
3232
run: yarn

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,3 +106,5 @@ typings/
106106
.dynamodb/
107107

108108
manual-test.ts
109+
110+
.claude/

AGENTS.md

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
# CLAUDE.md
2+
3+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4+
5+
## Project Overview
6+
7+
CashScript is a high-level language for Bitcoin Cash smart contracts, consisting of a compiler (`cashc`), a TypeScript SDK (`cashscript`), and shared utilities (`@cashscript/utils`). It compiles `.cash` contract files into Bitcoin Cash bytecode artifacts.
8+
9+
## Common Commands
10+
11+
```bash
12+
# Install all dependencies (also runs bootstrap + build)
13+
yarn
14+
15+
# Build all packages (required after code changes to propagate across packages)
16+
yarn build
17+
18+
# Run all tests (uses vitest)
19+
yarn test
20+
21+
# Run tests for a single package
22+
cd packages/cashc && yarn test
23+
cd packages/utils && yarn test
24+
25+
# Run a specific test by name
26+
yarn test -t 'test name from it/describe block'
27+
28+
# Run a single test file directly
29+
yarn vitest run packages/utils/test/bitauth-script.test.ts
30+
31+
# Lint all packages
32+
yarn lint
33+
34+
# Spellcheck
35+
yarn spellcheck
36+
37+
# Regenerate ANTLR parser after grammar changes (from packages/cashc)
38+
yarn antlr
39+
40+
# Run cashscript tests against real chipnet instead of mocknet
41+
TESTS_USE_CHIPNET=true yarn test
42+
```
43+
44+
## Architecture
45+
46+
### Monorepo Structure
47+
48+
Yarn workspaces + Lerna with three main packages:
49+
50+
- **`packages/cashc`** — Compiler: `.cash` source → artifact JSON
51+
- **`packages/cashscript`** — SDK: load artifacts, build and send transactions
52+
- **`packages/utils`** — Shared utilities used by both compiler and SDK
53+
54+
### Compiler Pipeline (`cashc`)
55+
56+
The compilation flow in `compiler.ts`:
57+
58+
1. **Lexing/Parsing** — ANTLR4 grammar (`src/grammar/CashScript.g4`) → parse tree
59+
2. **AST Building**`AstBuilder` converts parse tree → typed AST (`src/ast/`)
60+
3. **Semantic Analysis** — Three traversals in order:
61+
- `SymbolTableTraversal` — resolve identifiers and scopes
62+
- `TypeCheckTraversal` — type checking
63+
- `EnsureFinalRequireTraversal` — validate contract structure
64+
4. **Code Generation**`GenerateTargetTraversal` (`src/generation/`) emits bytecode opcodes, source maps, console logs, requires, and source tags
65+
5. **Optimization**`optimiseBytecode` (`utils/src/script.ts`) applies peephole optimizations, adjusting source maps and metadata indices
66+
6. **Artifact Generation** — produces the final JSON artifact with bytecode, ABI, debug info
67+
68+
The compiler uses the **visitor pattern** throughout — AST nodes accept traversals defined in `AstVisitor`/`AstTraversal`.
69+
70+
### SDK (`cashscript`)
71+
72+
- `Contract` — loads compiled artifacts, instantiates with constructor args
73+
- `TransactionBuilder` — builds and signs Bitcoin Cash transactions
74+
- Network providers: `ElectrumNetworkProvider`, `MockNetworkProvider`
75+
- `src/libauth-template/` — integrates with `@bitauth/libauth` for transaction evaluation and debugging
76+
77+
### Utils (`@cashscript/utils`)
78+
79+
Shared between compiler and SDK:
80+
- `artifact.ts` — artifact type definitions, `DebugInformation` structure
81+
- `script.ts` — bytecode optimization, opcode manipulation
82+
- `source-map.ts` — source map encoding/decoding (format: `sl:sc:el:ec:h` per opcode, `;`-separated, with field inheritance compression)
83+
- `bitauth-script.ts` — formats bytecode as human-readable BitAuth script (used in debugging)
84+
- `types.ts` — shared types including `SourceTagKind`, `SourceTagEntry`
85+
- `optimisations.ts` / `cashproof-optimisations.ts` — peephole optimization rules
86+
87+
## Code Conventions
88+
89+
- **ESM modules** — all packages use ES modules; file extensions required in imports (e.g., `./foo.js`)
90+
- **Max line length**: 125 characters (strings and template literals exempt)
91+
- **Explicit return types** on functions (expressions exempt)
92+
- **Keep nested code to a minimum** — use helper functions to keep code DRY and readable
93+
- Prefer writing code in a way that reads top-down, from the main entry point to the leaves.

CLAUDE.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
@AGENTS.md

README.md

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -27,17 +27,22 @@ npm install -g cashc
2727
### Usage
2828

2929
```bash
30-
Usage: cashc [options] [source_file]
30+
Usage: cashc [options] <source_file>
31+
32+
Arguments:
33+
source_file The source file to compile.
3134

3235
Options:
33-
-V, --version Output the version number.
34-
-o, --output <path> Specify a file to output the generated artifact.
35-
-h, --hex Compile the contract to hex format rather than a full artifact.
36-
-A, --asm Compile the contract to ASM format rather than a full artifact.
37-
-c, --opcount Display the number of opcodes in the compiled bytecode.
38-
-s, --size Display the size in bytes of the compiled bytecode.
39-
-f, --format <format> Specify the format of the output. (choices: "json", "ts", default: "json")
40-
-?, --help Display help
36+
-V, --version Output the version number.
37+
-o, --output <path> Specify a file to output the generated artifact.
38+
-h, --hex Compile the contract to hex format rather than a full artifact.
39+
-A, --asm Compile the contract to ASM format rather than a full artifact.
40+
-c, --opcount Display the number of opcodes in the compiled bytecode.
41+
-s, --size Display the size in bytes of the compiled bytecode.
42+
-S, --skip-enforce-function-parameter-types Do not enforce function parameter types.
43+
-L, --skip-enforce-locktime-guard Do not inject a tx.time guard when tx.locktime is used.
44+
-f, --format <format> Specify the format of the output. (choices: "json", "ts", default: "json")
45+
-?, --help Display help
4146
```
4247

4348
## The CashScript SDK

examples/announcement.cash

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
pragma cashscript ^0.12.0;
1+
pragma cashscript ^0.13.0;
22

33
/* This is a contract showcasing covenants outside of regular transactional use.
44
* It enforces the contract to make an "announcement" on Memo.cash, and send the

examples/announcement.ts

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,25 @@
1-
import { Contract, ElectrumNetworkProvider, Output, TransactionBuilder } from 'cashscript';
1+
import { Contract, Output, randomUtxo, TransactionBuilder } from 'cashscript';
22
import { compileFile } from 'cashc';
33
import { stringify } from '@bitauth/libauth';
44
import { URL } from 'url';
5+
import { MockNetworkProvider } from 'cashscript/dist';
56

67
// Compile the Announcement contract to an artifact object
78
const artifact = compileFile(new URL('announcement.cash', import.meta.url));
89

910
// Initialise a network provider for network operations on MAINNET
10-
const addressType = 'p2sh20';
11-
const provider = new ElectrumNetworkProvider();
11+
const contractType = 'p2sh20';
12+
13+
// Once you're ready to send transactions on a real network (like chipnet or mainnet), use the ElectrumNetworkProvider
14+
// const provider = new ElectrumNetworkProvider();
15+
const provider = new MockNetworkProvider();
1216

1317
// Instantiate a new contract using the compiled artifact and network provider
1418
// AND providing the constructor parameters (none)
15-
const contract = new Contract(artifact, [], { provider, addressType });
19+
const contract = new Contract(artifact, [], { provider, contractType });
20+
21+
// Add a mock UTXO to the mock network provider
22+
provider.addUtxo(contract.address, randomUtxo());
1623

1724
// Get contract balance & output address + balance
1825
console.log('contract address:', contract.address);

examples/hodl_vault.cash

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
pragma cashscript ^0.12.0;
1+
pragma cashscript ^0.13.0;
22

33
// This contract forces HODLing until a certain price target has been reached
44
// A minimum block is provided to ensure that oracle price entries from before this block are disregarded
@@ -11,7 +11,11 @@ contract HodlVault(
1111
int minBlock,
1212
int priceTarget
1313
) {
14-
function spend(sig ownerSig, datasig oracleSig, bytes oracleMessage) {
14+
function spend(
15+
sig ownerSig,
16+
datasig oracleSig,
17+
bytes8 oracleMessage
18+
) {
1519
// message: { blockHeight, price }
1620
bytes4 blockHeightBin, bytes4 priceBin = oracleMessage.split(4);
1721
int blockHeight = int(blockHeightBin);

0 commit comments

Comments
 (0)