From 91e6c8abc3517571eca08fefe13adc433394d2bb Mon Sep 17 00:00:00 2001
From: junderw <junderwood@bitcoinbank.co.jp>
Date: Wed, 15 Jan 2020 10:44:29 +0900
Subject: [PATCH] Move to bufferutils and add BufferReader

---
 src/buffer_writer.js     |  44 -----------------
 src/bufferutils.js       |  90 +++++++++++++++++++++++++++++++++
 src/transaction.js       |  13 +++--
 ts_src/buffer_writer.ts  |  54 --------------------
 ts_src/bufferutils.ts    | 104 +++++++++++++++++++++++++++++++++++++++
 ts_src/transaction.ts    |   3 +-
 types/buffer_writer.d.ts |  16 ------
 types/bufferutils.d.ts   |  32 ++++++++++++
 8 files changed, 233 insertions(+), 123 deletions(-)
 delete mode 100644 src/buffer_writer.js
 delete mode 100644 ts_src/buffer_writer.ts
 delete mode 100644 types/buffer_writer.d.ts

diff --git a/src/buffer_writer.js b/src/buffer_writer.js
deleted file mode 100644
index 19a2332..0000000
--- a/src/buffer_writer.js
+++ /dev/null
@@ -1,44 +0,0 @@
-'use strict';
-Object.defineProperty(exports, '__esModule', { value: true });
-const bufferutils = require('./bufferutils');
-const types = require('./types');
-const typeforce = require('typeforce');
-const varuint = require('varuint-bitcoin');
-/**
- * Helper class for serialization of bitcoin data types into a pre-allocated buffer.
- */
-class BufferWriter {
-  constructor(buffer, offset = 0) {
-    typeforce(types.tuple(types.Buffer, types.UInt32), [buffer, offset]);
-    this.buffer = buffer;
-    this.offset = offset;
-  }
-  writeUInt8(i) {
-    this.offset = this.buffer.writeUInt8(i, this.offset);
-  }
-  writeInt32(i) {
-    this.offset = this.buffer.writeInt32LE(i, this.offset);
-  }
-  writeUInt32(i) {
-    this.offset = this.buffer.writeUInt32LE(i, this.offset);
-  }
-  writeUInt64(i) {
-    this.offset = bufferutils.writeUInt64LE(this.buffer, i, this.offset);
-  }
-  writeVarInt(i) {
-    varuint.encode(i, this.buffer, this.offset);
-    this.offset += varuint.encode.bytes;
-  }
-  writeSlice(slice) {
-    this.offset += slice.copy(this.buffer, this.offset);
-  }
-  writeVarSlice(slice) {
-    this.writeVarInt(slice.length);
-    this.writeSlice(slice);
-  }
-  writeVector(vector) {
-    this.writeVarInt(vector.length);
-    vector.forEach(buf => this.writeVarSlice(buf));
-  }
-}
-exports.BufferWriter = BufferWriter;
diff --git a/src/bufferutils.js b/src/bufferutils.js
index 54ce1c9..19e8763 100644
--- a/src/bufferutils.js
+++ b/src/bufferutils.js
@@ -1,5 +1,8 @@
 'use strict';
 Object.defineProperty(exports, '__esModule', { value: true });
