2018-12-28 16:53:54 +01:00
|
|
|
import * as types from './types'
|
2018-06-25 08:24:37 +02:00
|
|
|
const bip66 = require('bip66')
|
2018-12-29 13:39:19 +01:00
|
|
|
|
2018-06-25 08:24:37 +02:00
|
|
|
const typeforce = require('typeforce')
|
2018-05-15 02:07:11 +02:00
|
|
|
|
2018-06-25 08:24:37 +02:00
|
|
|
const ZERO = Buffer.alloc(1, 0)
|
2018-12-28 04:59:43 +01:00
|
|
|
function toDER (x: Buffer): Buffer {
|
2018-05-15 02:07:11 +02:00
|
|
|
let i = 0
|
|
|
|
while (x[i] === 0) ++i
|
|
|
|
if (i === x.length) return ZERO
|
|
|
|
x = x.slice(i)
|
|
|
|
if (x[0] & 0x80) return Buffer.concat([ZERO, x], 1 + x.length)
|
|
|
|
return x
|
|
|
|
}
|
|
|
|
|
2018-12-28 04:59:43 +01:00
|
|
|
function fromDER (x: Buffer): Buffer {
|
2018-05-15 02:07:11 +02:00
|
|
|
if (x[0] === 0x00) x = x.slice(1)
|
2018-06-25 08:37:45 +02:00
|
|
|
const buffer = Buffer.alloc(32, 0)
|
|
|
|
const bstart = Math.max(0, 32 - x.length)
|
2018-05-15 02:07:11 +02:00
|
|
|
x.copy(buffer, bstart)
|
|
|
|
return buffer
|
|
|
|
}
|
2016-10-13 14:45:08 +02:00
|
|
|
|
2018-12-28 04:59:43 +01:00
|
|
|
interface ScriptSignature {
|
|
|
|
signature: Buffer
|
|
|
|
hashType: number
|
|
|
|
}
|
|
|
|
|
2016-10-13 14:45:08 +02:00
|
|
|
// BIP62: 1 byte hashType flag (only 0x01, 0x02, 0x03, 0x81, 0x82 and 0x83 are allowed)
|
2018-12-28 04:59:43 +01:00
|
|
|
export function decode (buffer: Buffer): ScriptSignature {
|
2018-06-25 08:37:45 +02:00
|
|
|
const hashType = buffer.readUInt8(buffer.length - 1)
|
|
|
|
const hashTypeMod = hashType & ~0x80
|
2016-10-13 14:45:08 +02:00
|
|
|
if (hashTypeMod <= 0 || hashTypeMod >= 4) throw new Error('Invalid hashType ' + hashType)
|
|
|
|
|
2018-06-25 08:37:45 +02:00
|
|
|
const decode = bip66.decode(buffer.slice(0, -1))
|
|
|
|
const r = fromDER(decode.r)
|
|
|
|
const s = fromDER(decode.s)
|
2016-10-13 14:45:08 +02:00
|
|
|
|
|
|
|
return {
|
2018-05-15 02:07:11 +02:00
|
|
|
signature: Buffer.concat([r, s], 64),
|
2016-10-13 14:45:08 +02:00
|
|
|
hashType: hashType
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-12-28 04:59:43 +01:00
|
|
|
export function encode (signature: Buffer, hashType: number): Buffer {
|
2018-05-15 02:07:11 +02:00
|
|
|
typeforce({
|
|
|
|
signature: types.BufferN(64),
|
|
|
|
hashType: types.UInt8
|
|
|
|
}, { signature, hashType })
|
|
|
|
|
2018-06-25 08:37:45 +02:00
|
|
|
const hashTypeMod = hashType & ~0x80
|
2016-10-13 14:45:08 +02:00
|
|
|
if (hashTypeMod <= 0 || hashTypeMod >= 4) throw new Error('Invalid hashType ' + hashType)
|
|
|
|
|
2018-06-25 08:37:45 +02:00
|
|
|
const hashTypeBuffer = Buffer.allocUnsafe(1)
|
2016-10-13 14:45:08 +02:00
|
|
|
hashTypeBuffer.writeUInt8(hashType, 0)
|
|
|
|
|
2018-06-25 08:37:45 +02:00
|
|
|
const r = toDER(signature.slice(0, 32))
|
|
|
|
const s = toDER(signature.slice(32, 64))
|
2016-10-13 14:45:08 +02:00
|
|
|
|
|
|
|
return Buffer.concat([
|
|
|
|
bip66.encode(r, s),
|
|
|
|
hashTypeBuffer
|
|
|
|
])
|
|
|
|
}
|