Merge pull request #1439 from Kukks/monero-fix

monero fixes
This commit is contained in:
Nicolas Dorier 2020-04-08 21:11:27 +09:00 committed by GitHub
commit 9a54445785
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 48 additions and 52 deletions

View file

@ -14,7 +14,6 @@ namespace BTCPayServer.Services.Altcoins.Monero.RPC.Models
[JsonProperty("amount")] public long Amount { get; set; }
[JsonProperty("confirmations")] public long Confirmations { get; set; }
[JsonProperty("double_spend_seen")] public bool DoubleSpendSeen { get; set; }
[JsonProperty("fee")] public long Fee { get; set; }
[JsonProperty("height")] public long Height { get; set; }
[JsonProperty("note")] public string Note { get; set; }
[JsonProperty("payment_id")] public string PaymentId { get; set; }

View file

@ -18,7 +18,6 @@ namespace BTCPayServer.Services.Altcoins.Monero.RPC.Models
[JsonProperty("amount")] public long Amount { get; set; }
[JsonProperty("confirmations")] public long Confirmations { get; set; }
[JsonProperty("double_spend_seen")] public bool DoubleSpendSeen { get; set; }
[JsonProperty("fee")] public long Fee { get; set; }
[JsonProperty("height")] public long Height { get; set; }
[JsonProperty("note")] public string Note { get; set; }
[JsonProperty("payment_id")] public string PaymentId { get; set; }

View file

@ -3,26 +3,26 @@ version: "3"
services:
monerod:
image: kukks/docker-monero:test
image: btcpayserver/monero:0.15.0.1-amd64
restart: unless-stopped
container_name: xmr_monerod
entrypoint: monerod --fixed-difficulty 100 --rpc-bind-ip=0.0.0.0 --confirm-external-bind --rpc-bind-port=18081 --non-interactive --block-notify="/scripts/notifier.sh https://127.0.0.1:14142/monerolikedaemoncallback/block?cryptoCode=xmr&hash=%s" --testnet --no-igd --hide-my-port --no-sync --offline
entrypoint: sleep 999999
# entrypoint: monerod --fixed-difficulty 200 --rpc-bind-ip=0.0.0.0 --confirm-external-bind --rpc-bind-port=18081 --block-notify="/bin/sh ./scripts/notifier.sh -k -X GET https://host.docker.internal:14142/monerolikedaemoncallback/block?cryptoCode=xmr&hash=%s" --testnet --no-igd --hide-my-port --offline
volumes:
- "monero_data:/home/monero/.bitmonero"
ports:
- "18081:18081"
monero_wallet:
image: kukks/docker-monero:test
image: btcpayserver/monero:0.15.0.1-amd64
restart: unless-stopped
container_name: xmr_wallet_rpc
entrypoint: monero-wallet-rpc --testnet --rpc-bind-ip=0.0.0.0 --disable-rpc-login --confirm-external-bind --rpc-bind-port=18082 --non-interactive --trusted-daemon --daemon-address=127.0.0.1:18081 --wallet-file=/wallet/wallet.keys --tx-notify="/scripts/notifier.sh https://127.0.0.1:14142/monerolikedaemoncallback/tx?cryptoCode=xmr&hash=%s"
entrypoint: monero-wallet-rpc --testnet --rpc-bind-ip=0.0.0.0 --disable-rpc-login --confirm-external-bind --rpc-bind-port=18082 --non-interactive --trusted-daemon --daemon-address=monerod:18081 --wallet-file=/wallet/wallet.keys --password-file=/wallet/password --tx-notify="/bin/sh ./scripts/notifier.sh -k -X GET https://host.docker.internal:14142/monerolikedaemoncallback/tx?cryptoCode=xmr&hash=%s"
ports:
- "18082:18082"
volumes:
- "monero_wallet:/wallet"
- "./monero_wallet:/wallet"
depends_on:
- monerod
volumes:
monero_data:
monero_wallet:

View file

