@bsv/sdk 1.8.13 → 1.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/package.json +1 -1
- package/dist/cjs/src/auth/Peer.js +35 -16
- package/dist/cjs/src/auth/Peer.js.map +1 -1
- package/dist/cjs/src/primitives/BigNumber.js +43 -31
- package/dist/cjs/src/primitives/BigNumber.js.map +1 -1
- package/dist/cjs/src/primitives/Hash.js +11 -5
- package/dist/cjs/src/primitives/Hash.js.map +1 -1
- package/dist/cjs/src/primitives/SymmetricKey.js +15 -6
- package/dist/cjs/src/primitives/SymmetricKey.js.map +1 -1
- package/dist/cjs/src/primitives/TransactionSignature.js +60 -18
- package/dist/cjs/src/primitives/TransactionSignature.js.map +1 -1
- package/dist/cjs/src/primitives/utils.js +74 -28
- package/dist/cjs/src/primitives/utils.js.map +1 -1
- package/dist/cjs/src/script/Script.js +217 -108
- package/dist/cjs/src/script/Script.js.map +1 -1
- package/dist/cjs/src/script/Spend.js +5 -2
- package/dist/cjs/src/script/Spend.js.map +1 -1
- package/dist/cjs/src/transaction/Beef.js +62 -7
- package/dist/cjs/src/transaction/Beef.js.map +1 -1
- package/dist/cjs/src/transaction/BeefTx.js +1 -1
- package/dist/cjs/src/transaction/BeefTx.js.map +1 -1
- package/dist/cjs/src/transaction/Transaction.js +67 -35
- package/dist/cjs/src/transaction/Transaction.js.map +1 -1
- package/dist/cjs/tsconfig.cjs.tsbuildinfo +1 -1
- package/dist/esm/src/auth/Peer.js +36 -16
- package/dist/esm/src/auth/Peer.js.map +1 -1
- package/dist/esm/src/primitives/BigNumber.js +43 -31
- package/dist/esm/src/primitives/BigNumber.js.map +1 -1
- package/dist/esm/src/primitives/Hash.js +11 -5
- package/dist/esm/src/primitives/Hash.js.map +1 -1
- package/dist/esm/src/primitives/SymmetricKey.js +15 -6
- package/dist/esm/src/primitives/SymmetricKey.js.map +1 -1
- package/dist/esm/src/primitives/TransactionSignature.js +60 -18
- package/dist/esm/src/primitives/TransactionSignature.js.map +1 -1
- package/dist/esm/src/primitives/utils.js +74 -28
- package/dist/esm/src/primitives/utils.js.map +1 -1
- package/dist/esm/src/script/Script.js +222 -110
- package/dist/esm/src/script/Script.js.map +1 -1
- package/dist/esm/src/script/Spend.js +6 -2
- package/dist/esm/src/script/Spend.js.map +1 -1
- package/dist/esm/src/transaction/Beef.js +64 -7
- package/dist/esm/src/transaction/Beef.js.map +1 -1
- package/dist/esm/src/transaction/BeefTx.js +1 -1
- package/dist/esm/src/transaction/BeefTx.js.map +1 -1
- package/dist/esm/src/transaction/Transaction.js +69 -35
- package/dist/esm/src/transaction/Transaction.js.map +1 -1
- package/dist/esm/tsconfig.esm.tsbuildinfo +1 -1
- package/dist/types/src/auth/Peer.d.ts +4 -0
- package/dist/types/src/auth/Peer.d.ts.map +1 -1
- package/dist/types/src/primitives/BigNumber.d.ts.map +1 -1
- package/dist/types/src/primitives/Hash.d.ts +10 -10
- package/dist/types/src/primitives/Hash.d.ts.map +1 -1
- package/dist/types/src/primitives/SymmetricKey.d.ts.map +1 -1
- package/dist/types/src/primitives/TransactionSignature.d.ts +34 -13
- package/dist/types/src/primitives/TransactionSignature.d.ts.map +1 -1
- package/dist/types/src/primitives/utils.d.ts +6 -8
- package/dist/types/src/primitives/utils.d.ts.map +1 -1
- package/dist/types/src/script/Script.d.ts +18 -9
- package/dist/types/src/script/Script.d.ts.map +1 -1
- package/dist/types/src/script/Spend.d.ts +1 -0
- package/dist/types/src/script/Spend.d.ts.map +1 -1
- package/dist/types/src/transaction/Beef.d.ts +9 -0
- package/dist/types/src/transaction/Beef.d.ts.map +1 -1
- package/dist/types/src/transaction/Transaction.d.ts +7 -0
- package/dist/types/src/transaction/Transaction.d.ts.map +1 -1
- package/dist/types/tsconfig.types.tsbuildinfo +1 -1
- package/dist/umd/bundle.js +3 -3
- package/dist/umd/bundle.js.map +1 -1
- package/docs/reference/primitives.md +87 -37
- package/docs/reference/script.md +11 -7
- package/docs/reference/transaction.md +2 -0
- package/package.json +1 -1
- package/src/auth/Peer.ts +44 -18
- package/src/primitives/BigNumber.ts +44 -23
- package/src/primitives/Hash.ts +41 -17
- package/src/primitives/SymmetricKey.ts +15 -6
- package/src/primitives/TransactionSignature.ts +77 -31
- package/src/primitives/utils.ts +80 -30
- package/src/script/Script.ts +238 -104
- package/src/script/Spend.ts +7 -3
- package/src/transaction/Beef.ts +74 -7
- package/src/transaction/BeefTx.ts +1 -1
- package/src/transaction/Transaction.ts +77 -34
package/src/primitives/Hash.ts
CHANGED
|
@@ -613,8 +613,12 @@ export class SHA256 {
|
|
|
613
613
|
this.h = new FastSHA256()
|
|
614
614
|
}
|
|
615
615
|
|
|
616
|
-
update (
|
|
617
|
-
|
|
616
|
+
update (
|
|
617
|
+
msg: Uint8Array | number[] | string,
|
|
618
|
+
enc?: 'hex' | 'utf8'
|
|
619
|
+
): this {
|
|
620
|
+
const data =
|
|
621
|
+
msg instanceof Uint8Array ? msg : Uint8Array.from(toArray(msg, enc))
|
|
618
622
|
this.h.update(data)
|
|
619
623
|
return this
|
|
620
624
|
}
|
|
@@ -778,8 +782,16 @@ export class SHA256HMAC {
|
|
|
778
782
|
* @example
|
|
779
783
|
* const myHMAC = new SHA256HMAC('deadbeef');
|
|
780
784
|
*/
|
|
781
|
-
constructor (key: number[] | string) {
|
|
782
|
-
const k =
|
|
785
|
+
constructor (key: Uint8Array | number[] | string) {
|
|
786
|
+
const k =
|
|
787
|
+
key instanceof Uint8Array
|
|
788
|
+
? key
|
|
789
|
+
: Uint8Array.from(
|
|
790
|
+
toArray(
|
|
791
|
+
key,
|
|
792
|
+
typeof key === 'string' ? 'hex' : undefined
|
|
793
|
+
)
|
|
794
|
+
)
|
|
783
795
|
this.h = new HMAC(sha256Fast, k)
|
|
784
796
|
}
|
|
785
797
|
|
|
@@ -794,8 +806,10 @@ export class SHA256HMAC {
|
|
|
794
806
|
* @example
|
|
795
807
|
* myHMAC.update('deadbeef', 'hex');
|
|
796
808
|
*/
|
|
797
|
-
update (msg: number[] | string, enc?: 'hex'): SHA256HMAC {
|
|
798
|
-
|
|
809
|
+
update (msg: Uint8Array | number[] | string, enc?: 'hex'): SHA256HMAC {
|
|
810
|
+
const data =
|
|
811
|
+
msg instanceof Uint8Array ? msg : Uint8Array.from(toArray(msg, enc))
|
|
812
|
+
this.h.update(data)
|
|
799
813
|
return this
|
|
800
814
|
}
|
|
801
815
|
|
|
@@ -902,8 +916,16 @@ export class SHA512HMAC {
|
|
|
902
916
|
* @example
|
|
903
917
|
* const myHMAC = new SHA512HMAC('deadbeef');
|
|
904
918
|
*/
|
|
905
|
-
constructor (key: number[] | string) {
|
|
906
|
-
const k =
|
|
919
|
+
constructor (key: Uint8Array | number[] | string) {
|
|
920
|
+
const k =
|
|
921
|
+
key instanceof Uint8Array
|
|
922
|
+
? key
|
|
923
|
+
: Uint8Array.from(
|
|
924
|
+
toArray(
|
|
925
|
+
key,
|
|
926
|
+
typeof key === 'string' ? 'hex' : undefined
|
|
927
|
+
)
|
|
928
|
+
)
|
|
907
929
|
this.h = new HMAC(sha512Fast, k)
|
|
908
930
|
}
|
|
909
931
|
|
|
@@ -918,8 +940,10 @@ export class SHA512HMAC {
|
|
|
918
940
|
* @example
|
|
919
941
|
* myHMAC.update('deadbeef', 'hex');
|
|
920
942
|
*/
|
|
921
|
-
update (msg: number[] | string, enc?: 'hex' | 'utf8'): SHA512HMAC {
|
|
922
|
-
|
|
943
|
+
update (msg: Uint8Array | number[] | string, enc?: 'hex' | 'utf8'): SHA512HMAC {
|
|
944
|
+
const data =
|
|
945
|
+
msg instanceof Uint8Array ? msg : Uint8Array.from(toArray(msg, enc))
|
|
946
|
+
this.h.update(data)
|
|
923
947
|
return this
|
|
924
948
|
}
|
|
925
949
|
|
|
@@ -998,7 +1022,7 @@ export const sha1 = (
|
|
|
998
1022
|
* const digest = sha256('Hello, world!');
|
|
999
1023
|
*/
|
|
1000
1024
|
export const sha256 = (
|
|
1001
|
-
msg: number[] | string,
|
|
1025
|
+
msg: Uint8Array | number[] | string,
|
|
1002
1026
|
enc?: 'hex' | 'utf8'
|
|
1003
1027
|
): number[] => {
|
|
1004
1028
|
return new SHA256().update(msg, enc).digest()
|
|
@@ -1036,7 +1060,7 @@ export const sha512 = (
|
|
|
1036
1060
|
* const doubleHash = hash256('Hello, world!');
|
|
1037
1061
|
*/
|
|
1038
1062
|
export const hash256 = (
|
|
1039
|
-
msg: number[] | string,
|
|
1063
|
+
msg: Uint8Array | number[] | string,
|
|
1040
1064
|
enc?: 'hex' | 'utf8'
|
|
1041
1065
|
): number[] => {
|
|
1042
1066
|
const first = new SHA256().update(msg, enc).digest()
|
|
@@ -1056,7 +1080,7 @@ export const hash256 = (
|
|
|
1056
1080
|
* const hash = hash160('Hello, world!');
|
|
1057
1081
|
*/
|
|
1058
1082
|
export const hash160 = (
|
|
1059
|
-
msg: number[] | string,
|
|
1083
|
+
msg: Uint8Array | number[] | string,
|
|
1060
1084
|
enc?: 'hex' | 'utf8'
|
|
1061
1085
|
): number[] => {
|
|
1062
1086
|
const first = new SHA256().update(msg, enc).digest()
|
|
@@ -1076,8 +1100,8 @@ export const hash160 = (
|
|
|
1076
1100
|
* const digest = sha256hmac('deadbeef', 'ffff001d');
|
|
1077
1101
|
*/
|
|
1078
1102
|
export const sha256hmac = (
|
|
1079
|
-
key: number[] | string,
|
|
1080
|
-
msg: number[] | string,
|
|
1103
|
+
key: Uint8Array | number[] | string,
|
|
1104
|
+
msg: Uint8Array | number[] | string,
|
|
1081
1105
|
enc?: 'hex'
|
|
1082
1106
|
): number[] => {
|
|
1083
1107
|
return new SHA256HMAC(key).update(msg, enc).digest()
|
|
@@ -1096,8 +1120,8 @@ export const sha256hmac = (
|
|
|
1096
1120
|
* const digest = sha512hmac('deadbeef', 'ffff001d');
|
|
1097
1121
|
*/
|
|
1098
1122
|
export const sha512hmac = (
|
|
1099
|
-
key: number[] | string,
|
|
1100
|
-
msg: number[] | string,
|
|
1123
|
+
key: Uint8Array | number[] | string,
|
|
1124
|
+
msg: Uint8Array | number[] | string,
|
|
1101
1125
|
enc?: 'hex'
|
|
1102
1126
|
): number[] => {
|
|
1103
1127
|
return new SHA512HMAC(key).update(msg, enc).digest()
|
|
@@ -43,13 +43,22 @@ export default class SymmetricKey extends BigNumber {
|
|
|
43
43
|
encrypt (msg: number[] | string, enc?: 'hex'): string | number[] {
|
|
44
44
|
const iv = Random(32)
|
|
45
45
|
msg = toArray(msg, enc)
|
|
46
|
+
const keyBytes = this.toArray('be', 32)
|
|
46
47
|
const { result, authenticationTag } = AESGCM(
|
|
47
48
|
msg,
|
|
48
49
|
[],
|
|
49
50
|
iv,
|
|
50
|
-
|
|
51
|
+
keyBytes
|
|
51
52
|
)
|
|
52
|
-
|
|
53
|
+
const totalLength = iv.length + result.length + authenticationTag.length
|
|
54
|
+
const combined = new Array(totalLength)
|
|
55
|
+
let offset = 0
|
|
56
|
+
for (const chunk of [iv, result, authenticationTag]) {
|
|
57
|
+
for (let i = 0; i < chunk.length; i++) {
|
|
58
|
+
combined[offset++] = chunk[i]
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return encode(combined, enc)
|
|
53
62
|
}
|
|
54
63
|
|
|
55
64
|
/**
|
|
@@ -71,15 +80,15 @@ export default class SymmetricKey extends BigNumber {
|
|
|
71
80
|
decrypt (msg: number[] | string, enc?: 'hex' | 'utf8'): string | number[] {
|
|
72
81
|
msg = toArray(msg, enc)
|
|
73
82
|
const iv = msg.slice(0, 32)
|
|
74
|
-
const
|
|
75
|
-
const
|
|
76
|
-
const
|
|
83
|
+
const tagStart = msg.length - 16
|
|
84
|
+
const ciphertext = msg.slice(32, tagStart)
|
|
85
|
+
const messageTag = msg.slice(tagStart)
|
|
77
86
|
const result = AESGCMDecrypt(
|
|
78
87
|
ciphertext,
|
|
79
88
|
[],
|
|
80
89
|
iv,
|
|
81
90
|
messageTag,
|
|
82
|
-
this.toArray()
|
|
91
|
+
this.toArray('be', 32)
|
|
83
92
|
)
|
|
84
93
|
if (result === null) {
|
|
85
94
|
throw new Error('Decryption failed!')
|
|
@@ -6,6 +6,30 @@ import Script from '../script/Script.js'
|
|
|
6
6
|
import TransactionInput from '../transaction/TransactionInput.js'
|
|
7
7
|
import TransactionOutput from '../transaction/TransactionOutput.js'
|
|
8
8
|
|
|
9
|
+
export interface SignatureHashCache {
|
|
10
|
+
hashPrevouts?: number[]
|
|
11
|
+
hashSequence?: number[]
|
|
12
|
+
hashOutputsAll?: number[]
|
|
13
|
+
hashOutputsSingle?: Map<number, number[]>
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
interface TransactionSignatureFormatParams {
|
|
17
|
+
sourceTXID: string
|
|
18
|
+
sourceOutputIndex: number
|
|
19
|
+
sourceSatoshis: number
|
|
20
|
+
transactionVersion: number
|
|
21
|
+
otherInputs: TransactionInput[]
|
|
22
|
+
outputs: TransactionOutput[]
|
|
23
|
+
inputIndex: number
|
|
24
|
+
subscript: Script
|
|
25
|
+
inputSequence: number
|
|
26
|
+
lockTime: number
|
|
27
|
+
scope: number
|
|
28
|
+
cache?: SignatureHashCache
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const EMPTY_SCRIPT = new Uint8Array(0)
|
|
32
|
+
|
|
9
33
|
export default class TransactionSignature extends Signature {
|
|
10
34
|
public static readonly SIGHASH_ALL = 0x00000001
|
|
11
35
|
public static readonly SIGHASH_NONE = 0x00000002
|
|
@@ -15,19 +39,23 @@ export default class TransactionSignature extends Signature {
|
|
|
15
39
|
|
|
16
40
|
scope: number
|
|
17
41
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
42
|
+
/**
|
|
43
|
+
* Formats the SIGHASH preimage for the targeted input, optionally using a cache to skip recomputing shared hash prefixes.
|
|
44
|
+
* @param params - Context for the signing input plus transaction metadata.
|
|
45
|
+
* @param params.cache - Optional cache storing previously computed `hashPrevouts`, `hashSequence`, or `hashOutputs*` values; it will be populated if present.
|
|
46
|
+
*/
|
|
47
|
+
static format (params: TransactionSignatureFormatParams): number[] {
|
|
48
|
+
return Array.from(this.formatBytes(params))
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Formats the same SIGHASH preimage bytes as `format`, supporting the optional cache for hash reuse.
|
|
53
|
+
* @param params - Context for the signing operation.
|
|
54
|
+
* @param params.cache - Optional `SignatureHashCache` that may already contain hashed prefixes and is populated during formatting.
|
|
55
|
+
* @returns Bytes for signing.
|
|
56
|
+
*/
|
|
57
|
+
static formatBytes (params: TransactionSignatureFormatParams): Uint8Array {
|
|
58
|
+
const cache = params.cache
|
|
31
59
|
const currentInput = {
|
|
32
60
|
sourceTXID: params.sourceTXID,
|
|
33
61
|
sourceOutputIndex: params.sourceOutputIndex,
|
|
@@ -51,9 +79,7 @@ export default class TransactionSignature extends Signature {
|
|
|
51
79
|
writer.writeUInt32LE(input.sourceOutputIndex)
|
|
52
80
|
}
|
|
53
81
|
|
|
54
|
-
|
|
55
|
-
const ret = Hash.hash256(buf)
|
|
56
|
-
return ret
|
|
82
|
+
return Hash.hash256(writer.toUint8Array())
|
|
57
83
|
}
|
|
58
84
|
|
|
59
85
|
const getSequenceHash = (): number[] => {
|
|
@@ -64,9 +90,7 @@ export default class TransactionSignature extends Signature {
|
|
|
64
90
|
writer.writeUInt32LE(sequence)
|
|
65
91
|
}
|
|
66
92
|
|
|
67
|
-
|
|
68
|
-
const ret = Hash.hash256(buf)
|
|
69
|
-
return ret
|
|
93
|
+
return Hash.hash256(writer.toUint8Array())
|
|
70
94
|
}
|
|
71
95
|
|
|
72
96
|
function getOutputsHash (outputIndex?: number): number[] {
|
|
@@ -77,7 +101,7 @@ export default class TransactionSignature extends Signature {
|
|
|
77
101
|
const satoshis = output.satoshis ?? 0 // Default to 0 if undefined
|
|
78
102
|
writer.writeUInt64LE(satoshis)
|
|
79
103
|
|
|
80
|
-
const script = output.lockingScript?.
|
|
104
|
+
const script = output.lockingScript?.toUint8Array() ?? EMPTY_SCRIPT
|
|
81
105
|
writer.writeVarIntNum(script.length)
|
|
82
106
|
writer.write(script)
|
|
83
107
|
}
|
|
@@ -91,14 +115,12 @@ export default class TransactionSignature extends Signature {
|
|
|
91
115
|
const satoshis = output.satoshis ?? 0 // Default to 0 if undefined
|
|
92
116
|
writer.writeUInt64LE(satoshis)
|
|
93
117
|
|
|
94
|
-
const script = output.lockingScript?.
|
|
118
|
+
const script = output.lockingScript?.toUint8Array() ?? EMPTY_SCRIPT
|
|
95
119
|
writer.writeVarIntNum(script.length)
|
|
96
120
|
writer.write(script)
|
|
97
121
|
}
|
|
98
122
|
|
|
99
|
-
|
|
100
|
-
const ret = Hash.hash256(buf)
|
|
101
|
-
return ret
|
|
123
|
+
return Hash.hash256(writer.toUint8Array())
|
|
102
124
|
}
|
|
103
125
|
|
|
104
126
|
let hashPrevouts = new Array(32).fill(0)
|
|
@@ -106,7 +128,12 @@ export default class TransactionSignature extends Signature {
|
|
|
106
128
|
let hashOutputs = new Array(32).fill(0)
|
|
107
129
|
|
|
108
130
|
if ((params.scope & TransactionSignature.SIGHASH_ANYONECANPAY) === 0) {
|
|
109
|
-
hashPrevouts
|
|
131
|
+
if (cache?.hashPrevouts != null) {
|
|
132
|
+
hashPrevouts = cache.hashPrevouts
|
|
133
|
+
} else {
|
|
134
|
+
hashPrevouts = getPrevoutHash()
|
|
135
|
+
if (cache != null) cache.hashPrevouts = hashPrevouts
|
|
136
|
+
}
|
|
110
137
|
}
|
|
111
138
|
|
|
112
139
|
if (
|
|
@@ -114,19 +141,39 @@ export default class TransactionSignature extends Signature {
|
|
|
114
141
|
(params.scope & 31) !== TransactionSignature.SIGHASH_SINGLE &&
|
|
115
142
|
(params.scope & 31) !== TransactionSignature.SIGHASH_NONE
|
|
116
143
|
) {
|
|
117
|
-
hashSequence
|
|
144
|
+
if (cache?.hashSequence != null) {
|
|
145
|
+
hashSequence = cache.hashSequence
|
|
146
|
+
} else {
|
|
147
|
+
hashSequence = getSequenceHash()
|
|
148
|
+
if (cache != null) cache.hashSequence = hashSequence
|
|
149
|
+
}
|
|
118
150
|
}
|
|
119
151
|
|
|
120
152
|
if (
|
|
121
153
|
(params.scope & 31) !== TransactionSignature.SIGHASH_SINGLE &&
|
|
122
154
|
(params.scope & 31) !== TransactionSignature.SIGHASH_NONE
|
|
123
155
|
) {
|
|
124
|
-
|
|
156
|
+
if (cache?.hashOutputsAll != null) {
|
|
157
|
+
hashOutputs = cache.hashOutputsAll
|
|
158
|
+
} else {
|
|
159
|
+
hashOutputs = getOutputsHash()
|
|
160
|
+
if (cache != null) cache.hashOutputsAll = hashOutputs
|
|
161
|
+
}
|
|
125
162
|
} else if (
|
|
126
163
|
(params.scope & 31) === TransactionSignature.SIGHASH_SINGLE &&
|
|
127
164
|
params.inputIndex < params.outputs.length
|
|
128
165
|
) {
|
|
129
|
-
|
|
166
|
+
const key = params.inputIndex
|
|
167
|
+
const cachedSingle = cache?.hashOutputsSingle?.get(key)
|
|
168
|
+
if (cachedSingle != null) {
|
|
169
|
+
hashOutputs = cachedSingle
|
|
170
|
+
} else {
|
|
171
|
+
hashOutputs = getOutputsHash(key)
|
|
172
|
+
if (cache != null) {
|
|
173
|
+
if (cache.hashOutputsSingle == null) cache.hashOutputsSingle = new Map()
|
|
174
|
+
cache.hashOutputsSingle.set(key, hashOutputs)
|
|
175
|
+
}
|
|
176
|
+
}
|
|
130
177
|
}
|
|
131
178
|
|
|
132
179
|
const writer = new Writer()
|
|
@@ -143,7 +190,7 @@ export default class TransactionSignature extends Signature {
|
|
|
143
190
|
writer.writeUInt32LE(params.sourceOutputIndex)
|
|
144
191
|
|
|
145
192
|
// scriptCode of the input (serialized as scripts inside CTxOuts)
|
|
146
|
-
const subscriptBin = params.subscript.
|
|
193
|
+
const subscriptBin = params.subscript.toUint8Array()
|
|
147
194
|
writer.writeVarIntNum(subscriptBin.length)
|
|
148
195
|
writer.write(subscriptBin)
|
|
149
196
|
|
|
@@ -163,8 +210,7 @@ export default class TransactionSignature extends Signature {
|
|
|
163
210
|
// sighashType
|
|
164
211
|
writer.writeUInt32LE(params.scope >>> 0)
|
|
165
212
|
|
|
166
|
-
|
|
167
|
-
return buf
|
|
213
|
+
return writer.toUint8Array()
|
|
168
214
|
}
|
|
169
215
|
|
|
170
216
|
// The format used in a tx
|
package/src/primitives/utils.ts
CHANGED
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
import BigNumber from './BigNumber.js'
|
|
2
2
|
import { hash256 } from './Hash.js'
|
|
3
3
|
|
|
4
|
+
const BufferCtor =
|
|
5
|
+
typeof globalThis !== 'undefined' ? (globalThis as any).Buffer : undefined
|
|
6
|
+
const CAN_USE_BUFFER =
|
|
7
|
+
BufferCtor != null && typeof BufferCtor.from === 'function'
|
|
8
|
+
const PURE_HEX_REGEX = /^[0-9a-fA-F]+$/
|
|
9
|
+
|
|
4
10
|
/**
|
|
5
11
|
* Prepends a '0' to an odd character length word to ensure it has an even number of characters.
|
|
6
12
|
* @param {string} word - The input word.
|
|
@@ -19,12 +25,23 @@ export const zero2 = (word: string): string => {
|
|
|
19
25
|
* @param {number[]} msg - The input array of numbers.
|
|
20
26
|
* @returns {string} - The hexadecimal string representation of the input array.
|
|
21
27
|
*/
|
|
28
|
+
const HEX_DIGITS = '0123456789abcdef'
|
|
29
|
+
const HEX_BYTE_STRINGS: string[] = new Array(256)
|
|
30
|
+
for (let i = 0; i < 256; i++) {
|
|
31
|
+
HEX_BYTE_STRINGS[i] =
|
|
32
|
+
HEX_DIGITS[(i >> 4) & 0xf] + HEX_DIGITS[i & 0xf]
|
|
33
|
+
}
|
|
34
|
+
|
|
22
35
|
export const toHex = (msg: number[]): string => {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
res += zero2(num.toString(16))
|
|
36
|
+
if (CAN_USE_BUFFER) {
|
|
37
|
+
return BufferCtor.from(msg).toString('hex')
|
|
26
38
|
}
|
|
27
|
-
return
|
|
39
|
+
if (msg.length === 0) return ''
|
|
40
|
+
const out = new Array(msg.length)
|
|
41
|
+
for (let i = 0; i < msg.length; i++) {
|
|
42
|
+
out[i] = HEX_BYTE_STRINGS[msg[i] & 0xff]
|
|
43
|
+
}
|
|
44
|
+
return out.join('')
|
|
28
45
|
}
|
|
29
46
|
|
|
30
47
|
/**
|
|
@@ -53,13 +70,37 @@ export const toArray = (msg: any, enc?: 'hex' | 'utf8' | 'base64'): any[] => {
|
|
|
53
70
|
}
|
|
54
71
|
}
|
|
55
72
|
|
|
73
|
+
const HEX_CHAR_TO_VALUE = new Int8Array(256).fill(-1)
|
|
74
|
+
for (let i = 0; i < 10; i++) {
|
|
75
|
+
HEX_CHAR_TO_VALUE[48 + i] = i // '0'-'9'
|
|
76
|
+
}
|
|
77
|
+
for (let i = 0; i < 6; i++) {
|
|
78
|
+
HEX_CHAR_TO_VALUE[65 + i] = 10 + i // 'A'-'F'
|
|
79
|
+
HEX_CHAR_TO_VALUE[97 + i] = 10 + i // 'a'-'f'
|
|
80
|
+
}
|
|
81
|
+
|
|
56
82
|
const hexToArray = (msg: string): number[] => {
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
83
|
+
if (CAN_USE_BUFFER && PURE_HEX_REGEX.test(msg)) {
|
|
84
|
+
const normalized = msg.length % 2 === 0 ? msg : '0' + msg
|
|
85
|
+
return Array.from(BufferCtor.from(normalized, 'hex'))
|
|
86
|
+
}
|
|
87
|
+
const res: number[] = new Array(Math.ceil(msg.length / 2))
|
|
88
|
+
let nibble = -1
|
|
89
|
+
let size = 0
|
|
90
|
+
for (let i = 0; i < msg.length; i++) {
|
|
91
|
+
const value = HEX_CHAR_TO_VALUE[msg.charCodeAt(i)]
|
|
92
|
+
if (value === -1) continue
|
|
93
|
+
if (nibble === -1) {
|
|
94
|
+
nibble = value
|
|
95
|
+
} else {
|
|
96
|
+
res[size++] = (nibble << 4) | value
|
|
97
|
+
nibble = -1
|
|
98
|
+
}
|
|
62
99
|
}
|
|
100
|
+
if (nibble !== -1) {
|
|
101
|
+
res[size++] = nibble
|
|
102
|
+
}
|
|
103
|
+
if (size !== res.length) res.length = size
|
|
63
104
|
return res
|
|
64
105
|
}
|
|
65
106
|
|
|
@@ -377,11 +418,13 @@ export const fromBase58Check = (
|
|
|
377
418
|
return { prefix, data }
|
|
378
419
|
}
|
|
379
420
|
|
|
421
|
+
type WriterChunk = readonly number[] | Uint8Array
|
|
422
|
+
|
|
380
423
|
export class Writer {
|
|
381
|
-
public bufs:
|
|
424
|
+
public bufs: WriterChunk[]
|
|
382
425
|
private length: number
|
|
383
426
|
|
|
384
|
-
constructor (bufs?:
|
|
427
|
+
constructor (bufs?: WriterChunk[]) {
|
|
385
428
|
this.bufs = bufs !== undefined ? bufs : []
|
|
386
429
|
this.length = 0
|
|
387
430
|
for (const b of this.bufs) this.length += b.length
|
|
@@ -391,19 +434,36 @@ export class Writer {
|
|
|
391
434
|
return this.length
|
|
392
435
|
}
|
|
393
436
|
|
|
437
|
+
toUint8Array (): Uint8Array {
|
|
438
|
+
const out = new Uint8Array(this.length)
|
|
439
|
+
let offset = 0
|
|
440
|
+
for (const buf of this.bufs) {
|
|
441
|
+
out.set(buf, offset)
|
|
442
|
+
offset += buf.length
|
|
443
|
+
}
|
|
444
|
+
return out
|
|
445
|
+
}
|
|
446
|
+
|
|
394
447
|
toArray (): number[] {
|
|
395
448
|
const totalLength = this.length
|
|
396
449
|
const ret = new Array(totalLength)
|
|
397
450
|
let offset = 0
|
|
398
451
|
for (const buf of this.bufs) {
|
|
399
|
-
|
|
400
|
-
|
|
452
|
+
if (buf instanceof Uint8Array) {
|
|
453
|
+
for (let i = 0; i < buf.length; i++) {
|
|
454
|
+
ret[offset++] = buf[i]
|
|
455
|
+
}
|
|
456
|
+
} else {
|
|
457
|
+
const arr = buf as number[]
|
|
458
|
+
for (let i = 0; i < arr.length; i++) {
|
|
459
|
+
ret[offset++] = arr[i]
|
|
460
|
+
}
|
|
401
461
|
}
|
|
402
462
|
}
|
|
403
463
|
return ret
|
|
404
464
|
}
|
|
405
465
|
|
|
406
|
-
write (buf:
|
|
466
|
+
write (buf: WriterChunk): this {
|
|
407
467
|
this.bufs.push(buf)
|
|
408
468
|
this.length += buf.length
|
|
409
469
|
return this
|
|
@@ -414,14 +474,12 @@ export class Writer {
|
|
|
414
474
|
for (let i = 0; i < buf2.length; i++) {
|
|
415
475
|
buf2[i] = buf[buf.length - 1 - i]
|
|
416
476
|
}
|
|
417
|
-
this.
|
|
418
|
-
this.length += buf2.length
|
|
419
|
-
return this
|
|
477
|
+
return this.write(buf2)
|
|
420
478
|
}
|
|
421
479
|
|
|
422
480
|
writeUInt8 (n: number): this {
|
|
423
481
|
const buf = new Array(1)
|
|
424
|
-
buf[0] = n
|
|
482
|
+
buf[0] = n & 0xff
|
|
425
483
|
this.write(buf)
|
|
426
484
|
return this
|
|
427
485
|
}
|
|
@@ -438,9 +496,7 @@ export class Writer {
|
|
|
438
496
|
(n >> 8) & 0xff, // shift right 8 bits to get the high byte
|
|
439
497
|
n & 0xff // low byte is just the last 8 bits
|
|
440
498
|
]
|
|
441
|
-
this.
|
|
442
|
-
this.length += 2
|
|
443
|
-
return this
|
|
499
|
+
return this.write(buf)
|
|
444
500
|
}
|
|
445
501
|
|
|
446
502
|
writeInt16BE (n: number): this {
|
|
@@ -452,9 +508,7 @@ export class Writer {
|
|
|
452
508
|
n & 0xff, // low byte is just the last 8 bits
|
|
453
509
|
(n >> 8) & 0xff // shift right 8 bits to get the high byte
|
|
454
510
|
]
|
|
455
|
-
this.
|
|
456
|
-
this.length += 2
|
|
457
|
-
return this
|
|
511
|
+
return this.write(buf)
|
|
458
512
|
}
|
|
459
513
|
|
|
460
514
|
writeInt16LE (n: number): this {
|
|
@@ -468,9 +522,7 @@ export class Writer {
|
|
|
468
522
|
(n >> 8) & 0xff,
|
|
469
523
|
n & 0xff // lowest byte
|
|
470
524
|
]
|
|
471
|
-
this.
|
|
472
|
-
this.length += 4
|
|
473
|
-
return this
|
|
525
|
+
return this.write(buf)
|
|
474
526
|
}
|
|
475
527
|
|
|
476
528
|
writeInt32BE (n: number): this {
|
|
@@ -484,9 +536,7 @@ export class Writer {
|
|
|
484
536
|
(n >> 16) & 0xff,
|
|
485
537
|
(n >> 24) & 0xff // highest byte
|
|
486
538
|
]
|
|
487
|
-
this.
|
|
488
|
-
this.length += 4
|
|
489
|
-
return this
|
|
539
|
+
return this.write(buf)
|
|
490
540
|
}
|
|
491
541
|
|
|
492
542
|
writeInt32LE (n: number): this {
|