string RefreseHash(string hash) { var array = HelperTools.HexStringToByteArray(hash); Array.Reverse(array); return(HelperTools.ByteToHexString(array)); }
public async Task <PrevTxOutput> GetPrevOutAsync(byte[] prevOutTxId, long prevOutN) { PrevTxOutput foundPrevOut; lock (prevTxOutputCache) { prevTxOutputCache.Cache.TryGetValue($"{HelperTools.ByteToHexString(prevOutTxId)}_{prevOutN}", out foundPrevOut); } if (foundPrevOut == null) { using var connection = GetDbConnection(); string cmdText = @" SELECT tx.txInternalId, tx.txExternalId, txinput.n FROM tx INNER JOIN txinput ON txinput.txInternalId = tx.txInternalId WHERE tx.txExternalId = @prevOutTxId AND txinput.n = @prevOutN; "; foundPrevOut = await connection.QueryFirstOrDefaultAsync <PrevTxOutput>(cmdText, new { prevOutTxId, prevOutN }); if (foundPrevOut != null) { CachePrevOut(foundPrevOut); } } else { logger.LogInformation($"GetPrevOutAsync: prevOut was found in prevTxOutputCache, key={HelperTools.ByteToHexString(prevOutTxId)}_{prevOutN}."); } return(foundPrevOut); }
private void CachePrevOut(PrevTxOutput prevTxOutput) { var cacheEntryOptions = new MemoryCacheEntryOptions() .SetSize(1) .SetSlidingExpiration(TimeSpan.FromMinutes(30)); prevTxOutputCache.Cache.Set <PrevTxOutput>($"{HelperTools.ByteToHexString(prevTxOutput.TxExternalId)}_{prevTxOutput.N}", prevTxOutput, cacheEntryOptions); }
public async Task <string> SendRawTransactionAsync(byte[] transaction, bool allowhighfees, bool dontCheckFees, CancellationToken?token) { var rpcResponse = await MakeRequestAsync <string>(token, new RpcRequest(1, "sendrawtransaction", HelperTools.ByteToHexString(transaction), allowhighfees, dontCheckFees )); return(rpcResponse.Result); }
public async Task SubmitTransaction() { var(txHex, txId) = CreateNewTransaction(); var payload = await SubmitTransactionAsync(txHex); Assert.AreEqual(payload.ReturnResult, "success"); // Try to fetch tx from the node var txFromNode = await rpcClient0.GetRawTransactionAsBytesAsync(txId); Assert.AreEqual(txHex, HelperTools.ByteToHexString(txFromNode)); }
public static CallbackNotificationViewModelBase CreateFromNotificationData(IClock clock, NotificationData notificationData) { var txId = new uint256(notificationData.TxExternalId).ToString(); var blockHash = (notificationData.BlockHash == null || notificationData.BlockHash.Length == 0) ? "" : new uint256(notificationData.BlockHash).ToString(); CallbackNotificationViewModelBase callbackModel; switch (notificationData.NotificationType) { case Domain.CallbackReason.DoubleSpend: case Domain.CallbackReason.DoubleSpendAttempt: callbackModel = new CallbackNotificationDoubleSpendViewModel { CallbackPayload = new DsNotificationPayloadCallbackViewModel { DoubleSpendTxId = new uint256(notificationData.DoubleSpendTxId).ToString(), Payload = HelperTools.ByteToHexString(notificationData.Payload) } }; break; case Domain.CallbackReason.MerkleProof: if (notificationData.MerkleFormat == MerkleFormat.TSC) { callbackModel = new CallbackNotificationMerkeProof2ViewModel { CallbackPayload = notificationData.MerkleProof2 }; } else { callbackModel = new CallbackNotificationMerkeProofViewModel { CallbackPayload = notificationData.MerkleProof }; } break; default: throw new BadRequestException("Unknown notification type."); } callbackModel.APIVersion = Const.MERCHANT_API_VERSION; callbackModel.BlockHash = blockHash; callbackModel.BlockHeight = notificationData.BlockHeight; callbackModel.CallbackReason = notificationData.NotificationType; callbackModel.CallbackTxId = txId; callbackModel.Timestamp = clock.UtcNow(); return(callbackModel); }
public async Task SubmitTransactionValid() { var(txHex, tx, prevOuts) = await CreateNewConsolidationTx(); Assert.IsTrue(Mapi.IsConsolidationTxn(tx, consolidationParameters, prevOuts)); var payload = await SubmitTransaction(txHex); Assert.AreEqual("success", payload.ReturnResult); // Try to fetch tx from the node var txFromNode = await rpcClient0.GetRawTransactionAsBytesAsync(tx.GetHash().ToString()); Assert.AreEqual(txHex, HelperTools.ByteToHexString(txFromNode)); }
public async Task SubmitTransactionAndWaitForProof2() { var(txHex, txId) = CreateNewTransaction(); var payload = await SubmitTransactionAsync(txHex, merkleProof : true, merkleFormat : MerkleFormat.TSC); Assert.AreEqual(payload.ReturnResult, "success"); // Try to fetch tx from the node var txFromNode = await rpcClient0.GetRawTransactionAsBytesAsync(txId); Assert.AreEqual(txHex, HelperTools.ByteToHexString(txFromNode)); Assert.AreEqual(0, Callback.Calls.Length); var notificationEventSubscription = EventBus.Subscribe <NewNotificationEvent>(); // This is not absolutely necessary, since we ar waiting for NotificationEvent too, but it helps // with troubleshooting: var generatedBlock = await GenerateBlockAndWaitForItTobeInsertedInDBAsync(); loggerTest.LogInformation($"Generated block {generatedBlock} should contain our transaction"); await WaitForEventBusEventAsync(notificationEventSubscription, $"Waiting for merkle notification event for tx {txId}", (evt) => evt.NotificationType == CallbackReason.MerkleProof && new uint256(evt.TransactionId) == new uint256(txId) ); WaitUntilEventBusIsIdle(); // Check if callback was received Assert.AreEqual(1, Callback.Calls.Length); // Verify that it parses merkleproof2 var callback = HelperTools.JSONDeserialize <JSONEnvelopeViewModel>(Callback.Calls[0].request) .ExtractPayload <CallbackNotificationMerkeProof2ViewModel>(); Assert.AreEqual(CallbackReason.MerkleProof, callback.CallbackReason); // Validate callback var blockHeader = BlockHeader.Parse(callback.CallbackPayload.Target, Network.RegTest); Assert.AreEqual(generatedBlock, blockHeader.GetHash()); Assert.AreEqual(new uint256(txId), new uint256(callback.CallbackTxId)); Assert.AreEqual(new uint256(txId), new uint256(callback.CallbackPayload.TxOrId)); }
private Task ProcessSubscriptionAsync(ZMQSubscription subscription) { if (subscription.Socket.TryReceiveFrameString(TimeSpan.FromMilliseconds(100), out string msgTopic)) { var msg = subscription.Socket.ReceiveMultipartBytes(); logger.LogDebug($"Received message with topic {msgTopic}. Length: {msg.Count}"); switch (msgTopic) { case ZMQTopic.HashBlock: string blockHash = HelperTools.ByteToHexString(msg[0]); logger.LogInformation($"New block with hash {blockHash}."); eventBus.Publish(new NewBlockDiscoveredEvent() { CreationDate = clock.UtcNow(), BlockHash = blockHash }); break; case ZMQTopic.InvalidTx: var invalidTxMsg = JsonSerializer.Deserialize <InvalidTxMessage>(msg[0]); logger.LogInformation($"Invalid tx notification for tx {invalidTxMsg.TxId} with reason {invalidTxMsg.RejectionCode} - {invalidTxMsg.RejectionReason}."); eventBus.Publish(new InvalidTxDetectedEvent() { CreationDate = clock.UtcNow(), Message = invalidTxMsg }); break; case ZMQTopic.DiscardedFromMempool: var removedFromMempoolMsg = JsonSerializer.Deserialize <RemovedFromMempoolMessage>(msg[0]); logger.LogInformation($"Removed from mempool tx notification for tx {removedFromMempoolMsg.TxId} with reason {removedFromMempoolMsg.Reason}. ColidedWith.TxId = {removedFromMempoolMsg.CollidedWith?.TxId}"); eventBus.Publish(new RemovedFromMempoolEvent() { CreationDate = clock.UtcNow(), Message = removedFromMempoolMsg }); break; default: logger.LogInformation($"Unknown message topic {msgTopic} received. Ignoring."); logger.LogInformation($"Message: {Encoding.UTF8.GetString(msg[0])}"); break; } subscription.LastMessageAt = clock.UtcNow(); } return(Task.CompletedTask); }