@ -4,7 +4,6 @@ using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using BTCPayServer.Data;
using BTCPayServer.Events;
using BTCPayServer.Services.Altcoins.Monero.Configuration;
using BTCPayServer.Services.Altcoins.Monero.Payments;
@ -28,8 +27,7 @@ namespace BTCPayServer.Services.Altcoins.Monero.Services
private readonly BTCPayNetworkProvider _networkProvider;
private readonly ILogger<MoneroListener> _logger;
private CompositeDisposable leases = new CompositeDisposable();
private Queue<Func<CancellationToken, Task>> taskQueue = new Queue<Func<CancellationToken, Task>>();
private CancellationTokenSource _Cts;
public MoneroListener(InvoiceRepository invoiceRepository,
@ -68,10 +66,34 @@ namespace BTCPayServer.Services.Altcoins.Monero.Services
_logger.LogInformation($"{e.CryptoCode} just became unavailable");
}
}));
_ = WorkThroughQueue(_Cts.Token);
return Task.CompletedTask;
}
private async Task WorkThroughQueue(CancellationToken token)
{
while (!token.IsCancellationRequested)
{
if (taskQueue.TryDequeue(out var t))
{
try
{
await t.Invoke(token);
}
catch (Exception e)
{
_logger.LogError($"error with queue item",e);
}
}
else
{
await Task.Delay(TimeSpan.FromSeconds(1), token);
}
}
}
private void OnMoneroEvent(MoneroEvent obj)
{
if (!_moneroRpcProvider.IsAvailable(obj.CryptoCode))
@ -81,12 +103,12 @@ namespace BTCPayServer.Services.Altcoins.Monero.Services
if (!string.IsNullOrEmpty(obj.BlockHash))
{
OnNewBlock(obj.CryptoCode);
taskQueue.Enqueue(token => OnNewBlock(obj.CryptoCode));
}
if (!string.IsNullOrEmpty(obj.TransactionHash))
{
_ = OnTransactionUpdated(obj.CryptoCode, obj.TransactionHash);
taskQueue.Enqueue(token => OnTransactionUpdated(obj.CryptoCode, obj.TransactionHash));
}
}
@ -209,7 +231,7 @@ namespace BTCPayServer.Services.Altcoins.Monero.Services
}
return HandlePaymnetData(cryptoCode, transfer.Address, transfer.Amount, transfer.SubaddrIndex.Major,
return HandlePaymentData(cryptoCode, transfer.Address, transfer.Amount, transfer.SubaddrIndex.Major,
transfer.SubaddrIndex.Minor, transfer.Txid, transfer.Confirmations, transfer.Height, invoice,
updatedPaymentEntities);
}));
@ -235,9 +257,9 @@ namespace BTCPayServer.Services.Altcoins.Monero.Services
return Task.CompletedTask;
}
private void OnNewBlock(string cryptoCode)
private async Task OnNewBlock(string cryptoCode)
{
_ = UpdateAnyPendingMoneroLikePayment(cryptoCode);
await UpdateAnyPendingMoneroLikePayment(cryptoCode);
_eventAggregator.Publish(new NewBlockEvent() {CryptoCode = cryptoCode});
}
@ -250,8 +272,7 @@ namespace BTCPayServer.Services.Altcoins.Monero.Services
new GetTransferByTransactionIdRequest() {TransactionId = transactionHash});
var paymentsToUpdate = new BlockingCollection<(PaymentEntity Payment, InvoiceEntity invoice)>();
//group all destinations of the tx together and loop through the sets
foreach (var destination in transfer.Transfers.GroupBy(destination => destination.Address))
{
@ -265,7 +286,7 @@ namespace BTCPayServer.Services.Altcoins.Monero.Services
var index = destination.First().SubaddrIndex;
await HandlePaymnetData(cryptoCode,
await HandlePaymentData(cryptoCode,
destination.Key,
destination.Sum(destination1 => destination1.Amount),
index.Major,
@ -289,7 +310,7 @@ namespace BTCPayServer.Services.Altcoins.Monero.Services
}
}
private async Task HandlePaymnetData(string cryptoCode, string address, long totalAmount, long subaccountIndex,
private async Task HandlePaymentData(string cryptoCode, string address, long totalAmount, long subaccountIndex,
long subaddressIndex,
string txId, long confirmations, long blockHeight, InvoiceEntity invoice,
BlockingCollection<(PaymentEntity Payment, InvoiceEntity invoice)> paymentsToUpdate)
@ -331,26 +352,18 @@ namespace BTCPayServer.Services.Altcoins.Monero.Services
private async Task UpdateAnyPendingMoneroLikePayment(string cryptoCode)
{
var invoiceIds =
await GetPendingInvoicesWithPaymentMethodOption(new PaymentMethodId(cryptoCode,
MoneroPaymentType.Instance));
var invoiceIds =await _invoiceRepository.GetPendingInvoices();
if (!invoiceIds.Any())
{
return;
}
var invoices = await _invoiceRepository.GetInvoices(new InvoiceQuery() {InvoiceId = invoiceIds});
invoices = invoices.Where(entity => entity.GetPaymentMethod(new PaymentMethodId(cryptoCode, MoneroPaymentType.Instance)) != null).ToArray();
_logger.LogInformation($"Updating pending payments for {cryptoCode} in {string.Join(',', invoiceIds)}");
await UpdatePaymentStates(cryptoCode, invoices);
}
private async Task<string[]> GetPendingInvoicesWithPaymentMethodOption(PaymentMethodId paymentMethodId)
{
return await _invoiceRepository.GetPendingInvoices(pendingInvoice =>
pendingInvoice.Where(data => data.InvoiceData.AddressInvoices.Any(invoiceData =>
invoiceData.GetpaymentMethodId() != null && invoiceData.GetpaymentMethodId() == paymentMethodId)));
}
private IEnumerable<PaymentEntity> GetAllMoneroLikePayments(InvoiceEntity invoice, string cryptoCode)
{
return invoice.GetPayments()

View file

@ -14,6 +14,7 @@ namespace BTCPayServer.Services.Altcoins.Monero.Services
{
private readonly MoneroLikeConfiguration _moneroLikeConfiguration;
private readonly EventAggregator _eventAggregator;
private readonly BTCPayServerEnvironment _btcPayServerEnvironment;
public ImmutableDictionary<string, JsonRpcClient> DaemonRpcClients;
public ImmutableDictionary<string, JsonRpcClient> WalletRpcClients;
@ -22,10 +23,11 @@ namespace BTCPayServer.Services.Altcoins.Monero.Services
public ConcurrentDictionary<string, MoneroLikeSummary> Summaries => _summaries;
public MoneroRPCProvider(MoneroLikeConfiguration moneroLikeConfiguration, EventAggregator eventAggregator, IHttpClientFactory httpClientFactory)
public MoneroRPCProvider(MoneroLikeConfiguration moneroLikeConfiguration, EventAggregator eventAggregator, IHttpClientFactory httpClientFactory, BTCPayServerEnvironment btcPayServerEnvironment)
{
_moneroLikeConfiguration = moneroLikeConfiguration;
_eventAggregator = eventAggregator;
_btcPayServerEnvironment = btcPayServerEnvironment;
DaemonRpcClients =
_moneroLikeConfiguration.MoneroLikeConfigurationItems.ToImmutableDictionary(pair => pair.Key,
pair => new JsonRpcClient(pair.Value.DaemonRpcUri, "", "", httpClientFactory.CreateClient()));
@ -61,8 +63,7 @@ namespace BTCPayServer.Services.Altcoins.Monero.Services
await daemonRpcClient.SendCommandAsync<JsonRpcClient.NoRequestModel, SyncInfoResponse>("sync_info",
JsonRpcClient.NoRequestModel.Instance);
summary.TargetHeight = daemonResult.TargetHeight ?? daemonResult.Height;
summary.Synced = !daemonResult.TargetHeight.HasValue ||
(daemonResult.Height >= daemonResult.TargetHeight && daemonResult.TargetHeight > 0);
summary.Synced = daemonResult.Height >= summary.TargetHeight && (summary.TargetHeight > 0 || _btcPayServerEnvironment.IsDevelopping);
summary.CurrentHeight = daemonResult.Height;
summary.UpdatedAt = DateTime.Now;
summary.DaemonAvailable = true;

View file

@ -1,27 +1,16 @@
using DBriize;
using Microsoft.Extensions.Logging;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using NBitpayClient;
using Newtonsoft.Json;
using System.Linq;
using NBitcoin;
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Query;
using Microsoft.EntityFrameworkCore.Infrastructure.Internal;
using BTCPayServer.Models;
using System.Threading.Tasks;
using BTCPayServer.Data;
using System.Globalization;
using BTCPayServer.Models.InvoicingModels;
using BTCPayServer.Logging;
using BTCPayServer.Payments;
using System.Data.Common;
using NBitcoin.Altcoins;
using NBitcoin.Altcoins.Elements;
using Newtonsoft.Json.Linq;
using Encoders = NBitcoin.DataEncoders.Encoders;
@ -99,16 +88,11 @@ retry:
}
}
public async Task<string[]> GetPendingInvoices(Func<IQueryable<PendingInvoiceData>, IQueryable<PendingInvoiceData>> filter = null )
public async Task<string[]> GetPendingInvoices()
{
using (var ctx = _ContextFactory.CreateContext())
{
var queryable = ctx.PendingInvoices.AsQueryable();
if (filter != null)
{
queryable = filter.Invoke(queryable);
}
return await queryable.Select(p => p.Id).ToArrayAsync();
return await ctx.PendingInvoices.AsQueryable().Select(data => data.Id).ToArrayAsync();
}
}