Skip to content

Commit daa0eeb

Browse files
committed
simplicityhl.md: first pass correcting things
Also remove some LLM-isms, though not all of them. Readers may find this grating to read; should ask a copy-editor or somebody to rewrite it all.
1 parent 09ffcff commit daa0eeb

File tree

1 file changed

+32
-34
lines changed

1 file changed

+32
-34
lines changed

docs/getting-started/simplicityhl.md

Lines changed: 32 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,10 @@ fn main() {
1919
**What this means:**
2020

2121
- Every contract has a `main()` function
22-
- `main()` must return a boolean (implicitly true here)
23-
- No side effects - pure functional programming
22+
- if `main()` does not abort, it is considered to have succeeded; you can think
23+
of "did the function reach its end" as an implicit boolean return
24+
- No side effects other than aborts and read-only access to witness data and the transaction environment
25+
(no state)
2426

2527
### Compiling Contracts
2628

@@ -31,9 +33,9 @@ SimplicityHL compiles to Simplicity bytecode through several stages:
3133
1. **Parse** - Source code to AST
3234
2. **Type Check** - Verify types are correct
3335
3. **Translate** - AST to Simplicity combinators
34-
4. **Commit** - Generate CMR (program hash)
3536

36-
**Result:** A 32-byte CMR that uniquely identifies your contract.
37+
**Result:** A Simplicity program, identified by its unique 32-byte Commitment Merkle Root (CMR).
38+
See "What is the CMR?" below for more information.
3739

3840
---
3941

@@ -43,15 +45,16 @@ SimplicityHL compiles to Simplicity bytecode through several stages:
4345

4446
**On-chain:**
4547
```
46-
Transaction → Simplicity VM → Your Program + Witness → true/false
48+
Transaction → Simplicity VM → Your Program + Witness → abort/pass
4749
```
4850

49-
**If true:** Transaction is valid
50-
**If false:** Transaction is rejected
51+
* **If aborts:** Transaction is rejected
52+
* **Otherwise:** Transaction is valid
5153

52-
**No state:** Contracts are stateless - they validate, not execute arbitrary code.
54+
**No state:** Contracts are stateless - they validate only
5355

54-
**Termination:** All execution terminates (guaranteed to complete).
56+
**Total:** Every program runs in finite time for all inputs (and it is efficiently possible
57+
to compute bounds on this time; see "Cost and Resource Bounds" below
5558

5659
### Witness Data
5760

@@ -236,7 +239,7 @@ fn main() {
236239

237240
**Use case:** Single-signature contract (P2PK)
238241

239-
### Pattern: Time Lock
242+
### Pattern: Absolute Time Lock
240243

241244
```rust
242245
fn main() {
@@ -247,7 +250,7 @@ fn main() {
247250

248251
**Use case:** Timelocked payments, vesting
249252

250-
### Pattern: Time Lock with Distance
253+
### Pattern: Relative Time Lock
251254

252255
```rust
253256
fn main() {
@@ -312,17 +315,18 @@ When your contract executes, it has access to the transaction via jets.
312315

313316
---
314317

315-
## Understanding CMR
318+
## Understanding Commitment Merkle Roots (CMRs)
316319

317-
### What is CMR?
320+
### What is the CMR?
318321

319-
CMR (Commitment Merkle Root) is a 32-byte hash that uniquely identifies your Simplicity program.
322+
A CMR (Commitment Merkle Root) is a 32-byte hash that uniquely identifies your Simplicity program.
320323

321324
**Properties:**
322325

323326
- Same code = same CMR (deterministic)
324-
- Different code = different CMR
325-
- CMR commits to entire program structure
327+
- Different code = different CMR (cryptographically binding)
328+
- CMR commits to entire program structure, **excluding** witness data and program data attached to the `disconnect` combinator
329+
- Same CMR = same contract = same address
326330

327331
**Code reference:** [`rust-simplicity/src/merkle/cmr.rs`](https://github.com/BlockstreamResearch/rust-simplicity/blob/master/src/merkle/cmr.rs)
328332

@@ -332,12 +336,6 @@ CMR (Commitment Merkle Root) is a 32-byte hash that uniquely identifies your Sim
332336
2. Combinators form a Merkle tree
333337
3. CMR is the root hash
334338

335-
**Why it matters:**
336-
337-
- Contracts are identified by CMR
338-
- Same CMR = same contract = same address
339-
- Verified during execution
340-
341339
---
342340

343341
## From Contract to Address
@@ -349,9 +347,7 @@ CMR (Commitment Merkle Root) is a 32-byte hash that uniquely identifies your Sim
349347
```
350348
Your Contract (.simf)
351349
↓ Compile
352-
Simplicity Bytecode
353-
↓ Commit
354-
CMR (32 bytes)
350+
Simplicity Bytecode (identified by its CMR)
355351
↓ Create Taproot Tree
356352
Merkle Root
357353
↓ Combine with Internal Key
@@ -372,17 +368,19 @@ Your Contract (.simf)
372368

373369
### What Gets Signed
374370

375-
When spending a Simplicity contract, signatures commit to a **sighash**.
371+
When spending a Simplicity contract, signatures commit to a **sighash**. A sighash commits to
372+
an arbitrary set of transaction data; typically users want to use the `SIGHASH_ALL` sighash
373+
which commits to the entire transaction and its inputs.
376374

377375
**Code reference:** [`rust-simplicity/src/policy/sighash.rs`](https://github.com/BlockstreamResearch/rust-simplicity/blob/master/src/policy/sighash.rs#L83-L94)
378376

379-
**Sighash includes:**
377+
**`SIGHASH_ALL` includes:**
380378

381379
- All transaction inputs
382380
- All transaction outputs
383381
- Locktime
384382
- Sequence numbers
385-
- **Genesis hash** (network identifier)
383+
- Genesis hash (which acts as a network identifier)
386384
- Spent UTXO data
387385

388386
**Computation:**
@@ -405,7 +403,7 @@ let sighash: [u8; 32] = tx_env.c_tx_env().sighash_all();
405403
let msg: u256 = jet::sig_all_hash(); // Gets the sighash
406404
```
407405

408-
**Why genesis hash matters:**
406+
**Why include the genesis hash?**
409407

410408
Liquid Testnet:
411409
```
@@ -417,9 +415,9 @@ Liquid Mainnet:
417415
1466275836220db2944ca059a3a10ef6fd2ea684b0688d2c3792968888a206003
418416
```
419417

420-
**Different genesis hash = different sighash = signatures won't work across networks.**
421-
422-
This prevents replay attacks.
418+
Including the genesis hash in the signature hash ensures that a given signature can
419+
only work on the network it is intended for, preventing confusion between blockchains
420+
(such as a test network and a production network).
423421

424422
---
425423

@@ -469,7 +467,7 @@ tx.input[0].witness = TxInWitness {
469467

470468
**Limits:**
471469

472-
- Maximum cost: `2^20` (1,048,576)
470+
- Maximum cost: `2^20` (1,048,576) weight units
473471
- Exceeding this makes transaction invalid
474472

475473
**Tools can check contract cost** and show resource usage statistics.
@@ -491,7 +489,7 @@ if let Some(padding) = bounds.cost.get_padding(&script_witness) {
491489
}
492490
```
493491

494-
**Development tools** handle padding automatically.
492+
Development tools handle padding automatically.
495493

496494
---
497495

0 commit comments

Comments
 (0)