From 378dc923ef29fa50d0344bfcdbb5bb77fd5d9055 Mon Sep 17 00:00:00 2001 From: "Ryan X. Charles" Date: Mon, 1 Sep 2014 17:27:39 -0700 Subject: [PATCH] preserve claimed length and op code 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. --- lib/script.js | 59 +++++++++++++++++++++++++++++++++++++------------- test/script.js | 10 ++++----- 2 files changed, 49 insertions(+), 20 deletions(-) diff --git a/lib/script.js b/lib/script.js index b8b2ce1..81a4cba 100644 --- a/lib/script.js +++ b/lib/script.js @@ -30,30 +30,59 @@ Script.prototype.fromBuffer = function(buf) { var br = new BufferReader(buf); while (!br.eof()) { - var opcode = br.readUInt8(); + var opcodenum = br.readUInt8(); - var len, chunk; - if (opcode > 0 && opcode < Opcode.map.OP_PUSHDATA1) { - // Read some bytes of data, opcode value is the length of data - this.chunks.push(br.buffer(opcode)); - } else if (opcode === Opcode.map.OP_PUSHDATA1) { + 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(); - chunk = br.buffer(len); - this.chunks.push(chunk); - } else if (opcode === Opcode.map.OP_PUSHDATA2) { + var buf = br.buffer(len); + this.chunks.push({ + buf: buf, + len: len, + opcodenum: opcodenum + }); + } else if (opcodenum === Opcode.map.OP_PUSHDATA2) { len = br.readUInt16LE(); - chunk = br.buffer(len); - this.chunks.push(chunk); - } else if (opcode === Opcode.map.OP_PUSHDATA4) { + buf = br.buffer(len); + this.chunks.push({ + buf: buf, + len: len, + opcodenum: opcodenum + }); + } else if (opcodenum === Opcode.map.OP_PUSHDATA4) { len = br.readUInt32LE(); - chunk = br.buffer(len); - this.chunks.push(chunk); + buf = br.buffer(len); + this.chunks.push({ + buf: buf, + len: len, + opcodenum: opcodenum + }); } else { - this.chunks.push(opcode); + 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; diff --git a/test/script.js b/test/script.js index ceb418b..a034675 100644 --- a/test/script.js +++ b/test/script.js @@ -32,7 +32,7 @@ describe('Script', function() { var buf = new Buffer([3, 1, 2, 3]); var script = Script().fromBuffer(buf); script.chunks.length.should.equal(1); - script.chunks[0].toString('hex').should.equal('010203'); + script.chunks[0].buf.toString('hex').should.equal('010203'); }); it('should parse this buffer containing OP_PUSHDATA1 and three bytes of data', function() { @@ -41,7 +41,7 @@ describe('Script', function() { buf.writeUInt8(3, 1); var script = Script().fromBuffer(buf); script.chunks.length.should.equal(1); - script.chunks[0].toString('hex').should.equal('010203'); + script.chunks[0].buf.toString('hex').should.equal('010203'); }); it('should parse this buffer containing OP_PUSHDATA2 and three bytes of data', function() { @@ -50,7 +50,7 @@ describe('Script', function() { buf.writeUInt16LE(3, 1); var script = Script().fromBuffer(buf); script.chunks.length.should.equal(1); - script.chunks[0].toString('hex').should.equal('010203'); + script.chunks[0].buf.toString('hex').should.equal('010203'); }); it('should parse this buffer containing OP_PUSHDATA4 and three bytes of data', function() { @@ -59,7 +59,7 @@ describe('Script', function() { buf.writeUInt16LE(3, 1); var script = Script().fromBuffer(buf); script.chunks.length.should.equal(1); - script.chunks[0].toString('hex').should.equal('010203'); + script.chunks[0].buf.toString('hex').should.equal('010203'); }); it('should parse this buffer an OP code, data, and another OP code', function() { @@ -71,7 +71,7 @@ describe('Script', function() { var script = Script().fromBuffer(buf); script.chunks.length.should.equal(3); script.chunks[0].should.equal(buf[0]); - script.chunks[1].toString('hex').should.equal('010203'); + script.chunks[1].buf.toString('hex').should.equal('010203'); script.chunks[2].should.equal(buf[buf.length - 1]); });