예제 #1
0
        public async Task <bool> Verify(string trHex, string pubKey, SigHash hashType = SigHash.All)
        {
            PubKey checkPubKey = new PubKey(pubKey);
            var    tr          = new Transaction(trHex);

            for (var i = 0; i < tr.Inputs.Count; i++)
            {
                var input        = tr.Inputs[i];
                var redeemScript = PayToScriptHashTemplate.Instance.ExtractScriptSigParameters(input.ScriptSig)?.RedeemScript ??
                                   PayToScriptHashTemplate.Instance.ExtractScriptSigParameters(input.WitScript)?.RedeemScript;
                if (redeemScript != null)
                {
                    if (PayToMultiSigTemplate.Instance.CheckScriptPubKey(redeemScript))
                    {
                        var pubkeys = PayToMultiSigTemplate.Instance.ExtractScriptPubKeyParameters(redeemScript).PubKeys;
                        for (int j = 0; j < pubkeys.Length; j++)
                        {
                            if (pubkeys[j] == checkPubKey)
                            {
                                var scriptParams = PayToScriptHashTemplate.Instance.ExtractScriptSigParameters(input.ScriptSig);
                                var hash         = Script.SignatureHash(scriptParams.RedeemScript, tr, i, hashType);
                                if (!checkPubKey.Verify(hash, scriptParams.Pushes[j + 1]))
                                {
                                    return(false);
                                }
                            }
                        }
                        continue;
                    }
                }

                var prevTransaction = await _bitcoinTransactionService.GetTransaction(input.PrevOut.Hash.ToString());

                var output = prevTransaction.Outputs[input.PrevOut.N];

                if (PayToPubkeyHashTemplate.Instance.CheckScriptPubKey(output.ScriptPubKey))
                {
                    if (output.ScriptPubKey.GetDestinationAddress(_rpcParams.Network) ==
                        checkPubKey.GetAddress(_rpcParams.Network))
                    {
                        var hash = Script.SignatureHash(output.ScriptPubKey, tr, i, hashType);
                        var sign = PayToPubkeyHashTemplate.Instance.ExtractScriptSigParameters(input.ScriptSig)?.TransactionSignature?.Signature;
                        if (sign == null)
                        {
                            return(false);
                        }
                        if (!checkPubKey.Verify(hash, sign))
                        {
                            return(false);
                        }
                    }
                }
            }
            return(true);
        }
        public async Task Cashout()
        {
            var currentMultiCashout = await _multiCashoutRepository.GetCurrentMultiCashout();

            if (currentMultiCashout != null)
            {
                Transaction tx = null;
                try
                {
                    tx = await _bitcoinTransactionService.GetTransaction(currentMultiCashout.TransactionHash);
                }
                catch
                {
                }
                if (tx != null)
                {
                    await _multiCashoutRepository.CompleteMultiCashout(currentMultiCashout.MultipleCashoutId);
                }
                else
                {
                    await RetryBroadcast(currentMultiCashout);
                }
            }

            var cashouts = (await _cashoutRequestRepository.GetOpenRequests()).OrderBy(o => o.Date).ToList();

            if (!cashouts.Any())
            {
                return;
            }
            var maxCount = await _settingsRepository.Get(Constants.MaxCountAggregatedCashouts, MaxCountAggregatedCashoutsDefault);

            var cashoutDelay = TimeSpan.FromSeconds(await _settingsRepository.Get(Constants.MaxCashoutDelaySeconds, MaxCashoutDelaySecondsDefault));

            cashouts = cashouts.Take(maxCount).ToList();

            if (cashouts.Count < maxCount && DateTime.UtcNow - cashouts.First().Date < cashoutDelay)
            {
                return;
            }

            var multiCashoutId = Guid.NewGuid();
            CreateMultiCashoutTransactionResult createTxData = null;
            string signedHex;

            try
            {
                createTxData = await _lykkeTransactionBuilderService.GetMultipleCashoutTransaction(cashouts.ToList(), multiCashoutId);

                signedHex = await _signatureApi.SignTransaction(createTxData.Transaction.ToHex());
            }
            catch (Exception)
            {
                if (createTxData != null)
                {
                    await _spentOutputService.RemoveSpentOutputs(createTxData.Transaction);
                }
                throw;
            }

            var signedTx = new Transaction(signedHex);

            var txHash = signedTx.GetHash().ToString();

            await _cashoutRequestRepository.SetMultiCashoutId(createTxData.UsedRequests.Select(o => o.CashoutRequestId), multiCashoutId);

            await _multiCashoutRepository.CreateMultiCashout(multiCashoutId, signedHex, txHash);

            await _bitcoinBroadcastService.BroadcastTransaction(multiCashoutId, createTxData.UsedRequests.Select(o => o.CashoutRequestId).ToList(),
                                                                signedTx);

            await _multiCashoutRepository.CompleteMultiCashout(multiCashoutId);

            SendCompleteCashoutEvents(createTxData.UsedRequests, txHash);
        }
예제 #3
0
        public async Task <IActionResult> AddCommitmentPunishmentPairOldDesign([FromQuery] string commitment,
                                                                               [FromQuery] string punishment)
        {
            if (string.IsNullOrEmpty(commitment) || string.IsNullOrEmpty(punishment))
            {
                return(BadRequest("Passed parameters should not be null or empty"));
            }
            else
            {
                Transaction cTx = new Transaction(commitment);
                Transaction pTx = new Transaction(punishment);

                try
                {
                    using (OffchainMonitorContext context = new OffchainMonitorContext())
                    {
                        var newlyAddedCommitment = new CommitmentEntity
                        {
                            Commitment = commitment,
                            Punishment = punishment
                        };

                        bool found    = false;
                        var  multisig = await settingsRepository.Get <string>("multisig");

                        var netwok = await Helper.GetNetwork(settingsRepository);

                        for (int i = 0; i < cTx.Inputs.Count; i++)
                        {
                            var prevHash = cTx.Inputs[i].PrevOut.Hash.ToString();
                            var prevTx   = await bitcoinTransactionService.GetTransaction(prevHash);

                            var prevOut = cTx.Inputs[i].PrevOut;
                            if (prevTx.Outputs[prevOut.N].ScriptPubKey.GetDestinationAddress(netwok).ToString()
                                == multisig)
                            {
                                found = true;

                                var existingMultisigOutput = (from o in context.MultisigOutputs
                                                              where o.TransactionId == prevOut.Hash.ToString() && o.OutputNumber == prevOut.N
                                                              select o).FirstOrDefault();
                                if (existingMultisigOutput == null)
                                {
                                    var newMultisigOutput = new MultisigOutputEntity();
                                    newMultisigOutput.TransactionId = prevOut.Hash.ToString();
                                    newMultisigOutput.OutputNumber  = (int)prevOut.N;
                                    newMultisigOutput.LastSeen      = DateTime.UtcNow;
                                    await context.MultisigOutputs.AddAsync(newMultisigOutput);

                                    existingMultisigOutput = newMultisigOutput;
                                }

                                existingMultisigOutput.LastSeen = DateTime.UtcNow;
                                existingMultisigOutput.Commitments.Add(newlyAddedCommitment);

                                newlyAddedCommitment.CommitmentOutput = existingMultisigOutput;
                                await context.Commitments.AddAsync(newlyAddedCommitment);
                            }
                        }

                        if (!found)
                        {
                            return(BadRequest(string.Format("The provide transaction does not pay to multisig:{0}", multisig)));
                        }

                        await context.SaveChangesAsync();
                    }
                    return(Ok());
                }
                catch (Exception exp)
                {
                    throw exp;
                }
            }
        }