Skip to content

Commit 35e9a18

Browse files
committed
Remove all Buffers with Uint8Arrays
1 parent 0e98b11 commit 35e9a18

22 files changed

+120
-179
lines changed

packages/cashc/src/ast/AST.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -315,7 +315,7 @@ export class StringLiteralNode extends LiteralNode {
315315

316316
export class HexLiteralNode extends LiteralNode {
317317
constructor(
318-
public value: Buffer,
318+
public value: Uint8Array,
319319
) {
320320
super();
321321
this.type = new BytesType(value.byteLength);

packages/cashc/src/ast/AstBuilder.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { hexToBin } from '@bitauth/libauth';
12
import { AbstractParseTreeVisitor } from 'antlr4ts/tree/AbstractParseTreeVisitor';
23
import { ParseTree } from 'antlr4ts/tree/ParseTree';
34
import { TerminalNode } from 'antlr4ts/tree/TerminalNode';
@@ -325,7 +326,7 @@ export default class AstBuilder
325326

326327
createHexLiteral(ctx: LiteralContext): HexLiteralNode {
327328
const hexString = (ctx.HexLiteral() as TerminalNode).text;
328-
const hexValue = Buffer.from(hexString.substring(2), 'hex');
329+
const hexValue = hexToBin(hexString.substring(2));
329330
const hexLiteral = new HexLiteralNode(hexValue);
330331
hexLiteral.location = Location.fromCtx(ctx);
331332
return hexLiteral;

packages/cashc/src/cashc-cli.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#! /usr/bin/env node
2-
import { binToHex } from '@bitauth/libauth';
2+
import { binToHex, hexToBin } from '@bitauth/libauth';
33
import { program } from 'commander';
44
import fs from 'fs';
55
import path from 'path';
@@ -49,7 +49,7 @@ function run(): void {
4949
} else if (arg === 'false') {
5050
script.unshift(Data.encodeBool(false));
5151
} else if (arg.startsWith('0x')) {
52-
script.unshift(Buffer.from(arg.substring(2), 'hex'));
52+
script.unshift(hexToBin(arg.substring(2)));
5353
} else if (!Number.isNaN(Number(arg))) {
5454
script.unshift(Data.encodeInt(Number(arg)));
5555
} else {

packages/cashc/src/generation/GenerateTargetTraversal.ts

+9-8
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { hexToBin } from '@bitauth/libauth';
12
import {
23
ContractNode,
34
ParameterNode,
@@ -442,35 +443,35 @@ export default class GenerateTargetTraversal extends AstTraversal {
442443
// <output amount>
443444
this.visit(node.parameters[0]);
444445
// <VarInt 25 bytes> OP_DUP OP_HASH160 OP_PUSH<20>
445-
this.emit(Buffer.from('1976a914', 'hex'));
446+
this.emit(hexToBin('1976a914'));
446447
this.emit(Op.OP_CAT);
447448
// <pkh>
448449
this.visit(node.parameters[1]);
449450
this.emit(Op.OP_CAT);
450451
// OP_EQUAL OP_CHECKSIG
451-
this.emit(Buffer.from('88ac', 'hex'));
452+
this.emit(hexToBin('88ac'));
452453
this.emit(Op.OP_CAT);
453454
this.popFromStack(2);
454455
} else if (node.identifier.name === Class.OUTPUT_P2SH) {
455456
// <output amount>
456457
this.visit(node.parameters[0]);
457458
// <VarInt 23 bytes> OP_HASH160 OP_PUSH<20>
458-
this.emit(Buffer.from('17a914', 'hex'));
459+
this.emit(hexToBin('17a914'));
459460
this.emit(Op.OP_CAT);
460461
// <script hash>
461462
this.visit(node.parameters[1]);
462463
this.emit(Op.OP_CAT);
463464
// OP_EQUAL
464-
this.emit(Buffer.from('87', 'hex'));
465+
this.emit(hexToBin('87'));
465466
this.emit(Op.OP_CAT);
466467
this.popFromStack(2);
467468
} else if (node.identifier.name === Class.OUTPUT_NULLDATA) {
468469
// Total script = bytes8(0) <VarInt> OP_RETURN (<VarInt> <chunk>)+
469470
// <output amount (0)>
470-
this.emit(Buffer.from('0000000000000000', 'hex'));
471+
this.emit(hexToBin('0000000000000000'));
471472
this.pushToStack('(value)');
472473
// OP_RETURN
473-
this.emit(Buffer.from('6a', 'hex'));
474+
this.emit(hexToBin('6a'));
474475
this.pushToStack('(value)');
475476
const { elements } = node.parameters[0] as ArrayNode;
476477
// <VarInt data chunk size (dynamic)>
@@ -481,7 +482,7 @@ export default class GenerateTargetTraversal extends AstTraversal {
481482
if (el instanceof HexLiteralNode) {
482483
// If the argument is a literal, we know its size
483484
if (el.value.byteLength > 75) {
484-
this.emit(Buffer.from('4c', 'hex'));
485+
this.emit(hexToBin('4c'));
485486
this.emit(Op.OP_SWAP);
486487
this.emit(Op.OP_CAT);
487488
}
@@ -491,7 +492,7 @@ export default class GenerateTargetTraversal extends AstTraversal {
491492
this.emit(Data.encodeInt(75));
492493
this.emit(Op.OP_GREATERTHAN);
493494
this.emit(Op.OP_IF);
494-
this.emit(Buffer.from('4c', 'hex'));
495+
this.emit(hexToBin('4c'));
495496
this.emit(Op.OP_SWAP);
496497
this.emit(Op.OP_CAT);
497498
this.emit(Op.OP_ENDIF);

packages/cashc/src/generation/ReplaceBytecodeNop.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ export default class ReplaceBytecodeNop {
1212
// Retrieve size of current cut
1313
script.splice(index, 1);
1414
let oldCut = script[index];
15-
if (oldCut instanceof Buffer) {
15+
if (oldCut instanceof Uint8Array) {
1616
oldCut = Data.decodeInt(oldCut);
1717
} else if (oldCut === Op.OP_0) {
1818
oldCut = 0;

packages/cashc/src/generation/Script.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import { Data } from '../util';
66

77
export const Op = OpcodesBCH;
88
export type Op = number;
9-
export type OpOrData = Op | Buffer;
9+
export type OpOrData = Op | Uint8Array;
1010
export type Script = OpOrData[];
1111

1212
export class toOps {

packages/cashc/src/print/OutputSourceCodeTraversal.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { binToHex } from '@bitauth/libauth';
12
import { SymbolTable } from '../ast/SymbolTable';
23
import {
34
Node,
@@ -237,7 +238,7 @@ export default class OutputSourceCodeTraversal extends AstTraversal {
237238
}
238239

239240
visitHexLiteral(node: HexLiteralNode): Node {
240-
this.addOutput(`0x${node.value.toString('hex')}`);
241+
this.addOutput(`0x${binToHex(node.value)}`);
241242
return node;
242243
}
243244
}

packages/cashc/src/util.ts

+13-11
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ import {
88
disassembleBytecodeBCH,
99
AuthenticationInstructions,
1010
hexToBin,
11+
utf8ToBin,
12+
binToUtf8,
1113
} from '@bitauth/libauth';
1214
import { ANTLRInputStream, CommonTokenStream } from 'antlr4ts';
1315
import fs from 'fs';
@@ -25,11 +27,11 @@ import ReplaceBytecodeNop from './generation/ReplaceBytecodeNop';
2527
import VerifyCovenantTraversal from './semantic/VerifyCovenantTraversal';
2628

2729
export const Data = {
28-
encodeBool(bool: boolean): Buffer {
30+
encodeBool(bool: boolean): Uint8Array {
2931
return bool ? this.encodeInt(1) : this.encodeInt(0);
3032
},
3133

32-
decodeBool(encodedBool: Buffer): boolean {
34+
decodeBool(encodedBool: Uint8Array): boolean {
3335
// Any encoding of 0 is false, else true
3436
for (let i = 0; i < encodedBool.byteLength; i += 1) {
3537
if (encodedBool[i] !== 0) {
@@ -41,11 +43,11 @@ export const Data = {
4143
return false;
4244
},
4345

44-
encodeInt(int: number): Buffer {
45-
return Buffer.from(bigIntToScriptNumber(BigInt(int)));
46+
encodeInt(int: number): Uint8Array {
47+
return bigIntToScriptNumber(BigInt(int));
4648
},
4749

48-
decodeInt(encodedInt: Buffer, maxLength?: number): number {
50+
decodeInt(encodedInt: Uint8Array, maxLength?: number): number {
4951
const options = { maximumScriptNumberByteLength: maxLength };
5052
const result = parseBytesAsScriptNumber(encodedInt, options);
5153

@@ -56,12 +58,12 @@ export const Data = {
5658
return Number(result);
5759
},
5860

59-
encodeString(str: string): Buffer {
60-
return Buffer.from(str, 'ascii');
61+
encodeString(str: string): Uint8Array {
62+
return utf8ToBin(str);
6163
},
6264

63-
decodeString(encodedString: Buffer): string {
64-
return encodedString.toString('ascii');
65+
decodeString(encodedString: Uint8Array): string {
66+
return binToUtf8(encodedString);
6567
},
6668

6769
scriptToAsm(script: Script): string {
@@ -75,7 +77,7 @@ export const Data = {
7577
scriptToBytecode(script: Script): Uint8Array {
7678
// Convert the script elements to AuthenticationInstructions
7779
const instructions = script.map((opOrData) => {
78-
if (opOrData instanceof Buffer) {
80+
if (opOrData instanceof Uint8Array) {
7981
return parseBytecode(encodeDataPush(opOrData))[0];
8082
} else {
8183
return { opcode: opOrData };
@@ -93,7 +95,7 @@ export const Data = {
9395
// Convert the AuthenticationInstructions to script elements
9496
const script = instructions.map((instruction) => {
9597
if ('data' in instruction) {
96-
return Buffer.from(instruction.data);
98+
return instruction.data;
9799
} else {
98100
return instruction.opcode;
99101
}

packages/cashc/test/ast/fixtures.ts

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { hexToBin } from '@bitauth/libauth';
12
import { BytesType, PrimitiveType } from '../../src';
23
import {
34
SourceFileNode,
@@ -447,7 +448,7 @@ export const fixtures: Fixture[] = [
447448
new BinaryOpNode(
448449
new IdentifierNode(PreimageField.BYTECODE),
449450
BinaryOperator.EQ,
450-
new HexLiteralNode(Buffer.from('00', 'hex')),
451+
new HexLiteralNode(hexToBin('00')),
451452
),
452453
),
453454
new RequireNode(
@@ -675,7 +676,7 @@ export const fixtures: Fixture[] = [
675676
new InstantiationNode(
676677
new IdentifierNode(Class.OUTPUT_NULLDATA),
677678
[new ArrayNode([
678-
new HexLiteralNode(Buffer.from('6d02', 'hex')),
679+
new HexLiteralNode(hexToBin('6d02')),
679680
new CastNode(
680681
new BytesType(),
681682
new StringLiteralNode('A contract may not injure a human being or, through inaction, allow a human being to come to harm.', '\''),
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
contract CastHashChecksig() {
22
function hello(pubkey pk, sig s) {
3-
require((ripemd160(bytes(pk)) == hash160(0x0) == !true));
3+
require((ripemd160(bytes(pk)) == hash160(0x) == !true));
44
require(checkSig(s, pk));
55
}
66
}

packages/cashc/test/test-util.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { hexToBin } from '@bitauth/libauth';
12
import { ParseTree } from 'antlr4ts/tree/ParseTree';
23
import { CommonTokenStream, ParserRuleContext } from 'antlr4ts';
34
import { TerminalNode } from 'antlr4ts/tree/TerminalNode';
@@ -19,7 +20,7 @@ export function literalToNode(literal: boolean | number | string): LiteralNode {
1920
} else if (typeof literal === 'number') {
2021
return new IntLiteralNode(literal);
2122
} else if (literal.startsWith('0x')) {
22-
return new HexLiteralNode(Buffer.from(literal.slice(2), 'hex'));
23+
return new HexLiteralNode(hexToBin(literal.slice(2)));
2324
} else {
2425
return new StringLiteralNode(literal, '"');
2526
}

packages/cashscript/src/Contract.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ export class Contract {
4949
}
5050

5151
this.redeemScript = [
52-
...encodedParameters as Buffer[],
52+
...encodedParameters as Uint8Array[],
5353
...Data.asmToScript(this.artifact.bytecode),
5454
];
5555

packages/cashscript/src/Parameter.ts

+9-5
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { hexToBin } from '@bitauth/libauth';
12
import {
23
PrimitiveType,
34
Data,
@@ -7,9 +8,12 @@ import {
78
import { TypeError } from './Errors';
89
import SignatureTemplate from './SignatureTemplate';
910

10-
export type Parameter = number | boolean | string | Buffer | SignatureTemplate;
11+
export type Parameter = number | boolean | string | Uint8Array | SignatureTemplate;
1112

12-
export function encodeParameter(parameter: Parameter, typeStr: string): Buffer | SignatureTemplate {
13+
export function encodeParameter(
14+
parameter: Parameter,
15+
typeStr: string,
16+
): Uint8Array | SignatureTemplate {
1317
const type = parseType(typeStr);
1418
if (type === PrimitiveType.BOOL) {
1519
if (typeof parameter !== 'boolean') {
@@ -28,15 +32,15 @@ export function encodeParameter(parameter: Parameter, typeStr: string): Buffer |
2832
return Data.encodeString(parameter);
2933
} else {
3034
if (type === PrimitiveType.SIG && parameter instanceof SignatureTemplate) return parameter;
31-
// Convert string to Buffer
35+
// Convert string to Uint8Array
3236
if (typeof parameter === 'string') {
3337
if (parameter.startsWith('0x')) {
3438
parameter = parameter.slice(2);
3539
}
36-
parameter = Buffer.from(parameter, 'hex');
40+
parameter = hexToBin(parameter);
3741
}
3842

39-
if (!(parameter instanceof Buffer)) throw Error(); // Shouldn't happen
43+
if (!(parameter instanceof Uint8Array)) throw Error(); // Shouldn't happen
4044

4145
// Bounded bytes types require a correctly sized parameter
4246
if (type instanceof BytesType && type.bound && parameter.byteLength !== type.bound) {

packages/cashscript/src/Transaction.ts

+14-9
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import {
22
bigIntToBinUint64LE,
33
hexToBin,
4-
instantiateSha256,
54
binToHex,
65
encodeTransaction,
76
addressContentsToLockingBytecode,
@@ -30,6 +29,7 @@ import {
3029
sha256,
3130
addressToLockScript,
3231
createSighashPreimage,
32+
placeholder,
3333
} from './util';
3434
import { P2SH_OUTPUT_SIZE, DUST_LIMIT } from './constants';
3535
import NetworkProvider from './network/NetworkProvider';
@@ -52,7 +52,7 @@ export class Transaction {
5252
private provider: NetworkProvider,
5353
private redeemScript: Script,
5454
private abiFunction: AbiFunction,
55-
private parameters: (Buffer | SignatureTemplate)[],
55+
private parameters: (Uint8Array | SignatureTemplate)[],
5656
private selector?: number,
5757
) {}
5858

@@ -176,7 +176,7 @@ export class Transaction {
176176

177177
const signature = utxo.template.generateSignature(sighash, secp256k1);
178178

179-
const inputScript = Data.scriptToBytecode([Buffer.from(signature), Buffer.from(pubkey)]);
179+
const inputScript = Data.scriptToBytecode([signature, pubkey]);
180180
inputScripts.push(inputScript);
181181

182182
return;
@@ -192,7 +192,7 @@ export class Transaction {
192192
const preimage = createSighashPreimage(transaction, utxo, i, bytecode, p.getHashType());
193193
const sighash = sha256(sha256(preimage));
194194

195-
return Buffer.from(p.generateSignature(sighash, secp256k1));
195+
return p.generateSignature(sighash, secp256k1);
196196
});
197197

198198
const preimage = this.abiFunction.covenant
@@ -248,16 +248,21 @@ export class Transaction {
248248
throw Error('Attempted to build a transaction without outputs');
249249
}
250250

251-
// Use a placeholder script with 65-length Buffer in the place of signatures
252-
// and a correctly sized preimage Buffer if the function is a covenant
253-
// for correct size calculation of inputs
251+
// Replace all SignatureTemplate with 65-length placeholder Uint8Arrays
252+
const placeholderParameters = this.parameters.map(p => (
253+
p instanceof SignatureTemplate ? placeholder(65) : p
254+
));
255+
256+
// Create a placeholder preimage of the correct size
254257
const placeholderPreimage = this.abiFunction.covenant
255-
? Buffer.alloc(getPreimageSize(Data.scriptToBytecode(this.redeemScript)), 0)
258+
? placeholder(getPreimageSize(Data.scriptToBytecode(this.redeemScript)))
256259
: undefined;
257260

261+
// Create a placeholder input script for size calculation using the placeholder
262+
// parameters and correctly sized placeholder preimage
258263
const placeholderScript = createInputScript(
259264
this.redeemScript,
260-
this.parameters.map(p => (p instanceof SignatureTemplate ? Buffer.alloc(65, 0) : p)),
265+
placeholderParameters,
261266
this.selector,
262267
placeholderPreimage,
263268
);

packages/cashscript/src/interfaces.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ export interface Recipient {
2020
}
2121

2222
export interface Output {
23-
to: string | Buffer;
23+
to: string | Uint8Array;
2424
amount: number;
2525
}
2626

packages/cashscript/src/network/ElectrumNetworkProvider.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ export default class ElectrumNetworkProvider implements NetworkProvider {
7676

7777
async connectCluster(): Promise<boolean[]> {
7878
try {
79-
return this.electrum.startup();
79+
return await this.electrum.startup();
8080
} catch (e) {
8181
return [];
8282
}

0 commit comments

Comments
 (0)