diff --git a/packages/cashc/src/generation/GenerateTargetTraversal.ts b/packages/cashc/src/generation/GenerateTargetTraversal.ts index df6f3cb92..1286db049 100644 --- a/packages/cashc/src/generation/GenerateTargetTraversal.ts +++ b/packages/cashc/src/generation/GenerateTargetTraversal.ts @@ -950,7 +950,8 @@ export default class GenerateTargetTraversal extends AstTraversal { this.visit(element); // OP_SIZE is a signed VM number, so it is empty for empty elements, and has an extra 0x00 byte for 128-255 bytes. - // In those cases (and for 76-127 bytes) we convert it to a single byte, and prepend OP_PUSHDATA1. + // In those cases (and for 76-127 bytes) we convert it to a single byte, and prepend OP_PUSHDATA1. Chunks over 255 + // bytes are not supported, so the size's high byte has to be 0x00 (an OP_0 would be empty and never match it). this.emit(Op.OP_SIZE, endLocationData); this.emit(Op.OP_DUP, endLocationData); this.emit(encodeInt(1n), endLocationData); @@ -961,7 +962,8 @@ export default class GenerateTargetTraversal extends AstTraversal { this.emit(Op.OP_NUM2BIN, endLocationData); this.emit(encodeInt(1n), endLocationData); this.emit(Op.OP_SPLIT, endLocationData); - this.emit(Op.OP_DROP, endLocationData); + this.emit(hexToBin('00'), endLocationData); + this.emit(Op.OP_EQUALVERIFY, endLocationData); this.emit(hexToBin('4c'), endLocationData); this.emit(Op.OP_SWAP, endLocationData); this.emit(Op.OP_CAT, endLocationData); diff --git a/packages/cashc/test/generation/fixtures/valid-contract-files/locking_bytecode_nulldata_chunks.ts b/packages/cashc/test/generation/fixtures/valid-contract-files/locking_bytecode_nulldata_chunks.ts index 0e947b97a..cac8955ee 100644 --- a/packages/cashc/test/generation/fixtures/valid-contract-files/locking_bytecode_nulldata_chunks.ts +++ b/packages/cashc/test/generation/fixtures/valid-contract-files/locking_bytecode_nulldata_chunks.ts @@ -20,20 +20,20 @@ export const fixtures: Fixture[] = [ // pkh (known length) + '14 OP_3 OP_ROLL OP_CAT OP_CAT ' // data (unknown length) - + 'OP_ROT OP_SIZE OP_DUP OP_1 4c OP_WITHIN OP_NOTIF OP_2 OP_NUM2BIN OP_1 OP_SPLIT OP_DROP 4c OP_SWAP OP_CAT OP_ENDIF ' + + 'OP_ROT OP_SIZE OP_DUP OP_1 4c OP_WITHIN OP_NOTIF OP_2 OP_NUM2BIN OP_1 OP_SPLIT 00 OP_EQUALVERIFY 4c OP_SWAP OP_CAT OP_ENDIF ' + 'OP_SWAP OP_CAT OP_CAT ' // ])); + 'OP_EQUAL', debug: { - bytecode: '8201148800cd016a03026d027e05046d656d6f7e0114537a7e7e7b827651014ca5645280517f75014c7c7e687c7e7e87', - sourceMap: '2:19:2:30;;;4:27:4:28;:16::45:1;:49::112:0;:78::84;::::1;:86::99:0;::::1;:101::104:0;;;::::1;;:106::110:0;::::1;;;;;;;;;;;;;;;;;;:8::114', + bytecode: '8201148800cd016a03026d027e05046d656d6f7e0114537a7e7e7b827651014ca5645280517f010088014c7c7e687c7e7e87', + sourceMap: '2:19:2:30;;;4:27:4:28;:16::45:1;:49::112:0;:78::84;::::1;:86::99:0;::::1;:101::104:0;;;::::1;;:106::110:0;::::1;;;;;;;;;;;;;;;;;;;:8::114', logs: [], requires: [ - { ip: 35, line: 4 }, + { ip: 36, line: 4 }, ], sourceTags: '0:2:pv', }, - fingerprint: '334d3b680b5a80af6ff0a2158f339b6edfd530828669f34b06e7c9aa41556126', + fingerprint: 'd5b78e3ef9d4e50fad5d0c10a5e3cb2a12390b8f18b4795098985801bf0c3e8f', }, }, ]; diff --git a/website/docs/language/globals.md b/website/docs/language/globals.md index 6449e6ef5..d769166f2 100644 --- a/website/docs/language/globals.md +++ b/website/docs/language/globals.md @@ -247,7 +247,7 @@ Creates new P2SH32 locking bytecode for the script hash, where `scriptHash` is t new LockingBytecodeNullData(bytes[] chunks): bytes ``` -Creates new OP_RETURN locking bytecode with `chunks` as its OP_RETURN data. Each chunk is pushed the same way as in the SDK's `addOpReturnOutput()`: with `OP_PUSHDATA1` for empty chunks and chunks of 76-255 bytes, and with a direct push for chunks of 1-75 bytes. Chunks larger than 255 bytes are not supported, and cause a compile error when their size is known at compile time. +Creates new OP_RETURN locking bytecode with `chunks` as its OP_RETURN data. Each chunk is pushed the same way as in the SDK's `addOpReturnOutput()`: with `OP_PUSHDATA1` for empty chunks and chunks of 76-255 bytes, and with a direct push for chunks of 1-75 bytes. Chunks larger than 255 bytes are not supported: they cause a compile error when their size is known at compile time, and fail the contract's execution otherwise. :::note `LockingBytecodeNullData` outputs are provably unspendable, so any BCH sent there would be burned. For these outputs no dust-minimum is enforced so often `LockingBytecodeNullData` outputs have 0 BCH on them.