@@ -31,6 +31,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31
31
using MiningCore . Configuration ;
32
32
using MiningCore . DaemonInterface ;
33
33
using MiningCore . Extensions ;
34
+ using MiningCore . Native ;
34
35
using MiningCore . Notifications ;
35
36
using MiningCore . Payments ;
36
37
using MiningCore . Persistence ;
@@ -139,10 +140,15 @@ private async Task PayoutBatch(Balance[] balances)
139
140
{
140
141
Destinations = balances
141
142
. Where ( x => x . Amount > 0 )
142
- . Select ( x => new TransferDestination
143
+ . Select ( x =>
143
144
{
144
- Address = x . Address ,
145
- Amount = ( ulong ) Math . Floor ( x . Amount * MoneroConstants . SmallestUnit [ poolConfig . Coin . Type ] )
145
+ ExtractAddressAndPaymentId ( x . Address , out var address , out var paymentId ) ;
146
+
147
+ return new TransferDestination
148
+ {
149
+ Address = address ,
150
+ Amount = ( ulong ) Math . Floor ( x . Amount * MoneroConstants . SmallestUnit [ poolConfig . Coin . Type ] )
151
+ } ;
146
152
} ) . ToArray ( ) ,
147
153
148
154
GetTxKey = true
@@ -190,10 +196,15 @@ private async Task PayoutBatch(Balance[] balances)
190
196
// update request
191
197
request . Destinations = page
192
198
. Where ( x => x . Amount > 0 )
193
- . Select ( x => new TransferDestination
199
+ . Select ( x =>
194
200
{
195
- Address = x . Address ,
196
- Amount = ( ulong ) Math . Floor ( x . Amount * MoneroConstants . SmallestUnit [ poolConfig . Coin . Type ] )
201
+ ExtractAddressAndPaymentId ( x . Address , out var address , out var paymentId ) ;
202
+
203
+ return new TransferDestination
204
+ {
205
+ Address = address ,
206
+ Amount = ( ulong ) Math . Floor ( x . Amount * MoneroConstants . SmallestUnit [ poolConfig . Coin . Type ] )
207
+ } ;
197
208
} ) . ToArray ( ) ;
198
209
199
210
logger . Info ( ( ) => $ "[{ LogCategory } ] Page { i + 1 } : Paying out { FormatAmount ( page . Sum ( x => x . Amount ) ) } to { page . Length } addresses") ;
@@ -210,19 +221,33 @@ private async Task PayoutBatch(Balance[] balances)
210
221
HandleTransferResponse ( transferResponse , balances ) ;
211
222
}
212
223
213
- private async Task PayoutToPaymentId ( Balance balance )
224
+ private void ExtractAddressAndPaymentId ( string input , out string address , out string paymentId )
214
225
{
215
- // extract paymentId
216
- var address = ( string ) null ;
217
- var paymentId = ( string ) null ;
226
+ paymentId = null ;
227
+ var index = input . IndexOf ( PayoutConstants . PayoutInfoSeperator ) ;
218
228
219
- var index = balance . Address . IndexOf ( PayoutConstants . PayoutInfoSeperator ) ;
220
229
if ( index != - 1 )
221
230
{
222
- paymentId = balance . Address . Substring ( index + 1 ) ;
223
- address = balance . Address . Substring ( 0 , index ) ;
231
+ address = input . Substring ( 0 , index ) ;
232
+
233
+ if ( index + 1 < input . Length )
234
+ {
235
+ paymentId = input . Substring ( index + 1 ) ;
236
+
237
+ // ignore invalid payment ids
238
+ if ( paymentId . Length != MoneroConstants . PaymentIdHexLength )
239
+ paymentId = null ;
240
+ }
224
241
}
225
242
243
+ else
244
+ address = input ;
245
+ }
246
+
247
+ private async Task PayoutToPaymentId ( Balance balance )
248
+ {
249
+ ExtractAddressAndPaymentId ( balance . Address , out var address , out var paymentId ) ;
250
+
226
251
if ( string . IsNullOrEmpty ( paymentId ) )
227
252
throw new InvalidOperationException ( "invalid paymentid" ) ;
228
253
@@ -290,6 +315,9 @@ public async Task ConfigureAsync(ClusterConfig clusterConfig, PoolConfig poolCon
290
315
walletDaemon = new DaemonClient ( jsonSerializerSettings ) ;
291
316
walletDaemon . Configure ( walletDaemonEndpoints , MoneroConstants . DaemonRpcLocation ) ;
292
317
318
+ // detect network
319
+ await GetNetworkTypeAsync ( ) ;
320
+
293
321
// detect transfer_split support
294
322
var response = await walletDaemon . ExecuteCmdSingleAsync < TransferResponse > ( MWC . TransferSplit ) ;
295
323
walletSupportsTransferSplit = response . Error . Code != MoneroConstants . MoneroRpcMethodNotFound ;
@@ -413,9 +441,65 @@ public async Task PayoutAsync(Balance[] balances)
413
441
#endif
414
442
}
415
443
444
+ // validate addresses
445
+ balances = balances
446
+ . Where ( x =>
447
+ {
448
+ ExtractAddressAndPaymentId ( x . Address , out var address , out var paymentId ) ;
449
+
450
+ var addressPrefix = LibCryptonote . DecodeAddress ( address ) ;
451
+ var addressIntegratedPrefix = LibCryptonote . DecodeIntegratedAddress ( address ) ;
452
+
453
+ switch ( networkType )
454
+ {
455
+ case MoneroNetworkType . Main :
456
+ if ( addressPrefix != MoneroConstants . AddressPrefix [ poolConfig . Coin . Type ] &&
457
+ addressIntegratedPrefix != MoneroConstants . AddressPrefixIntegrated [ poolConfig . Coin . Type ] )
458
+ {
459
+ logger . Warn ( ( ) => $ "[{ LogCategory } ] Excluding payment to invalid address { x . Address } ") ;
460
+ return false ;
461
+ }
462
+ break ;
463
+
464
+ case MoneroNetworkType . Test :
465
+ if ( addressPrefix != MoneroConstants . AddressPrefixTestnet [ poolConfig . Coin . Type ] &&
466
+ addressIntegratedPrefix != MoneroConstants . AddressPrefixIntegratedTestnet [ poolConfig . Coin . Type ] )
467
+ {
468
+ logger . Warn ( ( ) => $ "[{ LogCategory } ] Excluding payment to invalid address { x . Address } ") ;
469
+ return false ;
470
+ }
471
+ break ;
472
+ }
473
+
474
+ return true ;
475
+ } )
476
+ . ToArray ( ) ;
477
+
416
478
// simple balances first
417
479
var simpleBalances = balances
418
- . Where ( x => ! x . Address . Contains ( PayoutConstants . PayoutInfoSeperator ) )
480
+ . Where ( x =>
481
+ {
482
+ ExtractAddressAndPaymentId ( x . Address , out var address , out var paymentId ) ;
483
+
484
+ var hasPaymentId = paymentId != null ;
485
+ var isIntegratedAddress = false ;
486
+ var addressIntegratedPrefix = LibCryptonote . DecodeIntegratedAddress ( address ) ;
487
+
488
+ switch ( networkType )
489
+ {
490
+ case MoneroNetworkType . Main :
491
+ if ( addressIntegratedPrefix == MoneroConstants . AddressPrefixIntegrated [ poolConfig . Coin . Type ] )
492
+ isIntegratedAddress = true ;
493
+ break ;
494
+
495
+ case MoneroNetworkType . Test :
496
+ if ( addressIntegratedPrefix == MoneroConstants . AddressPrefixIntegratedTestnet [ poolConfig . Coin . Type ] )
497
+ isIntegratedAddress = true ;
498
+ break ;
499
+ }
500
+
501
+ return ! hasPaymentId && ! isIntegratedAddress ;
502
+ } )
419
503
. ToArray ( ) ;
420
504
421
505
if ( simpleBalances . Length > 0 )
@@ -425,7 +509,7 @@ public async Task PayoutAsync(Balance[] balances)
425
509
var minimumPaymentToPaymentId = extraConfig ? . MinimumPaymentToPaymentId ?? poolConfig . PaymentProcessing . MinimumPayment ;
426
510
427
511
var paymentIdBalances = balances . Except ( simpleBalances )
428
- . Where ( x => x . Address . Contains ( PayoutConstants . PayoutInfoSeperator ) && x . Amount >= minimumPaymentToPaymentId )
512
+ . Where ( x => x . Amount >= minimumPaymentToPaymentId )
429
513
. ToArray ( ) ;
430
514
431
515
foreach ( var balance in paymentIdBalances )
0 commit comments