@@ -3,13 +3,13 @@ var DashJoin = ('object' === typeof module && exports) || {};
3
3
'use strict' ;
4
4
5
5
let DashP2P = window . DashP2P || require ( 'dashp2p' ) ;
6
+ let DashTx = window . DashTx || require ( 'dashtx' ) ;
6
7
7
8
const DV_LITTLE_ENDIAN = true ;
8
9
9
10
const DENOM_LOWEST = 100001 ;
10
11
const PREDENOM_MIN = DENOM_LOWEST + 193 ;
11
12
const COLLATERAL = 10000 ; // DENOM_LOWEST / 10
12
- const PAYLOAD_SIZE_MAX = 4 * 1024 * 1024 ;
13
13
14
14
let STANDARD_DENOMINATIONS_MAP = {
15
15
// 0.00100001
@@ -24,11 +24,25 @@ var DashJoin = ('object' === typeof module && exports) || {};
24
24
0b00000001 : 1000010000 ,
25
25
} ;
26
26
27
+ // Note: "mask" may be a misnomer. The spec seems to be more of an ID,
28
+ // but the implementation makes it look more like a mask...
29
+ let STANDARD_DENOMINATION_MASKS = {
30
+ // 0.00100001
31
+ 100001 : 0b00010000 ,
32
+ // 0.01000010
33
+ 1000010 : 0b00001000 ,
34
+ // 0.10000100
35
+ 10000100 : 0b00000100 ,
36
+ // 1.00001000
37
+ 100001000 : 0b00000010 ,
38
+ // 10.00010000
39
+ 1000010000 : 0b00000001 ,
40
+ } ;
41
+
27
42
// https://github.com/dashpay/dash/blob/v19.x/src/coinjoin/coinjoin.h#L39
28
43
// const COINJOIN_ENTRY_MAX_SIZE = 9; // real
29
44
// const COINJOIN_ENTRY_MAX_SIZE = 2; // just for testing right now
30
45
31
- DashJoin . PAYLOAD_SIZE_MAX = PAYLOAD_SIZE_MAX ;
32
46
DashJoin . DENOM_LOWEST = DENOM_LOWEST ;
33
47
DashJoin . COLLATERAL = COLLATERAL ;
34
48
DashJoin . PREDENOM_MIN = PREDENOM_MIN ;
@@ -59,6 +73,17 @@ var DashJoin = ('object' === typeof module && exports) || {};
59
73
return 0 ;
60
74
} ;
61
75
76
+ Sizes . DSQ = 142 ;
77
+ Sizes . SENDDSQ = 1 ; // 1-byte bool
78
+ Sizes . DENOM = 4 ; // 32-bit uint
79
+ Sizes . PROTX = 32 ;
80
+ Sizes . TIME = 8 ; // 64-bit uint
81
+ Sizes . READY = 1 ; // 1-byte bool
82
+ Sizes . SIG = 97 ;
83
+
84
+ // Sizes.DSSU = 16;
85
+ // Sizes.SESSION_ID = 4;
86
+
62
87
/**
63
88
* Turns on or off DSQ messages (necessary for CoinJoin, but off by default)
64
89
* @param {Object } opts
@@ -72,43 +97,144 @@ var DashJoin = ('object' === typeof module && exports) || {};
72
97
send = true ,
73
98
} ) {
74
99
const command = 'senddsq' ;
75
- const SENDDSQ_SIZE = 1 ; // 1-byte bool
100
+ let [ bytes , payload ] = DashP2P . packers . _alloc ( message , Sizes . SENDDSQ ) ;
76
101
77
- if ( ! message ) {
78
- let dsqSize = DashP2P . sizes . HEADER_SIZE + SENDDSQ_SIZE ;
79
- message = new Uint8Array ( dsqSize ) ;
102
+ let sendByte = [ 0x01 ] ;
103
+ if ( ! send ) {
104
+ sendByte = [ 0x00 ] ;
80
105
}
106
+ payload . set ( sendByte , 0 ) ;
107
+
108
+ void DashP2P . packers . message ( { network, command, bytes } ) ;
109
+ return bytes ;
110
+ } ;
81
111
82
- let payload = message . subarray ( DashP2P . sizes . HEADER_SIZE ) ;
83
- if ( send ) {
84
- payload . set ( [ 0x01 ] , 0 ) ;
85
- } else {
86
- payload . set ( [ 0x00 ] , 0 ) ;
112
+ /**
113
+ * @param {Object } opts
114
+ * @param {NetworkName } opts.network - "mainnet", "testnet", etc
115
+ * @param {Uint8Array? } [opts.message]
116
+ * @param {Uint32 } opts.denomination
117
+ * @param {Uint8Array } opts.collateralTx
118
+ */
119
+ Packers . dsa = function ( { network, message, denomination, collateralTx } ) {
120
+ const command = 'dsa' ;
121
+ let dsaSize = Sizes . DENOM + collateralTx . length ;
122
+ let [ bytes , payload ] = DashP2P . packers . _alloc ( message , dsaSize ) ;
123
+
124
+ //@ts -ignore - numbers can be used as map keys
125
+ let denomMask = STANDARD_DENOMINATION_MASKS [ denomination ] ;
126
+ if ( ! denomMask ) {
127
+ throw new Error (
128
+ `contact your local Dash representative to vote for denominations of '${ denomination } '` ,
129
+ ) ;
87
130
}
88
131
89
- void DashP2P . packers . message ( { network, command, bytes : message } ) ;
90
- return message ;
91
- // return { message, payload };
132
+ let dv = new DataView ( payload . buffer ) ;
133
+ let offset = 0 ;
134
+
135
+ dv . setUint32 ( offset , denomMask , DV_LITTLE_ENDIAN ) ;
136
+ offset += Sizes . DENOM ;
137
+
138
+ payload . set ( collateralTx , offset ) ;
139
+
140
+ void DashP2P . packers . message ( { network, command, bytes } ) ;
141
+ return bytes ;
92
142
} ;
93
143
94
- Sizes . DSQ_SIZE = 142 ;
95
- // DSQ stuff??
96
- Sizes . DENOM = 4 ;
97
- Sizes . PROTX = 32 ;
98
- Sizes . TIME = 8 ;
99
- Sizes . READY = 1 ;
100
- Sizes . SIG = 97 ;
101
- //
144
+ /**
145
+ * @param {Object } opts
146
+ * @param {NetworkName } opts.network - "mainnet", "testnet", etc
147
+ * @param {Uint8Array? } [opts.message]
148
+ * @param {Array<import('dashtx').TxInput> } opts.inputs
149
+ * @param {Array<import('dashtx').TxOutput> } opts.outputs
150
+ * @param {Uint8Array } opts.collateralTx
151
+ */
152
+ Packers . dsi = function ( { network, message, inputs, collateralTx, outputs } ) {
153
+ const command = 'dsi' ;
154
+
155
+ let neutered = [ ] ;
156
+ for ( let input of inputs ) {
157
+ let _input = {
158
+ txId : input . txId || input . txid ,
159
+ txid : input . txid || input . txId ,
160
+ outputIndex : input . outputIndex ,
161
+ } ;
162
+ neutered . push ( _input ) ;
163
+ }
164
+
165
+ let inputsHex = DashTx . serializeInputs ( inputs ) ;
166
+ let inputHex = inputsHex . join ( '' ) ;
167
+ let outputsHex = DashTx . serializeOutputs ( outputs ) ;
168
+ let outputHex = outputsHex . join ( '' ) ;
169
+
170
+ let dsiSize = collateralTx . length ;
171
+ dsiSize += inputHex . length / 2 ;
172
+ dsiSize += outputHex . length / 2 ;
173
+
174
+ let [ bytes , payload ] = DashP2P . packers . _alloc ( message , dsiSize ) ;
102
175
103
- // Sizes.DSSU_SIZE = 16;
104
- // Sizes.SESSION_ID_SIZE = 4;
176
+ let offset = 0 ;
177
+ {
178
+ let j = 0 ;
179
+ for ( let i = 0 ; i < inputHex . length ; i += 2 ) {
180
+ let end = i + 2 ;
181
+ let hex = inputHex . slice ( i , end ) ;
182
+ payload [ j ] = parseInt ( hex , 16 ) ;
183
+ j += 1 ;
184
+ }
185
+ offset += inputHex . length / 2 ;
186
+ }
187
+
188
+ payload . set ( collateralTx , offset ) ;
189
+ offset += collateralTx . length ;
190
+
191
+ {
192
+ let outputsPayload = payload . subarray ( offset ) ;
193
+ let j = 0 ;
194
+ for ( let i = 0 ; i < outputHex . length ; i += 2 ) {
195
+ let end = i + 2 ;
196
+ let hex = outputHex . slice ( i , end ) ;
197
+ outputsPayload [ j ] = parseInt ( hex , 16 ) ;
198
+ j += 1 ;
199
+ }
200
+ offset += outputHex . length / 2 ;
201
+ }
202
+
203
+ void DashP2P . packers . message ( { network, command, bytes } ) ;
204
+ return bytes ;
205
+ } ;
206
+
207
+ /**
208
+ * @param {Object } opts
209
+ * @param {Uint8Array? } [opts.message]
210
+ * @param {NetworkName } opts.network - "mainnet", "testnet", etc
211
+ * @param {Array<import('dashtx').CoreUtxo> } [opts.inputs]
212
+ */
213
+ Packers . dss = function ( { network, message, inputs } ) {
214
+ const command = 'dss' ;
215
+
216
+ if ( ! inputs ?. length ) {
217
+ // TODO make better
218
+ throw new Error ( 'you must provide some inputs' ) ;
219
+ }
220
+
221
+ let txInputsHex = DashTx . serializeInputs ( inputs ) ;
222
+ let txInputHex = txInputsHex . join ( '' ) ;
223
+
224
+ let dssSize = txInputHex . length / 2 ;
225
+ let [ bytes , payload ] = DashP2P . packers . _alloc ( message , dssSize ) ;
226
+ void DashP2P . utils . hexToPayload ( txInputHex , payload ) ;
227
+
228
+ void DashP2P . packers . message ( { network, command, bytes } ) ;
229
+ return bytes ;
230
+ } ;
105
231
106
232
/**
107
233
* @param {Uint8Array } bytes
108
234
*/
109
235
Parsers . dsq = function ( bytes ) {
110
- if ( bytes . length !== Sizes . DSQ_SIZE ) {
111
- let msg = `developer error: 'dsq' must be ${ Sizes . DSQ_SIZE } bytes, but received ${ bytes . length } ` ;
236
+ if ( bytes . length !== Sizes . DSQ ) {
237
+ let msg = `developer error: 'dsq' must be ${ Sizes . DSQ } bytes, but received ${ bytes . length } ` ;
112
238
throw new Error ( msg ) ;
113
239
}
114
240
let dv = new DataView ( bytes . buffer ) ;
@@ -160,40 +286,8 @@ var DashJoin = ('object' === typeof module && exports) || {};
160
286
return dsqMessage ;
161
287
} ;
162
288
163
- Utils . hexToBytes = function ( hex ) {
164
- let bufLen = hex . length / 2 ;
165
- let u8 = new Uint8Array ( bufLen ) ;
166
-
167
- let i = 0 ;
168
- let index = 0 ;
169
- let lastIndex = hex . length - 2 ;
170
- for ( ; ; ) {
171
- if ( i > lastIndex ) {
172
- break ;
173
- }
174
-
175
- let h = hex . slice ( i , i + 2 ) ;
176
- let b = parseInt ( h , 16 ) ;
177
- u8 [ index ] = b ;
178
-
179
- i += 2 ;
180
- index += 1 ;
181
- }
182
-
183
- return u8 ;
184
- } ;
185
-
186
- Utils . bytesToHex = function ( u8 ) {
187
- /** @type {Array<String> } */
188
- let hex = [ ] ;
189
-
190
- u8 . forEach ( function ( b ) {
191
- let h = b . toString ( 16 ) . padStart ( 2 , '0' ) ;
192
- hex . push ( h ) ;
193
- } ) ;
194
-
195
- return hex . join ( '' ) ;
196
- } ;
289
+ // Utils.hexToBytes = DashTx.utils.hexToBytes;
290
+ // Utils.bytesToHex = DashTx.utils.bytesToHex;
197
291
198
292
Utils . _evonodeMapToList = function ( evonodesMap ) {
199
293
console . log ( '[debug] get evonode list...' ) ;
0 commit comments