@vbyte/btc-dev
Version:
Batteries-included toolset for plebian bitcoin development
81 lines (80 loc) • 2.4 kB
JavaScript
import { Buff, Stream } from '@vbyte/buff';
import { get_asm_code, } from './words.js';
const MAX_WORD_SIZE = 520;
export function encode_script(words, varint = false) {
if (words.length === 0)
return Buff.num(0, 1);
const bytes = [];
for (const word of words) {
bytes.push(encode_script_word(word));
}
const buffer = Buff.join(bytes);
return (varint)
? buffer.prepend(Buff.varint(buffer.length, 'le'))
: buffer;
}
export function encode_script_word(word) {
let buff;
if (typeof (word) === 'string') {
if (word.startsWith('OP_')) {
const asm_code = get_asm_code(word);
return Buff.num(asm_code, 1);
}
else if (Buff.is_hex(word)) {
buff = Buff.hex(word);
}
else {
buff = Buff.str(word);
}
}
else if (typeof (word) === 'number') {
buff = Buff.num(word);
}
else if (word instanceof Uint8Array) {
buff = new Buff(word);
}
else {
throw new Error('invalid word type:' + typeof (word));
}
if (buff.length === 1 && buff[0] <= 16) {
if (buff[0] !== 0)
buff[0] += 0x50;
}
else if (buff.length > MAX_WORD_SIZE) {
let words;
words = split_script_word(buff);
words = words.map(e => prefix_word_size(e));
buff = Buff.join(words);
}
else {
buff = prefix_word_size(buff);
}
return buff;
}
export function split_script_word(word) {
const words = [];
const buff = new Stream(word);
while (buff.size > MAX_WORD_SIZE) {
words.push(buff.read(MAX_WORD_SIZE));
}
words.push(buff.read(buff.size));
return words;
}
export function prefix_word_size(word) {
const varint = get_size_varint(word.length);
return Buff.join([varint, word]);
}
export function get_size_varint(size) {
const OP_PUSHDATA1 = Buff.num(0x4c, 1);
const OP_PUSHDATA2 = Buff.num(0x4d, 1);
switch (true) {
case (size <= 0x4b):
return Buff.num(size);
case (size > 0x4b && size < 0x100):
return Buff.join([OP_PUSHDATA1, Buff.num(size, 1, 'le')]);
case (size >= 0x100 && size <= MAX_WORD_SIZE):
return Buff.join([OP_PUSHDATA2, Buff.num(size, 2, 'le')]);
default:
throw new Error('Invalid word size:' + size.toString());
}
}