+const types = require('./types');
+const typeforce = require('typeforce');
+const varuint = require('varuint-bitcoin');
 // https://github.com/feross/buffer/blob/master/index.js#L1127
 function verifuint(value, max) {
   if (typeof value !== 'number')
@@ -38,3 +41,90 @@ function reverseBuffer(buffer) {
   return buffer;
 }
 exports.reverseBuffer = reverseBuffer;
+/**
+ * Helper class for serialization of bitcoin data types into a pre-allocated buffer.
+ */
+class BufferWriter {
+  constructor(buffer, offset = 0) {
+    this.buffer = buffer;
+    this.offset = offset;
+    typeforce(types.tuple(types.Buffer, types.UInt32), [buffer, offset]);
+  }
+  writeUInt8(i) {
+    this.offset = this.buffer.writeUInt8(i, this.offset);
+  }
+  writeInt32(i) {
+    this.offset = this.buffer.writeInt32LE(i, this.offset);
+  }
+  writeUInt32(i) {
+    this.offset = this.buffer.writeUInt32LE(i, this.offset);
+  }
+  writeUInt64(i) {
+    this.offset = writeUInt64LE(this.buffer, i, this.offset);
+  }
+  writeVarInt(i) {
+    varuint.encode(i, this.buffer, this.offset);
+    this.offset += varuint.encode.bytes;
+  }
+  writeSlice(slice) {
+    this.offset += slice.copy(this.buffer, this.offset);
+  }
+  writeVarSlice(slice) {
+    this.writeVarInt(slice.length);
+    this.writeSlice(slice);
+  }
+  writeVector(vector) {
+    this.writeVarInt(vector.length);
+    vector.forEach(buf => this.writeVarSlice(buf));
+  }
+}
+exports.BufferWriter = BufferWriter;
+/**
+ * Helper class for serialization of bitcoin data types into a pre-allocated buffer.
+ */
+class BufferReader {
+  constructor(buffer, offset = 0) {
+    this.buffer = buffer;
+    this.offset = offset;
+    typeforce(types.tuple(types.Buffer, types.UInt32), [buffer, offset]);
+  }
+  readUInt8() {
+    const result = this.buffer.readUInt8(this.offset);
+    this.offset++;
+    return result;
+  }
+  readInt32() {
+    const result = this.buffer.readInt32LE(this.offset);
+    this.offset += 4;
+    return result;
+  }
+  readUInt32() {
+    const result = this.buffer.readUInt32LE(this.offset);
+    this.offset += 4;
+    return result;
+  }
+  readUInt64() {
+    const result = readUInt64LE(this.buffer, this.offset);
+    this.offset += 8;
+    return result;
+  }
+  readVarInt() {
+    const vi = varuint.decode(this.buffer, this.offset);
+    this.offset += varuint.decode.bytes;
+    return vi;
+  }
+  readSlice(n) {
+    this.offset += n;
+    return this.buffer.slice(this.offset - n, this.offset);
+  }
+  readVarSlice() {
+    return this.readSlice(this.readVarInt());
+  }
+  readVector() {
+    const count = this.readVarInt();
+    const vector = [];
+    for (let i = 0; i < count; i++) vector.push(this.readVarSlice());
+    return vector;
+  }
+}
+exports.BufferReader = BufferReader;
diff --git a/src/transaction.js b/src/transaction.js
index fc36a63..ef97900 100644
--- a/src/transaction.js
+++ b/src/transaction.js
@@ -1,6 +1,5 @@
 'use strict';
 Object.defineProperty(exports, '__esModule', { value: true });
-const buffer_writer_1 = require('./buffer_writer');
 const bufferutils = require('./bufferutils');
 const bufferutils_1 = require('./bufferutils');
 const bcrypto = require('./crypto');
@@ -303,7 +302,7 @@ class Transaction {
     let hashSequence = ZERO;
     if (!(hashType & Transaction.SIGHASH_ANYONECANPAY)) {
       tbuffer = Buffer.allocUnsafe(36 * this.ins.length);
-      bufferWriter = new buffer_writer_1.BufferWriter(tbuffer, 0);
+      bufferWriter = new bufferutils_1.BufferWriter(tbuffer, 0);
       this.ins.forEach(txIn => {
         bufferWriter.writeSlice(txIn.hash);
         bufferWriter.writeUInt32(txIn.index);
@@ -316,7 +315,7 @@ class Transaction {
       (hashType & 0x1f) !== Transaction.SIGHASH_NONE
     ) {
       tbuffer = Buffer.allocUnsafe(4 * this.ins.length);
-      bufferWriter = new buffer_writer_1.BufferWriter(tbuffer, 0);
+      bufferWriter = new bufferutils_1.BufferWriter(tbuffer, 0);
       this.ins.forEach(txIn => {
         bufferWriter.writeUInt32(txIn.sequence);
       });
@@ -330,7 +329,7 @@ class Transaction {
         return sum + 8 + varSliceSize(output.script);
       }, 0);
       tbuffer = Buffer.allocUnsafe(txOutsSize);
-      bufferWriter = new buffer_writer_1.BufferWriter(tbuffer, 0);
+      bufferWriter = new bufferutils_1.BufferWriter(tbuffer, 0);
       this.outs.forEach(out => {
         bufferWriter.writeUInt64(out.value);
         bufferWriter.writeVarSlice(out.script);
@@ -342,13 +341,13 @@ class Transaction {
     ) {
       const output = this.outs[inIndex];
       tbuffer = Buffer.allocUnsafe(8 + varSliceSize(output.script));
-      bufferWriter = new buffer_writer_1.BufferWriter(tbuffer, 0);
+      bufferWriter = new bufferutils_1.BufferWriter(tbuffer, 0);
       bufferWriter.writeUInt64(output.value);
       bufferWriter.writeVarSlice(output.script);
       hashOutputs = bcrypto.hash256(tbuffer);
     }
     tbuffer = Buffer.allocUnsafe(156 + varSliceSize(prevOutScript));
-    bufferWriter = new buffer_writer_1.BufferWriter(tbuffer, 0);
+    bufferWriter = new bufferutils_1.BufferWriter(tbuffer, 0);
     const input = this.ins[inIndex];
     bufferWriter.writeUInt32(this.version);
     bufferWriter.writeSlice(hashPrevouts);
@@ -388,7 +387,7 @@ class Transaction {
   }
   __toBuffer(buffer, initialOffset, _ALLOW_WITNESS = false) {
     if (!buffer) buffer = Buffer.allocUnsafe(this.byteLength(_ALLOW_WITNESS));
-    const bufferWriter = new buffer_writer_1.BufferWriter(
+    const bufferWriter = new bufferutils_1.BufferWriter(
       buffer,
       initialOffset || 0,
     );
diff --git a/ts_src/buffer_writer.ts b/ts_src/buffer_writer.ts
deleted file mode 100644
index 541457d..0000000
--- a/ts_src/buffer_writer.ts
+++ /dev/null
@@ -1,54 +0,0 @@
-import * as bufferutils from './bufferutils';
-import * as types from './types';
-
-const typeforce = require('typeforce');
-const varuint = require('varuint-bitcoin');
-
-/**
- * Helper class for serialization of bitcoin data types into a pre-allocated buffer.
- */
-export class BufferWriter {
-  buffer: Buffer;
-  offset: number;
-
-  constructor(buffer: Buffer, offset: number = 0) {
-    typeforce(types.tuple(types.Buffer, types.UInt32), [buffer, offset]);
-    this.buffer = buffer;
-    this.offset = offset;
-  }
-
-  writeUInt8(i: number): void {
-    this.offset = this.buffer.writeUInt8(i, this.offset);
-  }
-
-  writeInt32(i: number): void {
-    this.offset = this.buffer.writeInt32LE(i, this.offset);
-  }
-
-  writeUInt32(i: number): void {
-    this.offset = this.buffer.writeUInt32LE(i, this.offset);
-  }
-
-  writeUInt64(i: number): void {
-    this.offset = bufferutils.writeUInt64LE(this.buffer, i, this.offset);
-  }
-
-  writeVarInt(i: number): void {
-    varuint.encode(i, this.buffer, this.offset);
-    this.offset += varuint.encode.bytes;
-  }
-
-  writeSlice(slice: Buffer): void {
-    this.offset += slice.copy(this.buffer, this.offset);
-  }
-
-  writeVarSlice(slice: Buffer): void {
-    this.writeVarInt(slice.length);
-    this.writeSlice(slice);
-  }
-
-  writeVector(vector: Buffer[]): void {
-    this.writeVarInt(vector.length);
-    vector.forEach((buf: Buffer) => this.writeVarSlice(buf));
-  }
-}
diff --git a/ts_src/bufferutils.ts b/ts_src/bufferutils.ts
index adb6060..6904b73 100644
--- a/ts_src/bufferutils.ts
+++ b/ts_src/bufferutils.ts
@@ -1,3 +1,8 @@
+import * as types from './types';
+
+const typeforce = require('typeforce');
+const varuint = require('varuint-bitcoin');
+
 // https://github.com/feross/buffer/blob/master/index.js#L1127
 function verifuint(value: number, max: number): void {
   if (typeof value !== 'number')
@@ -42,3 +47,102 @@ export function reverseBuffer(buffer: Buffer): Buffer {
   }
   return buffer;
 }
+
+/**
+ * Helper class for serialization of bitcoin data types into a pre-allocated buffer.
+ */
+export class BufferWriter {
+  constructor(private buffer: Buffer, public offset: number = 0) {
+    typeforce(types.tuple(types.Buffer, types.UInt32), [buffer, offset]);
+  }
+
+  writeUInt8(i: number): void {
+    this.offset = this.buffer.writeUInt8(i, this.offset);
+  }
+
+  writeInt32(i: number): void {
+    this.offset = this.buffer.writeInt32LE(i, this.offset);
+  }
+
+  writeUInt32(i: number): void {
+    this.offset = this.buffer.writeUInt32LE(i, this.offset);
+  }
+
+  writeUInt64(i: number): void {
+    this.offset = writeUInt64LE(this.buffer, i, this.offset);
+  }
+
+  writeVarInt(i: number): void {
+    varuint.encode(i, this.buffer, this.offset);
+    this.offset += varuint.encode.bytes;
+  }
+
+  writeSlice(slice: Buffer): void {
+    this.offset += slice.copy(this.buffer, this.offset);
+  }
+
+  writeVarSlice(slice: Buffer): void {
+    this.writeVarInt(slice.length);
+    this.writeSlice(slice);
+  }
+
+  writeVector(vector: Buffer[]): void {
+    this.writeVarInt(vector.length);
+    vector.forEach((buf: Buffer) => this.writeVarSlice(buf));
+  }
+}
+
+/**
+ * Helper class for serialization of bitcoin data types into a pre-allocated buffer.
+ */
+export class BufferReader {
+  constructor(private buffer: Buffer, public offset: number = 0) {
+    typeforce(types.tuple(types.Buffer, types.UInt32), [buffer, offset]);
+  }
+
+  readUInt8(): number {
+    const result = this.buffer.readUInt8(this.offset);
+    this.offset++;
+    return result;
+  }
+
+  readInt32(): number {
+    const result = this.buffer.readInt32LE(this.offset);
+    this.offset += 4;
+    return result;
+  }
+
+  readUInt32(): number {
+    const result = this.buffer.readUInt32LE(this.offset);
+    this.offset += 4;
+    return result;
+  }
+
+  readUInt64(): number {
+    const result = readUInt64LE(this.buffer, this.offset);
+    this.offset += 8;
+    return result;
+  }
+
+  readVarInt(): number {
+    const vi = varuint.decode(this.buffer, this.offset);
+    this.offset += varuint.decode.bytes;
+    return vi;
+  }
+
+  readSlice(n: number): Buffer {
+    this.offset += n;
+    return this.buffer.slice(this.offset - n, this.offset);
+  }
+
+  readVarSlice(): Buffer {
+    return this.readSlice(this.readVarInt());
+  }
+
+  readVector(): Buffer[] {
+    const count = this.readVarInt();
+    const vector: Buffer[] = [];
+    for (let i = 0; i < count; i++) vector.push(this.readVarSlice());
+    return vector;
+  }
+}
diff --git a/ts_src/transaction.ts b/ts_src/transaction.ts
index ac5aea4..3b792ec 100644
--- a/ts_src/transaction.ts
+++ b/ts_src/transaction.ts
@@ -1,6 +1,5 @@
-import { BufferWriter } from './buffer_writer';
 import * as bufferutils from './bufferutils';
-import { reverseBuffer } from './bufferutils';
+import { BufferWriter, reverseBuffer } from './bufferutils';
 import * as bcrypto from './crypto';
 import * as bscript from './script';
 import { OPS as opcodes } from './script';
diff --git a/types/buffer_writer.d.ts b/types/buffer_writer.d.ts
deleted file mode 100644
index 5ff07f9..0000000
--- a/types/buffer_writer.d.ts
+++ /dev/null
@@ -1,16 +0,0 @@
-/**
- * Helper class for serialization of bitcoin data types into a pre-allocated buffer.
- */
-export declare class BufferWriter {
-    buffer: Buffer;
-    offset: number;
-    constructor(buffer: Buffer, offset?: number);
-    writeUInt8(i: number): void;
-    writeInt32(i: number): void;
-    writeUInt32(i: number): void;
-    writeUInt64(i: number): void;
-    writeVarInt(i: number): void;
-    writeSlice(slice: Buffer): void;
-    writeVarSlice(slice: Buffer): void;
-    writeVector(vector: Buffer[]): void;
-}
diff --git a/types/bufferutils.d.ts b/types/bufferutils.d.ts
index 1eff78d..d9e6dc0 100644
--- a/types/bufferutils.d.ts
+++ b/types/bufferutils.d.ts
@@ -1,3 +1,35 @@
 export declare function readUInt64LE(buffer: Buffer, offset: number): number;
 export declare function writeUInt64LE(buffer: Buffer, value: number, offset: number): number;
 export declare function reverseBuffer(buffer: Buffer): Buffer;
+/**
+ * Helper class for serialization of bitcoin data types into a pre-allocated buffer.
+ */
+export declare class BufferWriter {
+    private buffer;
+    offset: number;
+    constructor(buffer: Buffer, offset?: number);
+    writeUInt8(i: number): void;
+    writeInt32(i: number): void;
+    writeUInt32(i: number): void;
+    writeUInt64(i: number): void;
+    writeVarInt(i: number): void;
+    writeSlice(slice: Buffer): void;
+    writeVarSlice(slice: Buffer): void;
+    writeVector(vector: Buffer[]): void;
+}
+/**
+ * Helper class for serialization of bitcoin data types into a pre-allocated buffer.
+ */
+export declare class BufferReader {
+    private buffer;
+    offset: number;
+    constructor(buffer: Buffer, offset?: number);
+    readUInt8(): number;
+    readInt32(): number;
+    readUInt32(): number;
+    readUInt64(): number;
+    readVarInt(): number;
+    readSlice(n: number): Buffer;
+    readVarSlice(): Buffer;
+    readVector(): Buffer[];
+}