Skip to content

Commit 4e0ed3a

Browse files
committed
Add .slice(0, x) and .slice(x, y.length) bytecode optimisations
1 parent d28151f commit 4e0ed3a

File tree

6 files changed

+47
-1
lines changed

6 files changed

+47
-1
lines changed

packages/cashc/test/cashproof/slice.equiv

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,7 @@
88
# x.split(10)[1].split(15)[0]
99
OP_10 OP_SPLIT OP_NIP OP_15 OP_SPLIT OP_DROP
1010
;
11+
12+
# Slice optimisation
13+
OP_0 OP_SPLIT OP_NIP <=> ;
14+
OP_SIZE OP_SPLIT OP_DROP <=> ;

packages/cashc/test/generation/fixtures.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -878,4 +878,31 @@ export const fixtures: Fixture[] = [
878878
updatedAt: '',
879879
},
880880
},
881+
{
882+
fn: 'slice_optimised.cash',
883+
artifact: {
884+
contractName: 'Slice',
885+
constructorInputs: [{ name: 'data', type: 'bytes32' }],
886+
abi: [{ name: 'spend', inputs: [] }],
887+
bytecode: '14 OP_SPLIT OP_DROP OP_0 14 OP_NUM2BIN OP_EQUAL',
888+
debug: {
889+
bytecode: '01147f750001148087',
890+
sourceMap: '3:34:3:36;:20::37:1;;4:31:4:32:0;:23::33:1;;:8::35',
891+
logs: [],
892+
requires: [
893+
{
894+
ip: 8,
895+
line: 4,
896+
message: undefined,
897+
},
898+
],
899+
},
900+
source: fs.readFileSync(new URL('../valid-contract-files/slice_optimised.cash', import.meta.url), { encoding: 'utf-8' }),
901+
compiler: {
902+
name: 'cashc',
903+
version,
904+
},
905+
updatedAt: '',
906+
},
907+
},
881908
];
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
contract Slice(bytes32 data) {
2+
function spend() {
3+
bytes pkh = data.slice(0, 20);
4+
require(pkh == bytes20(0));
5+
}
6+
}

packages/utils/src/cashproof-optimisations.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,4 +121,8 @@ OP_15 OP_NIP <=> OP_DROP OP_15;
121121
OP_16 OP_NIP <=> OP_DROP OP_16;
122122
123123
OP_2 OP_PICK OP_SWAP OP_2 OP_PICK OP_NIP <=> OP_DROP OP_2DUP;
124+
125+
# .slice(0, x) optimisation & .slice(x, y.length) optimisation
126+
OP_0 OP_SPLIT OP_NIP <=> ;
127+
OP_SIZE OP_SPLIT OP_DROP <=> ;
124128
`;

packages/utils/src/optimisations.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,10 @@ const provableOptimisations = [
114114
['OP_16 OP_NIP', 'OP_DROP OP_16'],
115115

116116
['OP_2 OP_PICK OP_SWAP OP_2 OP_PICK OP_NIP', 'OP_DROP OP_2DUP'],
117+
118+
// .slice(0, x) optimisation & .slice(x, y.length) optimisation
119+
['OP_0 OP_SPLIT OP_NIP', ''],
120+
['OP_SIZE OP_SPLIT OP_DROP', ''],
117121
] as [string, string][];
118122

119123
const unprovableOptimisations = [

website/docs/releases/release-notes.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@ title: Release Notes
66

77
#### cashc compiler
88
- :sparkles: Add `.slice(start, end)` operator for bytes and strings.
9-
- :sparkles: Add bounded bytes typing and bounds checking for `.split()`
9+
- :sparkles: Add bounded bytes typing and bounds checking for `.split()` (includes checking for negative indices)
10+
- :racehorse: Add optimisation for `.slice(0, x)` and `.slice(x, y.length)` (also applies to `.split(0)[1]`)
1011
- :bug: Disallow incorrect bounded bytes typing when using `.split()`
1112

1213
#### CashScript SDK

0 commit comments

Comments
 (0)