Skip to content

Commit e8b7287

Browse files
mr-zwetsrkalis
authored andcommitted
update docs for VM Limits & BigInts
1 parent 78100b2 commit e8b7287

File tree

5 files changed

+54
-15
lines changed

5 files changed

+54
-15
lines changed

website/docs/compiler/vmlimits.md

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
---
2+
title: Bitcoin Cash VM Limits
3+
sidebar_label: VM Limits
4+
---
5+
6+
Bitcoin Cash enforces VM limits to ensure secure and efficient contract execution. When developing with CashScript, keep these limits in mind to ensure your contracts run smoothly without encountering transaction errors due to size or computational constraints.
7+
8+
## Maximum Contract Size
9+
10+
The Bitcoin Cash VM has a **maximum size for smart contracts** which limits the length of input bytecode to **1,650 bytes**. While typical contracts stay well below this, complex contracts with extensive logic might require adjustments to fit within this constraint.
11+
12+
### Modular Contract Design
13+
14+
If your contract includes multiple functions, consider a modular design. Separating contract logic into independent components allows each function to be deployed as a smaller contract, reducing the overall transaction size. This approach can naturally divide complex contracts without impacting functionality. For more on this, see the guide on [Contract Optimization](/docs/guides/optimization).
15+
16+
## Operation Cost Limit
17+
18+
Bitcoin Cash also enforces an **operation cost limit** (op-cost) on each transaction input. The op-cost limit controls the computational budget available for operations in a contract and is calculated based on the input length, with each byte allowing for a higher maximum opereraction cost.
19+
20+
```ts
21+
function maxOperationCost(unlockingBytecodeLength) {
22+
return (41n + unlockingBytecodeLength) * 800n;
23+
}
24+
```
25+
26+
With this formula, increasing your input length allows for a larger compute budget. You can view specific op-costs for each operation in the [op-cost-table][op-cost-table], which outlines the compute cost of operation.
27+
28+
### Buying Compute Budget
29+
30+
To increase your contract's compute budget for resource-intensive operations (e.g., cryptographic hashing or large number calculations), you can use zero-padding to extend the input length. By adding non-essential, zero-value bytes, you effectively buy more computation power for your contract without adding functional complexity. This technique could be useful for contracts requiring a higher operation budget, allowing them to meet the contract's computational demands without exceeding the op-cost limit.
31+
32+
## Other Limits
33+
34+
For completeness, here are additional Bitcoin Cash VM limits relevant to CashScript development:
35+
36+
- **Signature Operation Count** (SigChecks) Limits the number of signature verifications (e.g. `OP_CHECKSIG`, `OP_CHECKDATASIG`) per transaction to ensure efficient validation.
37+
38+
- **Hashing Limit**: Limits the number of hashing operations (e.g. `OP_SHA256`, `OP_HASH160`) allowed per transaction to prevent excessive resource usage.
39+
40+
- **Stack Element Byte Length**: Each stack element has a maximum length of 10,000 bytes. This limit also affects the size of Pay-to-Script-Hash (P2SH) contracts which are pushed as an element to the stack on spending.
41+
42+
[op-cost-table]: https://github.com/bitjson/bch-vm-limits/blob/master/operation-costs.md

website/docs/guides/optimization.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ When optimizing your contract, you will need to compare the contract size to see
1313
With the compiler CLI, you can easily check the opcode count and bytesize directly from the generated contract artifact.
1414

1515
```bash
16-
cashc ./contract.cash --opcount --size
16+
cashc ./contract.cash --size --opcount
1717
```
1818

1919
The size outputs of the `cashc` compiler are based on the bytecode without constructor arguments. This means they will always be an underestimate, as the contract hasn't been initialized with contract arguments.
@@ -23,7 +23,7 @@ The compiler opcount and bytesize outputs are still helpful to compare the effec
2323
:::
2424

2525
:::tip
26-
To get the exact contract opcount and bytesize including constructor parameters, initialise the contract with the TypScript SDK and check the values of `contract.opcount` and `contract.bytesize`.
26+
To get the exact contract bytesize including constructor parameters, initialise the contract with the TypScript SDK and check the value of `contract.bytesize`.
2727
:::
2828

2929
## Optimization Tips & Tricks

website/docs/language/types.md

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ The operators `||` and `&&` don't apply common short-circuiting rules. This mean
2020
:::
2121

2222
## Integer
23-
`int`: Signed integer of 64 bit size.
23+
`int`: Signed integer of arbitrary size (BigInt).
2424

2525
Operators:
2626

@@ -33,14 +33,6 @@ Note the lack of the `**` (exponentiation) operator as well as any bitwise opera
3333

3434
Underscores can be used to separate the digits of a numeric literal to aid readability, e.g. `1_000_000`. Numbers can also be formatted in scientific notation, e.g. `1e6` or `1E6`. These can also be combined, e.g. `1_000e6`.
3535

36-
#### Over- & Underflows
37-
38-
The maximum range for 64-bit integers is `-9223372036854775807` to `9223372036854775807`, operations exceeding these limits will fail the transaction. So operations like summation, subtraction and multiplication should take into account these boundary cases with over- or underflows.
39-
40-
:::caution
41-
Contract authors should always consider whether `+`, `-` and `*` operations can cause under- or overflows and how this would impact contract security.
42-
:::
43-
4436
#### Division by Zero
4537

4638
The script will fail when the right hand side of division or modulo operations is zero.

website/docs/sdk/instantiation.md

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -91,23 +91,27 @@ console.log(contract.tokenAddress)
9191
contract.opcount: number
9292
```
9393

94-
The number of opcodes in the contract's bytecode can be retrieved through the `opcount` member field. This is useful to ensure that the contract is not too big, since Bitcoin Cash smart contracts can contain a maximum of 201 opcodes.
94+
The number of opcodes in the contract's bytecode can be retrieved through the `opcount` member field.
9595

9696
#### Example
9797
```ts
98-
assert(contract.opcount <= 201)
98+
console.log(contract.opcount)
9999
```
100100

101101
### bytesize
102102
```ts
103103
contract.bytesize: number
104104
```
105105

106-
The size of the contract's bytecode in bytes can be retrieved through the `bytesize` member field. This is useful to ensure that the contract is not too big, since Bitcoin Cash smart contracts can be 520 bytes at most.
106+
The size of the contract's bytecode in bytes can be retrieved through the `bytesize` member field. This is useful to ensure that the contract is not too big, since Bitcoin Cash smart contracts can be 1,650 bytes at most.
107+
108+
:::info
109+
The size outputs of the `cashc` compiler are based on the bytecode without constructor arguments. This means they will always be an underestimate, as the contract hasn't been initialized with contract arguments.
110+
:::
107111

108112
#### Example
109113
```ts
110-
console.log(contract.bytesize)
114+
assert(contract.bytesize <= 1650)
111115
```
112116

113117
### bytecode

website/sidebars.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ module.exports = {
2525
label: 'Compiler',
2626
items: [
2727
'compiler/compiler',
28+
'compiler/vmlimits',
2829
'compiler/artifacts',
2930
'compiler/grammar',
3031
],

0 commit comments

Comments
 (0)