40
40
* @prop {Function } _debugPrint
41
41
* @prop {Function } _hash
42
42
* @prop {Function } _hashAndSignAll
43
+ * @prop {Function } _hashAndSignOne
43
44
* @prop {Function } _legacyMustSelectInputs
44
45
* @prop {Function } _legacySelectOptimalUtxos
45
46
* @prop {Function } _packInputs
66
67
/**
67
68
* @typedef tx
68
69
* @prop {TxHashAndSignAll } hashAndSignAll
70
+ * @prop {TxHashAndSignOne } hashAndSignOne
69
71
*/
70
72
71
73
/** @type {Tx } */
@@ -250,7 +252,60 @@ var DashTx = ("object" === typeof module && exports) || {};
250
252
}
251
253
void Tx . _addPrivKeyUtils ( privUtils , keys ) ;
252
254
253
- return await Tx . _hashAndSignAll ( txInfo , privUtils ) ;
255
+ let sortedInputs = txInfo . inputs . slice ( 0 ) ;
256
+ sortedInputs . sort ( Tx . sortInputs ) ;
257
+ for ( let i = 0 ; i < sortedInputs . length ; i += 1 ) {
258
+ let isSelf = sortedInputs [ i ] === txInfo . inputs [ i ] ;
259
+ if ( ! isSelf ) {
260
+ console . warn (
261
+ `txInfo.inputs are not ordered correctly, use txInfo.inputs.sort(Tx.sortInputs)\n(this will be an exception in the next version)` ,
262
+ ) ;
263
+ break ;
264
+ }
265
+ }
266
+
267
+ let sortedOutputs = txInfo . outputs . slice ( 0 ) ;
268
+ sortedOutputs . sort ( Tx . sortOutputs ) ;
269
+ for ( let i = 0 ; i < sortedOutputs . length ; i += 1 ) {
270
+ let isSelf = sortedOutputs [ i ] === txInfo . outputs [ i ] ;
271
+ if ( ! isSelf ) {
272
+ console . warn (
273
+ `txInfo.outputs are not ordered correctly, use txInfo.outputs.sort(Tx.sortOutputs)\n(this will be an exception in the next version)` ,
274
+ ) ;
275
+ break ;
276
+ }
277
+ }
278
+
279
+ /** @type {TxInfoSigned } */
280
+ let txInfoSigned = {
281
+ /** @type {Array<TxInputSigned> } */
282
+ inputs : [ ] ,
283
+ outputs : txInfo . outputs ,
284
+ version : txInfo . version || CURRENT_VERSION ,
285
+ locktime : txInfo . locktime || 0x00 ,
286
+ transaction : "" ,
287
+ } ;
288
+
289
+ return await Tx . _hashAndSignAll ( txInfoSigned , txInfo , privUtils ) ;
290
+ } ;
291
+
292
+ /** @type {TxHashAndSignAll } */
293
+ txInst . hashAndSignOne = async function ( txInfo , i ) {
294
+ let privUtils = Object . assign ( { } , keyUtils ) ;
295
+ void Tx . _addPrivKeyUtils ( keyUtils , null ) ;
296
+
297
+ /** @type {TxInfoSigned } */
298
+ let txInfoSigned = {
299
+ /** @type {Array<TxInputSigned> } */
300
+ inputs : [ ] ,
301
+ outputs : txInfo . outputs ,
302
+ version : txInfo . version || CURRENT_VERSION ,
303
+ locktime : txInfo . locktime || 0x00 ,
304
+ transaction : "" ,
305
+ } ;
306
+
307
+ let txInputSigned = await Tx . _hashAndSignOne ( privUtils , txInfo , i ) ;
308
+ txInfoSigned . inputs [ i ] = txInputSigned ;
254
309
} ;
255
310
256
311
txInst . legacy = { } ;
@@ -897,6 +952,7 @@ var DashTx = ("object" === typeof module && exports) || {};
897
952
} ;
898
953
899
954
/**
955
+ * @param {TxInfoSigned } txInfoSigned
900
956
* @param {TxInfo } txInfo
901
957
* TODO _param {Array<TxInputRaw>} txInfo.inputs - needs type narrowing check
902
958
* TODO _param {Array<TxOutput>} txInfo.outputs
@@ -905,128 +961,105 @@ var DashTx = ("object" === typeof module && exports) || {};
905
961
* @param {TxDeps } keyUtils
906
962
* @returns {Promise<TxInfoSigned> }
907
963
*/
908
- Tx . _hashAndSignAll = async function ( txInfo , keyUtils ) {
909
- let sortedInputs = txInfo . inputs . slice ( 0 ) ;
910
- sortedInputs . sort ( Tx . sortInputs ) ;
911
- for ( let i = 0 ; i < sortedInputs . length ; i += 1 ) {
912
- let isSelf = sortedInputs [ i ] === txInfo . inputs [ i ] ;
913
- if ( ! isSelf ) {
914
- console . warn (
915
- `txInfo.inputs are not ordered correctly, use txInfo.inputs.sort(Tx.sortInputs)\n(this will be an exception in the next version)` ,
916
- ) ;
917
- break ;
918
- }
964
+ Tx . _hashAndSignAll = async function ( txInfoSigned , txInfo , keyUtils ) {
965
+ for ( let i = 0 ; i < txInfo . inputs . length ; i += 1 ) {
966
+ let txInputSigned = await DashTx . _hashAndSignOne ( keyUtils , txInfo , i ) ;
967
+ txInfoSigned . inputs [ i ] = txInputSigned ;
919
968
}
920
969
921
- let sortedOutputs = txInfo . outputs . slice ( 0 ) ;
922
- sortedOutputs . sort ( Tx . sortOutputs ) ;
923
- for ( let i = 0 ; i < sortedOutputs . length ; i += 1 ) {
924
- let isSelf = sortedOutputs [ i ] === txInfo . outputs [ i ] ;
925
- if ( ! isSelf ) {
926
- console . warn (
927
- `txInfo.outputs are not ordered correctly, use txInfo.outputs.sort(Tx.sortOutputs)\n(this will be an exception in the next version)` ,
928
- ) ;
929
- break ;
930
- }
931
- }
970
+ let transaction = Tx . createSigned ( txInfoSigned ) ;
932
971
933
- /** @type { TxInfoSigned } */
934
- let txInfoSigned = {
935
- /** @type { Array<TxInputSigned> } */
936
- inputs : [ ] ,
972
+ return {
973
+ // @ts -ignore - tsc doesn't support an enum here
974
+ inputs : txInfo . inputs ,
975
+ locktime : txInfo . locktime || 0x0 ,
937
976
outputs : txInfo . outputs ,
977
+ transaction : transaction ,
938
978
version : txInfo . version || CURRENT_VERSION ,
939
- locktime : txInfo . locktime || 0x00 ,
940
- transaction : "" ,
941
979
} ;
980
+ } ;
942
981
943
- /**
944
- * @param {TxPrivateKey } privKey
945
- */
946
- function createGetPrivateKey ( privKey ) {
947
- return function ( ) {
948
- return privKey ;
949
- } ;
950
- }
951
-
952
- function throwGetPrivateKeyError ( ) {
953
- if ( false ) {
954
- return new Uint8Array ( 0 ) ;
955
- }
982
+ /**
983
+ * @param {TxPrivateKey } privKey
984
+ */
985
+ function createGetPrivateKey ( privKey ) {
986
+ return function ( ) {
987
+ return privKey ;
988
+ } ;
989
+ }
956
990
957
- const msg =
958
- "getPrivateKey() is only valid for the lifetime of transaction signing process" ;
959
- throw new Error ( msg ) ;
991
+ function throwGetPrivateKeyError ( ) {
992
+ if ( false ) {
993
+ return new Uint8Array ( 0 ) ;
960
994
}
961
995
962
- for ( let i = 0 ; i < txInfo . inputs . length ; i += 1 ) {
963
- let txInput = txInfo . inputs [ i ] ;
964
- // TODO script -> lockScript, sigScript
965
- //let lockScriptHex = txInput.script;
966
- let _sigHashType = txInput . sigHashType ?? Tx . SIGHASH_ALL ;
967
- let txHashable = Tx . createHashable ( txInfo , i ) ;
968
- let txHashBuf = await Tx . hashPartial ( txHashable , _sigHashType ) ;
969
- let privKey = await keyUtils . getPrivateKey ( txInput , i , txInfo . inputs ) ;
970
-
971
- let sigBuf = await keyUtils . sign ( privKey , txHashBuf ) ;
972
- let sigHex = "" ;
973
- if ( "string" === typeof sigBuf ) {
974
- console . warn ( `sign() should return a Uint8Array of an ASN.1 signature` ) ;
975
- sigHex = sigBuf ;
976
- } else {
977
- sigHex = Tx . utils . bytesToHex ( sigBuf ) ;
978
- }
979
-
980
- let pubKeyHex = txInput . publicKey ;
981
- if ( ! pubKeyHex ) {
982
- let getPrivateKey = createGetPrivateKey ( privKey ) ;
983
- let _txInput = Object . assign ( { } , { getPrivateKey } , txInput ) ;
984
- let pubKey = await keyUtils . getPublicKey ( _txInput , i , txInfo . inputs ) ;
985
- pubKeyHex = Tx . utils . bytesToHex ( pubKey ) ;
986
- _txInput . getPrivateKey = throwGetPrivateKeyError ;
987
- }
988
- if ( "string" !== typeof pubKeyHex ) {
989
- let warn = new Error ( "stack" ) ;
990
- console . warn (
991
- `utxo inputs should be plain JSON and use hex rather than buffers for 'publicKey'` ,
992
- warn . stack ,
993
- ) ;
994
- pubKeyHex = Tx . utils . bytesToHex ( pubKeyHex ) ;
995
- }
996
-
997
- /** @type TxInputSigned */
998
- let txInputSigned = {
999
- txId : txInput . txId || txInput . txid ,
1000
- txid : txInput . txId || txInput . txid ,
1001
- outputIndex : txInput . outputIndex ,
1002
- signature : sigHex ,
1003
- publicKey : pubKeyHex ,
1004
- sigHashType : _sigHashType ,
1005
- } ;
1006
-
1007
- // expose _actual_ values used, for debugging
1008
- let txHashHex = Tx . utils . bytesToHex ( txHashBuf ) ;
1009
- Object . assign ( {
1010
- _hash : txHashHex ,
1011
- _signature : sigHex . toString ( ) ,
1012
- _lockScript : txInfo . inputs [ i ] . script ,
1013
- _publicKey : pubKeyHex ,
1014
- _sigHashType : _sigHashType ,
1015
- } ) ;
996
+ const msg =
997
+ "getPrivateKey() is only valid for the lifetime of transaction signing process" ;
998
+ throw new Error ( msg ) ;
999
+ }
1016
1000
1017
- txInfoSigned . inputs [ i ] = txInputSigned ;
1001
+ /**
1002
+ * @param {TxInfo } txInfo
1003
+ * @param {TxDeps } keyUtils
1004
+ * @param {Number } i - which input to try to sign
1005
+ * @returns {Promise<TxInputSigned> }
1006
+ */
1007
+ Tx . _hashAndSignOne = async function ( keyUtils , txInfo , i ) {
1008
+ let txInput = txInfo . inputs [ i ] ;
1009
+ // TODO script -> lockScript, sigScript
1010
+ //let lockScriptHex = txInput.script;
1011
+ let _sigHashType = txInput . sigHashType ?? Tx . SIGHASH_ALL ;
1012
+ let txHashable = Tx . createHashable ( txInfo , i ) ;
1013
+ let txHashBuf = await Tx . hashPartial ( txHashable , _sigHashType ) ;
1014
+ let privKey = await keyUtils . getPrivateKey ( txInput , i , txInfo . inputs ) ;
1015
+
1016
+ let sigBuf = await keyUtils . sign ( privKey , txHashBuf ) ;
1017
+ let sigHex = "" ;
1018
+ if ( "string" === typeof sigBuf ) {
1019
+ console . warn ( `sign() should return a Uint8Array of an ASN.1 signature` ) ;
1020
+ sigHex = sigBuf ;
1021
+ } else {
1022
+ sigHex = Tx . utils . bytesToHex ( sigBuf ) ;
1018
1023
}
1019
1024
1020
- let transaction = Tx . createSigned ( txInfoSigned ) ;
1025
+ let pubKeyHex = txInput . publicKey ;
1026
+ if ( ! pubKeyHex ) {
1027
+ let getPrivateKey = createGetPrivateKey ( privKey ) ;
1028
+ let _txInput = Object . assign ( { } , { getPrivateKey } , txInput ) ;
1029
+ let pubKey = await keyUtils . getPublicKey ( _txInput , i , txInfo . inputs ) ;
1030
+ pubKeyHex = Tx . utils . bytesToHex ( pubKey ) ;
1031
+ _txInput . getPrivateKey = throwGetPrivateKeyError ;
1032
+ }
1033
+ if ( "string" !== typeof pubKeyHex ) {
1034
+ let warn = new Error ( "stack" ) ;
1035
+ console . warn (
1036
+ `utxo inputs should be plain JSON and use hex rather than buffers for 'publicKey'` ,
1037
+ warn . stack ,
1038
+ ) ;
1039
+ pubKeyHex = Tx . utils . bytesToHex ( pubKeyHex ) ;
1040
+ }
1021
1041
1022
- return {
1023
- //@ts -ignore - tsc doesn't support an enum here
1024
- inputs : txInfo . inputs ,
1025
- locktime : txInfo . locktime || 0x0 ,
1026
- outputs : txInfo . outputs ,
1027
- transaction : transaction ,
1028
- version : txInfo . version || CURRENT_VERSION ,
1042
+ /** @type TxInputSigned */
1043
+ let txInputSigned = {
1044
+ txId : txInput . txId || txInput . txid ,
1045
+ txid : txInput . txId || txInput . txid ,
1046
+ outputIndex : txInput . outputIndex ,
1047
+ signature : sigHex ,
1048
+ publicKey : pubKeyHex ,
1049
+ sigHashType : _sigHashType ,
1029
1050
} ;
1051
+
1052
+ // expose _actual_ values used, for debugging
1053
+ let txHashHex = Tx . utils . bytesToHex ( txHashBuf ) ;
1054
+ Object . assign ( {
1055
+ _hash : txHashHex ,
1056
+ _signature : sigHex . toString ( ) ,
1057
+ _lockScript : txInfo . inputs [ i ] . script ,
1058
+ _publicKey : pubKeyHex ,
1059
+ _sigHashType : _sigHashType ,
1060
+ } ) ;
1061
+
1062
+ return txInputSigned ;
1030
1063
} ;
1031
1064
1032
1065
Tx . createRaw = function ( opts ) {
@@ -1860,6 +1893,12 @@ if ("object" === typeof module) {
1860
1893
* @param {Array<TxPrivateKey> } [keys]
1861
1894
*/
1862
1895
1896
+ /**
1897
+ * @callback TxHashAndSignOne
1898
+ * @param {TxInfo } txInfo
1899
+ * @param {Number } i - which to sign
1900
+ */
1901
+
1863
1902
/**
1864
1903
* @callback TxHashPartial
1865
1904
* @param {String } txHex - signable tx hex (like raw tx, but with (lock)script)
0 commit comments