Browse Source

Fixed script, script number and signature

fixTypes
junderw 6 years ago
parent
commit
3b77caa4f1
No known key found for this signature in database GPG Key ID: B256185D3A971908
  1. 74
      src/script.ts
  2. 10
      src/script_number.ts
  3. 19
      src/script_signature.ts

74
src/script.ts

@ -10,37 +10,49 @@ const OPS = require('bitcoin-ops')
const REVERSE_OPS = require('bitcoin-ops/map')
const OP_INT_BASE = OPS.OP_RESERVED // OP_1 - 1
function isOPInt (value) {
function isOPInt (value:number): boolean {
return types.Number(value) &&
((value === OPS.OP_0) ||
(value >= OPS.OP_1 && value <= OPS.OP_16) ||
(value === OPS.OP_1NEGATE))
}
function isPushOnlyChunk (value) {
return types.Buffer(value) || isOPInt(value)
function isPushOnlyChunk (value: number | Buffer): boolean {
return types.Buffer(value) || isOPInt(<number>value)
}
function isPushOnly (value) {
export function isPushOnly (value: Array<number | Buffer>) {
return types.Array(value) && value.every(isPushOnlyChunk)
}
function asMinimalOP (buffer) {
function asMinimalOP (buffer: Buffer): number | void {
if (buffer.length === 0) return OPS.OP_0
if (buffer.length !== 1) return
if (buffer[0] >= 1 && buffer[0] <= 16) return OP_INT_BASE + buffer[0]
if (buffer[0] === 0x81) return OPS.OP_1NEGATE
}
function compile (chunks) {
function chunksIsBuffer(buf: Buffer | Array<number | Buffer>): buf is Buffer {
return Buffer.isBuffer(buf)
}
function chunksIsArray(buf: Buffer | Array<number | Buffer>): buf is Array<number | Buffer> {
return types.Array(buf)
}
function singleChunkIsBuffer(buf: number | Buffer): buf is Buffer {
return Buffer.isBuffer(buf)
}
export function compile (chunks: Buffer | Array<number | Buffer>): Buffer {
// TODO: remove me
if (Buffer.isBuffer(chunks)) return chunks
if (chunksIsBuffer(chunks)) return chunks
typeforce(types.Array, chunks)
const bufferSize = chunks.reduce(function (accum, chunk) {
const bufferSize = chunks.reduce(function (accum: number, chunk) {
// data chunk
if (Buffer.isBuffer(chunk)) {
if (singleChunkIsBuffer(chunk)) {
// adhere to BIP62.3, minimal push policy
if (chunk.length === 1 && asMinimalOP(chunk) !== undefined) {
return accum + 1
@ -58,7 +70,7 @@ function compile (chunks) {
chunks.forEach(function (chunk) {
// data chunk
if (Buffer.isBuffer(chunk)) {
if (singleChunkIsBuffer(chunk)) {
// adhere to BIP62.3, minimal push policy
const opcode = asMinimalOP(chunk)
if (opcode !== undefined) {
@ -82,9 +94,9 @@ function compile (chunks) {
return buffer
}
function decompile (buffer) {
export function decompile (buffer: Buffer | Array<number | Buffer>): Array<number | Buffer> {
// TODO: remove me
if (types.Array(buffer)) return buffer
if (chunksIsArray(buffer)) return buffer
typeforce(types.Buffer, buffer)
@ -127,17 +139,17 @@ function decompile (buffer) {
return chunks
}
function toASM (chunks) {
if (Buffer.isBuffer(chunks)) {
export function toASM (chunks: Buffer | Array<number | Buffer>): string {
if (chunksIsBuffer(chunks)) {
chunks = decompile(chunks)
}
return chunks.map(function (chunk) {
// data?
if (Buffer.isBuffer(chunk)) {
if (singleChunkIsBuffer(chunk)) {
const op = asMinimalOP(chunk)
if (op === undefined) return chunk.toString('hex')
chunk = op
chunk = <number>op
}
// opcode!
@ -145,7 +157,7 @@ function toASM (chunks) {
}).join(' ')
}
function fromASM (asm) {
export function fromASM (asm: string): Buffer {
typeforce(types.String, asm)
return compile(asm.split(' ').map(function (chunkStr) {
@ -158,49 +170,35 @@ function fromASM (asm) {
}))
}
function toStack (chunks) {
export function toStack (chunks: Buffer | Array<number | Buffer>): Array<Buffer> {
chunks = decompile(chunks)
typeforce(isPushOnly, chunks)
return chunks.map(function (op) {
if (Buffer.isBuffer(op)) return op
if (singleChunkIsBuffer(op)) return op
if (op === OPS.OP_0) return Buffer.allocUnsafe(0)
return scriptNumber.encode(op - OP_INT_BASE)
})
}
function isCanonicalPubKey (buffer) {
export function isCanonicalPubKey (buffer: Buffer): boolean {
return ecc.isPoint(buffer)
}
function isDefinedHashType (hashType) {
export function isDefinedHashType (hashType: number): boolean {
const hashTypeMod = hashType & ~0x80
// return hashTypeMod > SIGHASH_ALL && hashTypeMod < SIGHASH_SINGLE
return hashTypeMod > 0x00 && hashTypeMod < 0x04
}
function isCanonicalScriptSignature (buffer) {
export function isCanonicalScriptSignature (buffer: Buffer): boolean {
if (!Buffer.isBuffer(buffer)) return false
if (!isDefinedHashType(buffer[buffer.length - 1])) return false
return bip66.check(buffer.slice(0, -1))
}
module.exports = {
compile: compile,
decompile: decompile,
fromASM: fromASM,
toASM: toASM,
toStack: toStack,
number: require('./script_number'),
signature: require('./script_signature'),
isCanonicalPubKey: isCanonicalPubKey,
isCanonicalScriptSignature: isCanonicalScriptSignature,
isPushOnly: isPushOnly,
isDefinedHashType: isDefinedHashType
}
export {}
export const number = require('./script_number')
export const signature = require('./script_signature')

10
src/script_number.ts

@ -1,6 +1,6 @@
const Buffer = require('safe-buffer').Buffer
function decode (buffer, maxLength, minimal) {
export function decode (buffer: Buffer, maxLength?: number, minimal?: boolean): number {
maxLength = maxLength || 4
minimal = minimal === undefined ? true : minimal
@ -41,7 +41,7 @@ function scriptNumSize (i) {
: 0
}
function encode (number) {
export function encode (number: number): Buffer {
let value = Math.abs(number)
const size = scriptNumSize(value)
const buffer = Buffer.allocUnsafe(size)
@ -60,9 +60,3 @@ function encode (number) {
return buffer
}
module.exports = {
decode: decode,
encode: encode
}
export {}

19
src/script_signature.ts

@ -4,7 +4,7 @@ const typeforce = require('typeforce')
const types = require('./types')
const ZERO = Buffer.alloc(1, 0)
function toDER (x) {
function toDER (x: Buffer): Buffer {
let i = 0
while (x[i] === 0) ++i
if (i === x.length) return ZERO
@ -13,7 +13,7 @@ function toDER (x) {
return x
}
function fromDER (x) {
function fromDER (x: Buffer): Buffer {
if (x[0] === 0x00) x = x.slice(1)
const buffer = Buffer.alloc(32, 0)
const bstart = Math.max(0, 32 - x.length)
@ -21,8 +21,13 @@ function fromDER (x) {
return buffer
}
interface ScriptSignature {
signature: Buffer
hashType: number
}
// BIP62: 1 byte hashType flag (only 0x01, 0x02, 0x03, 0x81, 0x82 and 0x83 are allowed)
function decode (buffer) {
export function decode (buffer: Buffer): ScriptSignature {
const hashType = buffer.readUInt8(buffer.length - 1)
const hashTypeMod = hashType & ~0x80
if (hashTypeMod <= 0 || hashTypeMod >= 4) throw new Error('Invalid hashType ' + hashType)
@ -37,7 +42,7 @@ function decode (buffer) {
}
}
function encode (signature, hashType) {
export function encode (signature: Buffer, hashType: number): Buffer {
typeforce({
signature: types.BufferN(64),
hashType: types.UInt8
@ -57,9 +62,3 @@ function encode (signature, hashType) {
hashTypeBuffer
])
}
module.exports = {
decode: decode,
encode: encode
}
export {}

Loading…
Cancel
Save