Skip to content

Commit a0dd4e5

Browse files
authored
Fix datapush for negative numbers
1 parent 2ea6ba9 commit a0dd4e5

File tree

1 file changed

+40
-30
lines changed

1 file changed

+40
-30
lines changed

scripts/compile.js

Lines changed: 40 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -76,40 +76,50 @@ export function preprocessJS(source) {
7676
}
7777

7878

79+
function encodeScriptNumLE(n) {
80+
const neg = n < 0;
81+
let v = Math.abs(n);
82+
const bytes = [];
83+
while (v > 0) { bytes.push(v & 0xff); v >>= 8; }
84+
if (bytes.length === 0) bytes.push(0x00); // zero
85+
86+
const msbIndex = bytes.length - 1;
87+
if (neg) {
88+
if (bytes[msbIndex] & 0x80) {
89+
bytes.push(0x80); // extend and set sign bit
90+
} else {
91+
bytes[msbIndex] |= 0x80; // set sign bit
92+
}
93+
} else {
94+
if (bytes[msbIndex] & 0x80) {
95+
bytes.push(0x00); // avoid being interpreted as negative
96+
}
97+
}
98+
return bytes.map(b => b.toString(16).padStart(2, '0')).join('');
99+
}
79100

80101
export function compileScript(program) {
81-
return preprocessJS(program).split(' ').filter(x => {
82-
// Remove empty entries
83-
return x.trim().length > 0
84-
}).map(x => {
85-
// Keep hashes untouched
86-
if (x.length > 8)
87-
return x
88-
// Parse decimal integer
89-
const int = parseInt(x, 10)
90-
// Keep non-integers untouched
91-
if (isNaN(int))
92-
return x
93-
if(int < 0){
94-
console.log(program)
95-
throw Error('Value should not be negative!')
96-
}
97-
// Construct OP_0 to OP_16
98-
if (0 <= int && int <= 16)
99-
return 'OP_' + int
100-
// Format hexadecimal integer
101-
let hex = int.toString(16)
102-
// Pad hexadecimal digits to byte alignment
103-
hex = hex.padStart(Math.ceil(hex.length / 2) * 2, 0)
104-
// Force integer to be a natural number
105-
if (parseInt(hex.slice(0, 2), 16) >= 0x80) {
106-
hex = '00' + hex
107-
}
108-
// Swap endianness to little endian
109-
return hex.match(/[a-fA-F0-9]{2}/g).reverse().join('')
110-
})
102+
return preprocessJS(program)
103+
.split(' ')
104+
.filter(x => x.trim().length > 0)
105+
.map(x => {
106+
if (x.length > 8) return x; // keep long hex/hash tokens
107+
const int = parseInt(x, 10);
108+
if (isNaN(int)) return x; // non-integers unchanged
109+
110+
// Minimal opcodes for small ints
111+
if (int === 0) return 'OP_0';
112+
if (int === -1) return 'OP_1NEGATE'; // or: return '81' if you want data push
113+
if (1 <= int && int <= 16) return 'OP_' + int;
114+
115+
// Minimal sign-and-magnitude little-endian encoding
116+
return encodeScriptNumLE(int);
117+
});
111118
}
112119

120+
121+
122+
113123
export function replace_unlock_opcodes(script) {
114124
return script.map(opcode => {
115125
switch (opcode) {

0 commit comments

Comments
 (0)