When parsing OP_PUSHDATAX commands, the the length of data might not require the size integer of OP_PUSHDATAX. For instance, you might write 1 byte, and yet use OP_PUSHDATA4. We need to record which OP_PUSHDATAX was used so that when we write the buffer back out, we can write the same one. Also, the claimed length may be different. For instance, we may OP_PUSHDATA of length 100 to the stack, but there may only be 50 bytes left in the script. In that case, buf.length and chunk.len will be different. I'm not sure if that would be considered a valid script, but in any case, for script analysis, we need both values.
89 lines
1.9 KiB
JavaScript
89 lines
1.9 KiB
JavaScript
var BufferReader = require('./bufferreader');
|
|
var Opcode = require('./opcode');
|
|
|
|
var Script = function Script(buf) {
|
|
if (!(this instanceof Script))
|
|
return new Script(buf);
|
|
|
|
this.chunks = [];
|
|
|
|
if (Buffer.isBuffer(buf)) {
|
|
this.fromBuffer(buf);
|
|
}
|
|
else if (typeof buf === 'string') {
|
|
var str = buf;
|
|
this.fromString(str);
|
|
}
|
|
else if (typeof buf !== 'undefined') {
|
|
var obj = buf;
|
|
this.set(obj);
|
|
}
|
|
};
|
|
|
|
Script.prototype.set = function(obj) {
|
|
this.chunks = obj.chunks || this.chunks;
|
|
return this;
|
|
};
|
|
|
|
Script.prototype.fromBuffer = function(buf) {
|
|
this.chunks = [];
|
|
|
|
var br = new BufferReader(buf);
|
|
while (!br.eof()) {
|
|
var opcodenum = br.readUInt8();
|
|
|
|
var len, buf;
|
|
if (opcodenum > 0 && opcodenum < Opcode.map.OP_PUSHDATA1) {
|
|
len = opcodenum;
|
|
this.chunks.push({
|
|
buf: br.buffer(len),
|
|
len: len,
|
|
opcodenum: opcodenum
|
|
});
|
|
} else if (opcodenum === Opcode.map.OP_PUSHDATA1) {
|
|
len = br.readUInt8();
|
|
var buf = br.buffer(len);
|
|
this.chunks.push({
|
|
buf: buf,
|
|
len: len,
|
|
opcodenum: opcodenum
|
|
});
|
|
} else if (opcodenum === Opcode.map.OP_PUSHDATA2) {
|
|
len = br.readUInt16LE();
|
|
buf = br.buffer(len);
|
|
this.chunks.push({
|
|
buf: buf,
|
|
len: len,
|
|
opcodenum: opcodenum
|
|
});
|
|
} else if (opcodenum === Opcode.map.OP_PUSHDATA4) {
|
|
len = br.readUInt32LE();
|
|
buf = br.buffer(len);
|
|
this.chunks.push({
|
|
buf: buf,
|
|
len: len,
|
|
opcodenum: opcodenum
|
|
});
|
|
} else {
|
|
this.chunks.push(opcodenum);
|
|
}
|
|
}
|
|
|
|
return this;
|
|
};
|
|
|
|
Script.prototype.toBuffer = function() {
|
|
var bw = new BufferWriter();
|
|
|
|
for (var key in this.chunks) {
|
|
if (this.chunks.hasOwnProperty(key)) {
|
|
var chunk = this.chunks[key];
|
|
if (typeof chunk === 'number') {
|
|
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
module.exports = Script;
|