/// <summary> /// Gets the block. /// </summary> /// <param name="blockId">The block identifier.</param> /// <returns>Given a block hash (id) returns the requested block object.</returns> /// <exception cref="System.ArgumentNullException">blockId cannot be null.</exception> public async Task<Block> GetBlockAsync(uint256 blockId) { if (blockId == null) throw new ArgumentNullException("blockId"); var result = await SendRequestAsync("block", _format, blockId.ToString()).ConfigureAwait(false); ; return new Block(result); }
public Coins GetCoins(uint256 txId) { try { return Index.GetAsync<Coins>(txId.ToString()).Result; } catch(AggregateException aex) { ExceptionDispatchInfo.Capture(aex.InnerException).Throw(); return null; //Can't happen } }
public void uintTests() { var v = new uint256("00000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); var v2 = new uint256("00000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); var vless = new uint256("00000000fffffffffffffffffffffffffffffffffffffffffffffffffffffffe"); var vplus = new uint256("00000001ffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); Assert.Equal("00000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff", v.ToString()); Assert.Equal(new uint256("00000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), v); Assert.Equal(new uint256("0x00000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), v); Assert.Equal(uint256.Parse("0x00000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), v); Assert.True(v < vplus); Assert.True(v > vless); uint256 unused; Assert.True(uint256.TryParse("0x00000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff", out unused)); Assert.True(uint256.TryParse("00000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff", out unused)); Assert.True(uint256.TryParse("00000000ffffFFfFffffffffffffffffffffffffffffffffffffffffffffffff", out unused)); Assert.False(uint256.TryParse("00000000gfffffffffffffffffffffffffffffffffffffffffffffffffffffff", out unused)); Assert.False(uint256.TryParse("100000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff", out unused)); Assert.False(uint256.TryParse("1100000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff", out unused)); Assert.Throws<FormatException>(() => uint256.Parse("1100000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff")); Assert.Throws<FormatException>(() => uint256.Parse("100000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff")); uint256.Parse("00000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff"); Assert.Throws<FormatException>(() => uint256.Parse("000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff")); Assert.True(v >= v2); Assert.True(v <= v2); Assert.False(v < v2); Assert.False(v > v2); Assert.True(v.ToBytes()[0] == 0xFF); Assert.True(v.ToBytes(false)[0] == 0x00); AssertEquals(v, new uint256(v.ToBytes())); AssertEquals(v, new uint256(v.ToBytes(false), false)); Assert.Equal(0xFF, v.GetByte(0)); Assert.Equal(0x00, v.GetByte(31)); Assert.Equal(0x39, new uint256("39000001ffffffffffffffffffffffffffffffffffffffffffffffffffffffff").GetByte(31)); Assert.Throws<ArgumentOutOfRangeException>(() => v.GetByte(32)); }
public async Task GetRawTransactionAsync_TransactionCannotBeFound_ReturnsNullAsync() { var txId = new uint256(12142124); this.pooledTransaction.Setup(p => p.GetTransaction(txId)) .ReturnsAsync((Transaction)null) .Verifiable(); this.blockStore.Setup(b => b.GetTransactionById(txId)) .Returns((Transaction)null) .Verifiable(); this.controller = new NodeController(this.chainIndexer, this.chainState.Object, this.connectionManager.Object, this.dateTimeProvider.Object, this.fullNode.Object, this.LoggerFactory.Object, this.nodeSettings, this.network, this.asyncProvider.Object, this.selfEndpointTracker.Object, this.consensusManager.Object, this.blockStore.Object, this.initialBlockDownloadState.Object, this.getUnspentTransaction.Object, this.networkDifficulty.Object, this.pooledGetUnspentTransaction.Object, this.pooledTransaction.Object); string txid = txId.ToString(); bool verbose = false; var json = (JsonResult)await this.controller.GetRawTransactionAsync(txid, verbose).ConfigureAwait(false); Assert.Null(json.Value); this.pooledTransaction.Verify(); this.blockStore.Verify(); }
/// <summary> /// Get the a whole block, will fail if bitcoinq does not run with txindex=1 and one of the transaction of the block is entirely spent /// </summary> /// <param name="blockId"></param> /// <returns></returns> public Block GetBlock(uint256 blockId) { var resp = SendCommand("getblock", blockId.ToString()); var header = ParseBlockHeader(resp); Block block = new Block(header); var transactions = resp.Result["tx"] as JArray; try { foreach (var tx in transactions) { block.AddTransaction(GetRawTransaction(new uint256(tx.ToString()))); } } catch (RPCException ex) { if (ex.RPCCode == RPCErrorCode.RPC_INVALID_ADDRESS_OR_KEY) { return(null); } throw; } return(block); }
public async Task GetTxOutAsync_IncludeInMempool_UnspentTransactionFound_VOutNotFound_ReturnsModelAsync() { var txId = new uint256(1243124); Transaction transaction = this.CreateTransaction(); var unspentOutputs = new UnspentOutputs(1, transaction); this.pooledGetUnspentTransaction.Setup(s => s.GetUnspentTransactionAsync(txId)) .ReturnsAsync(unspentOutputs) .Verifiable(); string txid = txId.ToString(); uint vout = 13; bool includeMemPool = true; var json = (JsonResult)await this.controller.GetTxOutAsync(txid, vout, includeMemPool).ConfigureAwait(false); var resultModel = (GetTxOutModel)json.Value; this.pooledGetUnspentTransaction.Verify(); Assert.Equal(this.chain.Tip.HashBlock, resultModel.BestBlock); Assert.True(resultModel.Coinbase); Assert.Equal(3, resultModel.Confirmations); Assert.Null(resultModel.ScriptPubKey); Assert.Null(resultModel.Value); }
public async Task GetTaskAsync_Verbose_ChainStateTipNull_DoesNotCalulateConfirmationsAsync() { var block = this.chain.GetBlock(1); Transaction transaction = this.CreateTransaction(); uint256 txId = new uint256(12142124); this.pooledTransaction.Setup(p => p.GetTransaction(txId)) .ReturnsAsync(transaction); var blockStore = new Mock <IBlockStore>(); blockStore.Setup(b => b.GetTrxBlockIdAsync(txId)) .ReturnsAsync(block.HashBlock); this.fullNode.Setup(f => f.NodeFeature <IBlockStore>(false)) .Returns(blockStore.Object); var result = await this.controller.GetRawTransactionAsync(txId.ToString(), 1).ConfigureAwait(false); Assert.NotNull(result); var model = Assert.IsType <TransactionVerboseModel>(result); Assert.Null(model.Confirmations); }
/// <summary> /// Get the a whole block /// </summary> /// <param name="blockId"></param> /// <returns></returns> public async Task<Block> GetBlockAsync(uint256 blockId) { var resp = await SendCommandAsync("getblock", blockId.ToString(), false).ConfigureAwait(false); return new Block(Encoders.Hex.DecodeData(resp.Result.ToString())); }
private async void Round_StatusChangedAsync(object sender, CoordinatorRoundStatus status) { try { var round = sender as CoordinatorRound; Money feePerInputs = null; Money feePerOutputs = null; // If success save the coinjoin. if (status == CoordinatorRoundStatus.Succeded) { uint256[] mempoolHashes = null; try { mempoolHashes = await RpcClient.GetRawMempoolAsync().ConfigureAwait(false); } catch (Exception ex) { Logger.LogError(ex); } using (await CoinJoinsLock.LockAsync().ConfigureAwait(false)) { if (mempoolHashes is { }) { var fallOuts = UnconfirmedCoinJoins.Where(x => !mempoolHashes.Contains(x)); CoinJoins.RemoveAll(x => fallOuts.Contains(x)); UnconfirmedCoinJoins.RemoveAll(x => fallOuts.Contains(x)); } uint256 coinJoinHash = round.CoinJoin.GetHash(); CoinJoins.Add(coinJoinHash); UnconfirmedCoinJoins.Add(coinJoinHash); LastSuccessfulCoinJoinTime = DateTimeOffset.UtcNow; await File.AppendAllLinesAsync(CoinJoinsFilePath, new[] { coinJoinHash.ToString() }).ConfigureAwait(false); // When a round succeeded, adjust the denomination as to users still be able to register with the latest round's active output amount. IEnumerable <(Money value, int count)> outputs = round.CoinJoin.GetIndistinguishableOutputs(includeSingle: true); var bestOutput = outputs.OrderByDescending(x => x.count).FirstOrDefault(); if (bestOutput != default) { Money activeOutputAmount = bestOutput.value; int currentConfirmationTarget = await AdjustConfirmationTargetAsync(lockCoinJoins : false).ConfigureAwait(false); var fees = await CoordinatorRound.CalculateFeesAsync(RpcClient, currentConfirmationTarget).ConfigureAwait(false); feePerInputs = fees.feePerInputs; feePerOutputs = fees.feePerOutputs; Money newDenominationToGetInWithactiveOutputs = activeOutputAmount - (feePerInputs + (2 * feePerOutputs)); if (newDenominationToGetInWithactiveOutputs < RoundConfig.Denomination) { if (newDenominationToGetInWithactiveOutputs > Money.Coins(0.01m)) { RoundConfig.Denomination = newDenominationToGetInWithactiveOutputs; RoundConfig.ToFile(); } } } }
/// <inheritdoc /> public void ProcessTransaction(Transaction transaction, Block block = null) { uint256 transactionHash = transaction.GetHash(); this.logger.LogDebug($"watch only wallet received transaction - hash: {transactionHash}, coin: {this.coinType}"); // Check the transaction inputs to see if a watched address is affected. foreach (TxIn input in transaction.Inputs) { // See if the previous transaction is in the watch-only wallet. this.txLookup.TryGetValue(input.PrevOut.Hash, out TransactionData prevTransactionData); // If it is null, it can't be related to one of the watched addresses (or it is the very first watched transaction) if (prevTransactionData == null) { continue; } var prevTransaction = Transaction.Load(prevTransactionData.Hex, this.network); // Check if the previous transaction's outputs contain one of our addresses. foreach (TxOut prevOutput in prevTransaction.Outputs) { this.Wallet.WatchedAddresses.TryGetValue(prevOutput.ScriptPubKey.ToString(), out WatchedAddress addressInWallet); if (addressInWallet != null) { // Retrieve a transaction, if present. addressInWallet.Transactions.TryGetValue(transactionHash.ToString(), out TransactionData existingTransaction); if (existingTransaction == null) { var newTransaction = new TransactionData { Id = transactionHash, Hex = transaction.ToHex(), BlockHash = block?.GetHash() }; // Add the Merkle proof to the transaction. if (block != null) { newTransaction.MerkleProof = new MerkleBlock(block, new[] { transactionHash }).PartialMerkleTree; } addressInWallet.Transactions.TryAdd(transactionHash.ToString(), newTransaction); // Update the lookup cache with the new transaction information. // Since the WO record is new it probably isn't in the lookup cache. this.txLookup.TryAdd(newTransaction.Id, newTransaction); } else { // If there was a transaction already present in the WO wallet, // it is most likely that it has now been confirmed in a block. // Therefore, update the transaction record with the hash of the // block containing the transaction. if (existingTransaction.BlockHash == null) { existingTransaction.BlockHash = block?.GetHash(); } if (block != null && existingTransaction.MerkleProof == null) { // Add the Merkle proof now that the transaction is confirmed in a block. existingTransaction.MerkleProof = new MerkleBlock(block, new[] { transactionHash }).PartialMerkleTree; } // Update the lookup cache with the new transaction information. // Since the WO record was not new it probably is already in the lookup cache. // Therefore, unconditionally update it. this.txLookup.AddOrUpdate(existingTransaction.Id, existingTransaction, (key, oldValue) => existingTransaction); } this.SaveWatchOnlyWallet(); } } } // Check the transaction outputs for transactions we might be interested in. foreach (TxOut utxo in transaction.Outputs) { // Check if the outputs contain one of our addresses. this.Wallet.WatchedAddresses.TryGetValue(utxo.ScriptPubKey.ToString(), out WatchedAddress addressInWallet); if (addressInWallet != null) { // Retrieve a transaction, if present. addressInWallet.Transactions.TryGetValue(transactionHash.ToString(), out TransactionData existingTransaction); if (existingTransaction == null) { var newTransaction = new TransactionData { Id = transactionHash, Hex = transaction.ToHex(), BlockHash = block?.GetHash() }; // Add the Merkle proof to the (non-spending) transaction. if (block != null) { newTransaction.MerkleProof = new MerkleBlock(block, new[] { transactionHash }).PartialMerkleTree; } addressInWallet.Transactions.TryAdd(transactionHash.ToString(), newTransaction); // Update the lookup cache with the new transaction information. // Since the WO record is new it probably isn't in the lookup cache. this.txLookup.TryAdd(newTransaction.Id, newTransaction); } else { // If there was a transaction already present in the WO wallet, // it is most likely that it has now been confirmed in a block. // Therefore, update the transaction record with the hash of the // block containing the transaction. if (existingTransaction.BlockHash == null) { existingTransaction.BlockHash = block?.GetHash(); } if (block != null && existingTransaction.MerkleProof == null) { // Add the Merkle proof now that the transaction is confirmed in a block. existingTransaction.MerkleProof = new MerkleBlock(block, new[] { transactionHash }).PartialMerkleTree; } // Update the lookup cache with the new transaction information. // Since the WO record was not new it probably is already in the lookup cache. // Therefore, unconditionally update it. this.txLookup.AddOrUpdate(existingTransaction.Id, existingTransaction, (key, oldValue) => existingTransaction); } this.SaveWatchOnlyWallet(); } } this.Wallet.WatchedTransactions.TryGetValue(transactionHash.ToString(), out TransactionData existingWatchedTransaction); if (existingWatchedTransaction != null && block != null) { // The transaction was previously stored, in an unconfirmed state. // So now update the block hash and Merkle proof since it has // appeared in a block. existingWatchedTransaction.BlockHash = block.GetHash(); existingWatchedTransaction.MerkleProof = new MerkleBlock(block, new[] { transaction.GetHash() }).PartialMerkleTree; // Update the lookup cache with the new transaction information. this.txLookup.AddOrUpdate(existingWatchedTransaction.Id, existingWatchedTransaction, (key, oldValue) => existingWatchedTransaction); this.SaveWatchOnlyWallet(); } }
public Task <GetTransactionResponse> GetTransaction(uint256 transactionId) { return(Get <GetTransactionResponse>("transactions/" + EscapeUrlPart(transactionId.ToString()) + CreateParameters())); }
private async void Round_StatusChangedAsync(object sender, CcjRoundStatus status) { try { var round = sender as CcjRound; Money feePerInputs = null; Money feePerOutputs = null; // If success save the coinjoin. if (status == CcjRoundStatus.Succeded) { using (await CoinJoinsLock.LockAsync()) { uint256 coinJoinHash = round.SignedCoinJoin.GetHash(); CoinJoins.Add(coinJoinHash); await File.AppendAllLinesAsync(CoinJoinsFilePath, new[] { coinJoinHash.ToString() }); // When a round succeeded, adjust the denomination as to users still be able to register with the latest round's active output amount. IEnumerable <(Money value, int count)> outputs = round.SignedCoinJoin.GetIndistinguishableOutputs(includeSingle: true); var bestOutput = outputs.OrderByDescending(x => x.count).FirstOrDefault(); if (bestOutput != default) { Money activeOutputAmount = bestOutput.value; int currentConfirmationTarget = await AdjustConfirmationTargetAsync(lockCoinJoins : false); var fees = await CcjRound.CalculateFeesAsync(RpcClient, currentConfirmationTarget); feePerInputs = fees.feePerInputs; feePerOutputs = fees.feePerOutputs; Money newDenominationToGetInWithactiveOutputs = activeOutputAmount - (feePerInputs + 2 * feePerOutputs); if (newDenominationToGetInWithactiveOutputs < RoundConfig.Denomination) { if (newDenominationToGetInWithactiveOutputs > Money.Coins(0.01m)) { RoundConfig.Denomination = newDenominationToGetInWithactiveOutputs; await RoundConfig.ToFileAsync(); } } } } } // If aborted in signing phase, then ban Alices those didn't sign. if (status == CcjRoundStatus.Aborted && round.Phase == CcjRoundPhase.Signing) { IEnumerable <Alice> alicesDidntSign = round.GetAlicesByNot(AliceState.SignedCoinJoin, syncLock: false); CcjRound nextRound = GetCurrentInputRegisterableRoundOrDefault(syncLock: false); if (nextRound != null) { int nextRoundAlicesCount = nextRound.CountAlices(syncLock: false); var alicesSignedCount = round.AnonymitySet - alicesDidntSign.Count(); // New round's anonset should be the number of alices those signed in this round. // Except if the number of alices in the next round is already larger. var newAnonymitySet = Math.Max(alicesSignedCount, nextRoundAlicesCount); // But it cannot be larger than the current anonset of that round. newAnonymitySet = Math.Min(newAnonymitySet, nextRound.AnonymitySet); // Only change the anonymity set of the next round if new anonset doesnt equal and newanonset larger than 1. if (nextRound.AnonymitySet != newAnonymitySet && newAnonymitySet > 1) { nextRound.UpdateAnonymitySet(newAnonymitySet, syncLock: false); if (nextRoundAlicesCount >= nextRound.AnonymitySet) { // Progress to the next phase, which will be OutputRegistration await nextRound.ExecuteNextPhaseAsync(CcjRoundPhase.ConnectionConfirmation); } } } foreach (Alice alice in alicesDidntSign) // Because the event sometimes is raised from inside the lock. { // If its from any coinjoin, then don't ban. IEnumerable <OutPoint> utxosToBan = alice.Inputs.Select(x => x.Outpoint); await UtxoReferee.BanUtxosAsync(1, DateTimeOffset.UtcNow, forceNoted : false, round.RoundId, utxosToBan.ToArray()); } } // If finished start a new round. if (status == CcjRoundStatus.Aborted || status == CcjRoundStatus.Succeded) { round.StatusChanged -= Round_StatusChangedAsync; round.CoinJoinBroadcasted -= Round_CoinJoinBroadcasted; await MakeSureTwoRunningRoundsAsync(feePerInputs, feePerOutputs); } } catch (Exception ex) { Logger.LogWarning <CcjCoordinator>(ex); } }
public void SetCoins(uint256 txId, Coins coins) { Index.PutAsync(txId.ToString(), coins); }
public Transaction GetRawTransaction(uint256 txid) { var response = SendCommand("getrawtransaction", txid.ToString()); var tx = new Transaction(); tx.ReadWrite(Encoders.Hex.DecodeData(response.Result.ToString())); return tx; }
public BlockHeader GetBlockHeader(uint256 blockHash) { var resp = SendCommand("getblock", blockHash.ToString()); return(ParseBlockHeader(resp)); }
/// <summary> /// Gets blocks headers. /// </summary> /// <param name="blockId">The initial block identifier.</param> /// <param name="count">how many headers to get.</param> /// <returns>Given a block hash (blockId) returns as much block headers as specified.</returns> /// <exception cref="System.ArgumentNullException">blockId cannot be null</exception> /// <exception cref="System.ArgumentOutOfRangeException">count must be greater or equal to one.</exception> public async Task<IEnumerable<BlockHeader>> GetBlockHeadersAsync(uint256 blockId, int count) { if(blockId == null) throw new ArgumentNullException("blockId"); if(count < 1) throw new ArgumentOutOfRangeException("count", "count must be greater or equal to one."); var result = await SendRequestAsync("headers", _format, count.ToString(CultureInfo.InvariantCulture), blockId.ToString()).ConfigureAwait(false); const int hexSize = (BlockHeader.Size); return Enumerable .Range(0, result.Length / hexSize) .Select(i => new BlockHeader(result.SafeSubarray(i * hexSize, hexSize))); }
/// <summary> /// Gets a transaction. /// </summary> /// <param name="txId">The transaction identifier.</param> /// <returns>Given a transaction hash (id) returns the requested transaction object.</returns> /// <exception cref="System.ArgumentNullException">txId cannot be null</exception> public async Task<Transaction> GetTransactionAsync(uint256 txId) { if(txId == null) throw new ArgumentNullException("txId"); var result = await SendRequestAsync("tx", _format, txId.ToString()).ConfigureAwait(false); return new Transaction(result); }
public Task <Block> GetAsync(uint256 id) { return(GetAsync(id.ToString())); }
public BlockHeader GetBlockHeader(uint256 blockHash) { var resp = SendCommand("getblock", blockHash.ToString()); return ParseBlockHeader(resp); }
public async Task <Transaction> GetRawTransactionAsync(uint256 txid, bool throwIfNotFound = true) { var response = await SendCommandAsync(new RPCRequest("getrawtransaction", new[] { txid.ToString() }), throwIfNotFound).ConfigureAwait(false); if (throwIfNotFound) { response.ThrowIfError(); } if (response.Error != null && response.Error.Code == RPCErrorCode.RPC_INVALID_ADDRESS_OR_KEY) { return(null); } response.ThrowIfError(); var tx = new Transaction(); tx.ReadWrite(Encoders.Hex.DecodeData(response.Result.ToString())); return(tx); }
public async Task<BlockHeader> GetBlockHeaderAsync(uint256 blockHash) { var resp = await SendCommandAsync("getblock", blockHash.ToString()).ConfigureAwait(false); return ParseBlockHeader(resp); }
public Task <Coins> GetCoinsAsync(uint256 txId) { return(Index.GetAsync <Coins>(txId.ToString())); }
public async Task<Transaction> GetRawTransactionAsync(uint256 txid, bool throwIfNotFound = true) { var response = await SendCommandAsync(new RPCRequest("getrawtransaction", new[] { txid.ToString() }), throwIfNotFound).ConfigureAwait(false); if (throwIfNotFound) response.ThrowIfError(); if (response.Error != null && response.Error.Code == RPCErrorCode.RPC_INVALID_ADDRESS_OR_KEY) return null; response.ThrowIfError(); var tx = new Transaction(); tx.ReadWrite(Encoders.Hex.DecodeData(response.Result.ToString())); return tx; }
/// <summary> /// GetTransactions only returns on txn which are not entirely spent unless you run bitcoinq with txindex=1. /// </summary> /// <param name="blockHash"></param> /// <returns></returns> public IEnumerable<Transaction> GetTransactions(uint256 blockHash) { if (blockHash == null) throw new ArgumentNullException("blockHash"); var resp = SendCommand("getblock", blockHash.ToString()); var tx = resp.Result["tx"] as JArray; if (tx != null) { foreach (var item in tx) { var result = GetRawTransaction(uint256.Parse(item.ToString()), false); if (result != null) yield return result; } } }
public async Task <TransactionEntry> GetTransactionAsync(bool loadPreviousOutput, bool fetchColor, uint256 txId) { if (txId == null) { return(null); } TransactionEntry result = null; var table = Configuration.GetTransactionTable(); var searchedEntity = new TransactionEntry.Entity(txId); var query = new TableQuery <DynamicTableEntity>() .Where( TableQuery.CombineFilters( TableQuery.GenerateFilterCondition("PartitionKey", QueryComparisons.Equal, searchedEntity.PartitionKey), TableOperators.And, TableQuery.CombineFilters( TableQuery.GenerateFilterCondition("RowKey", QueryComparisons.GreaterThan, txId.ToString() + "-"), TableOperators.And, TableQuery.GenerateFilterCondition("RowKey", QueryComparisons.LessThan, txId.ToString() + "|") ) )); query.TakeCount = 10; //Should not have more List <TransactionEntry.Entity> entities = new List <TransactionEntry.Entity>(); foreach (var e in await table.ExecuteQuerySegmentedAsync(query, null).ConfigureAwait(false)) { if (e.IsFat()) { entities.Add(new TransactionEntry.Entity(await FetchFatEntity(e).ConfigureAwait(false), ConsensuFactory)); } else { entities.Add(new TransactionEntry.Entity(e, ConsensuFactory)); } } if (entities.Count == 0) { result = null; } else { result = new TransactionEntry(entities.ToArray()); if (result.Transaction == null) { foreach (var block in result.BlockIds.Select(id => GetBlock(id)).Where(b => b != null)) { result.Transaction = block.Transactions.FirstOrDefault(t => t.GetHash() == txId); entities[0].Transaction = result.Transaction; if (entities[0].Transaction != null) { await UpdateEntity(table, entities[0].CreateTableEntity()).ConfigureAwait(false); } break; } } if (fetchColor && result.ColoredTransaction == null) { result.ColoredTransaction = await ColoredTransaction.FetchColorsAsync(txId, result.Transaction, new CachedColoredTransactionRepository(new IndexerColoredTransactionRepository(Configuration))).ConfigureAwait(false); entities[0].ColoredTransaction = result.ColoredTransaction; if (entities[0].ColoredTransaction != null) { await UpdateEntity(table, entities[0].CreateTableEntity()).ConfigureAwait(false); } } var needTxOut = result.SpentCoins == null && loadPreviousOutput && result.Transaction != null; if (needTxOut) { var inputs = result.Transaction.Inputs.Select(o => o.PrevOut).ToArray(); var parents = await GetTransactionsAsync(false, false, inputs .Select(i => i.Hash) .ToArray()).ConfigureAwait(false); for (int i = 0; i < parents.Length; i++) { if (parents[i] == null) { IndexerTrace.MissingTransactionFromDatabase(result.Transaction.Inputs[i].PrevOut.Hash); return(null); } } var outputs = parents.Select((p, i) => p.Transaction.Outputs[inputs[i].N]).ToArray(); result.SpentCoins = Enumerable .Range(0, inputs.Length) .Select(i => new Spendable(inputs[i], outputs[i])) .ToList(); entities[0].PreviousTxOuts.Clear(); entities[0].PreviousTxOuts.AddRange(outputs); if (entities[0].IsLoaded) { await UpdateEntity(table, entities[0].CreateTableEntity()).ConfigureAwait(false); } } } return(result != null && result.Transaction != null ? result : null); }
public CcjCoordinator(Network network, TrustedNodeNotifyingBehavior trustedNodeNotifyingBehavior, string folderPath, RPCClient rpc, CcjRoundConfig roundConfig) { Network = Guard.NotNull(nameof(network), network); TrustedNodeNotifyingBehavior = Guard.NotNull(nameof(trustedNodeNotifyingBehavior), trustedNodeNotifyingBehavior); FolderPath = Guard.NotNullOrEmptyOrWhitespace(nameof(folderPath), folderPath, trim: true); RpcClient = Guard.NotNull(nameof(rpc), rpc); RoundConfig = Guard.NotNull(nameof(roundConfig), roundConfig); Rounds = new List <CcjRound>(); RoundsListLock = new AsyncLock(); CoinJoins = new List <uint256>(); CoinJoinsLock = new AsyncLock(); Directory.CreateDirectory(FolderPath); UtxoReferee = new UtxoReferee(Network, FolderPath, RpcClient, RoundConfig); if (File.Exists(CoinJoinsFilePath)) { try { var toRemove = new List <string>(); string[] allLines = File.ReadAllLines(CoinJoinsFilePath); foreach (string line in allLines) { try { uint256 txHash = new uint256(line); RPCResponse getRawTransactionResponse = RpcClient.SendCommand(RPCOperations.getrawtransaction, txHash.ToString(), true); CoinJoins.Add(txHash); } catch (Exception ex) { toRemove.Add(line); var logEntry = ex is RPCException rpce && rpce.RPCCode == RPCErrorCode.RPC_INVALID_ADDRESS_OR_KEY ? $"CoinJoins file contains invalid transaction ID {line}" : $"CoinJoins file got corrupted. Deleting offending line \"{line.Substring(0, 20)}\"."; Logger.LogWarning <CcjCoordinator>($"{logEntry}. {ex.GetType()}: {ex.Message}"); } } if (toRemove.Count != 0) // a little performance boost, it'll be empty almost always { var newAllLines = allLines.Where(x => !toRemove.Contains(x)); File.WriteAllLines(CoinJoinsFilePath, newAllLines); } } catch (Exception ex) { Logger.LogWarning <CcjCoordinator>($"CoinJoins file got corrupted. Deleting {CoinJoinsFilePath}. {ex.GetType()}: {ex.Message}"); File.Delete(CoinJoinsFilePath); } } try { string roundCountFilePath = Path.Combine(folderPath, "RoundCount.txt"); if (File.Exists(roundCountFilePath)) { string roundCount = File.ReadAllText(roundCountFilePath); CcjRound.RoundCount = long.Parse(roundCount); } else { // First time initializes (so the first constructor will increment it and we'll start from 1.) CcjRound.RoundCount = 0; } } catch (Exception ex) { CcjRound.RoundCount = 0; Logger.LogInfo <CcjCoordinator>($"{nameof(CcjRound.RoundCount)} file was corrupt. Resetting to 0."); Logger.LogDebug <CcjCoordinator>(ex); } TrustedNodeNotifyingBehavior.Block += TrustedNodeNotifyingBehavior_BlockAsync; }
public Transaction GetKnownTransaction(uint256 txId) { return(Repository.Get <Record>("Broadcasts", txId.ToString())?.Transaction ?? Repository.Get <Transaction>("CachedTransactions", txId.ToString())); }
public void methods() { Assert.True(R1L.GetHex() == R1L.ToString()); Assert.True(R2L.GetHex() == R2L.ToString()); Assert.True(OneL.GetHex() == OneL.ToString()); Assert.True(MaxL.GetHex() == MaxL.ToString()); uint256 TmpL = new uint256(R1L); Assert.True(TmpL == R1L); TmpL.SetHex(R2L.ToString()); Assert.True(TmpL == R2L); TmpL.SetHex(ZeroL.ToString()); Assert.True(TmpL == 0); TmpL.SetHex(HalfL.ToString()); Assert.True(TmpL == HalfL); TmpL.SetHex(R1L.ToString()); AssertEx.CollectionEquals(R1L.ToBytes(), R1Array); AssertEx.CollectionEquals(TmpL.ToBytes(), R1Array); AssertEx.CollectionEquals(R2L.ToBytes(), R2Array); AssertEx.CollectionEquals(ZeroL.ToBytes(), ZeroArray); AssertEx.CollectionEquals(OneL.ToBytes(), OneArray); Assert.True(R1L.Size == 32); Assert.True(R2L.Size == 32); Assert.True(ZeroL.Size == 32); Assert.True(MaxL.Size == 32); //No sense in .NET //Assert.True(R1L.begin() + 32 == R1L.end()); //Assert.True(R2L.begin() + 32 == R2L.end()); //Assert.True(OneL.begin() + 32 == OneL.end()); //Assert.True(MaxL.begin() + 32 == MaxL.end()); //Assert.True(TmpL.begin() + 32 == TmpL.end()); Assert.True(R1L.GetLow64() == R1LLow64); Assert.True(HalfL.GetLow64() == 0x0000000000000000UL); Assert.True(OneL.GetLow64() == 0x0000000000000001UL); Assert.True(R1L.GetSerializeSize(0, ProtocolVersion.PROTOCOL_VERSION) == 32); Assert.True(ZeroL.GetSerializeSize(0, ProtocolVersion.PROTOCOL_VERSION) == 32); MemoryStream ss = new MemoryStream(); R1L.Serialize(ss, 0, ProtocolVersion.PROTOCOL_VERSION); Assert.True(ArrayToString(ss.ToArray()) == ArrayToString(R1Array)); TmpL.Unserialize(ss, 0, ProtocolVersion.PROTOCOL_VERSION); Assert.True(R1L == TmpL); ss = new MemoryStream(); ZeroL.Serialize(ss, 0, ProtocolVersion.PROTOCOL_VERSION); Assert.True(ArrayToString(ss.ToArray()) == ArrayToString(ZeroArray)); ss.Position = 0; TmpL.Unserialize(ss, 0, ProtocolVersion.PROTOCOL_VERSION); Assert.True(ZeroL == TmpL); ss = new MemoryStream(); MaxL.Serialize(ss, 0, ProtocolVersion.PROTOCOL_VERSION); Assert.True(ArrayToString(ss.ToArray()) == ArrayToString(MaxArray)); ss.Position = 0; TmpL.Unserialize(ss, 0, ProtocolVersion.PROTOCOL_VERSION); Assert.True(MaxL == TmpL); ss = new MemoryStream(); Assert.True(R1S.GetHex() == R1S.ToString()); Assert.True(R2S.GetHex() == R2S.ToString()); Assert.True(OneS.GetHex() == OneS.ToString()); Assert.True(MaxS.GetHex() == MaxS.ToString()); uint160 TmpS = new uint160(R1S); Assert.True(TmpS == R1S); TmpS.SetHex(R2S.ToString()); Assert.True(TmpS == R2S); TmpS.SetHex(ZeroS.ToString()); Assert.True(TmpS == 0); TmpS.SetHex(HalfS.ToString()); Assert.True(TmpS == HalfS); TmpS.SetHex(R1S.ToString()); Assert.True(ArrayToString(R1S.ToBytes()) == ArrayToString(R1Array.Take(20).ToArray())); Assert.True(ArrayToString(TmpS.ToBytes()) == ArrayToString(R1Array.Take(20).ToArray())); Assert.True(ArrayToString(R2S.ToBytes()) == ArrayToString(R2Array.Take(20).ToArray())); Assert.True(ArrayToString(ZeroS.ToBytes()) == ArrayToString(ZeroArray.Take(20).ToArray())); Assert.True(ArrayToString(OneS.ToBytes()) == ArrayToString(OneArray.Take(20).ToArray())); Assert.True(R1S.Size == 20); Assert.True(R2S.Size == 20); Assert.True(ZeroS.Size == 20); Assert.True(MaxS.Size == 20); //No sense in .NET //Assert.True(R1S.begin() + 20 == R1S.end()); //Assert.True(R2S.begin() + 20 == R2S.end()); //Assert.True(OneS.begin() + 20 == OneS.end()); //Assert.True(MaxS.begin() + 20 == MaxS.end()); //Assert.True(TmpS.begin() + 20 == TmpS.end()); Assert.True(R1S.GetLow64() == R1LLow64); Assert.True(HalfS.GetLow64() == 0x0000000000000000UL); Assert.True(OneS.GetLow64() == 0x0000000000000001UL); Assert.True(R1S.GetSerializeSize(0, ProtocolVersion.PROTOCOL_VERSION) == 20); Assert.True(ZeroS.GetSerializeSize(0, ProtocolVersion.PROTOCOL_VERSION) == 20); R1S.Serialize(ss, 0, ProtocolVersion.PROTOCOL_VERSION); Assert.True(ArrayToString(ss.ToArray()) == ArrayToString(R1Array.Take(20).ToArray())); ss.Position = 0; TmpS.Unserialize(ss, 0, ProtocolVersion.PROTOCOL_VERSION); Assert.True(R1S == TmpS); ss = new MemoryStream(); ZeroS.Serialize(ss, 0, ProtocolVersion.PROTOCOL_VERSION); Assert.True(ArrayToString(ss.ToArray()) == ArrayToString(ZeroArray.Take(20).ToArray())); ss.Position = 0; TmpS.Unserialize(ss, 0, ProtocolVersion.PROTOCOL_VERSION); Assert.True(ZeroS == TmpS); ss = new MemoryStream(); MaxS.Serialize(ss, 0, ProtocolVersion.PROTOCOL_VERSION); Assert.True(ArrayToString(ss.ToArray()) == ArrayToString(MaxArray.Take(20).ToArray())); ss.Position = 0; TmpS.Unserialize(ss, 0, ProtocolVersion.PROTOCOL_VERSION); Assert.True(MaxS == TmpS); ss = new MemoryStream(); //for(int i = 0 ; i < 255 ; ++i) //{ // Assert.True((OneL << i).GetDouble() == Math.Pow(1.0, i)); // if(i < 160) // Assert.True((OneS << i).GetDouble() == Math.Pow(1.0, i)); //} //Assert.True(ZeroL.GetDouble() == 0.0); //Assert.True(ZeroS.GetDouble() == 0.0); //for(int i = 256 ; i > 53 ; --i) // Assert.True(almostEqual((R1L >> (256 - i)).GetDouble(), Math.Pow(R1Ldouble, i))); //for(int i = 160 ; i > 53 ; --i) // Assert.True(almostEqual((R1S >> (160 - i)).GetDouble(), Math.Pow(R1Sdouble, i))); //ulong R1L64part = (R1L >> 192).GetLow64(); //ulong R1S64part = (R1S >> 96).GetLow64(); //for(int i = 53 ; i > 0 ; --i) // doubles can store all integers in {0,...,2^54-1} exactly //{ // Assert.True((R1L >> (256 - i)).GetDouble() == (double)(R1L64part >> (64 - i))); // Assert.True((R1S >> (160 - i)).GetDouble() == (double)(R1S64part >> (64 - i))); //} }
public async Task GetRawTransactionWithTransactionInMempoolAsync() { using (NodeBuilder builder = NodeBuilder.Create(this)) { //Arrange. // Create a sending and a receiving node. CoreNode sendingNode = builder.CreateStratisPosNode(this.network).WithReadyBlockchainData(ReadyBlockchain.StratisRegTest150Miner).Start(); CoreNode receivingNode = builder.CreateStratisPosNode(this.network).WithReadyBlockchainData(ReadyBlockchain.StratisRegTest150Listener).Start(); TestHelper.ConnectAndSync(sendingNode, receivingNode); // Get an address to send to. IEnumerable <string> unusedaddresses = await $"http://localhost:{receivingNode.ApiPort}/api" .AppendPathSegment("wallet/unusedAddresses") .SetQueryParams(new { walletName = "mywallet", accountName = "account 0", count = 1 }) .GetJsonAsync <IEnumerable <string> >(); // Build and send a transaction. WalletBuildTransactionModel buildTransactionModel = await $"http://localhost:{sendingNode.ApiPort}/api" .AppendPathSegment("wallet/build-transaction") .PostJsonAsync(new BuildTransactionRequest { WalletName = "mywallet", AccountName = "account 0", FeeType = "low", Password = "******", ShuffleOutputs = true, AllowUnconfirmed = true, Recipients = unusedaddresses.Select(address => new RecipientModel { DestinationAddress = address, Amount = "1" }).ToList(), }) .ReceiveJson <WalletBuildTransactionModel>(); await $"http://localhost:{sendingNode.ApiPort}/api" .AppendPathSegment("wallet/send-transaction") .PostJsonAsync(new SendTransactionRequest { Hex = buildTransactionModel.Hex }) .ReceiveJson <WalletSendTransactionModel>(); uint256 txId = buildTransactionModel.TransactionId; // Act. RPCClient rpc = sendingNode.CreateRPCClient(); RPCResponse response = await rpc.SendCommandAsync(RPCOperations.getrawtransaction, txId.ToString()); // Assert. response.ResultString.Should().Be(buildTransactionModel.Hex); } }
public void CanChooseInputsForCall() { const int utxoIndex = 0; uint256 utxoId = uint256.Zero; uint256 utxoIdUnused = uint256.One; string senderAddress = uint160.Zero.ToBase58Address(this.network); string contractAddress = uint160.One.ToBase58Address(this.network); var request = new BuildCallContractTransactionRequest { Amount = "0", AccountName = "account 0", ContractAddress = contractAddress, FeeAmount = "0.01", GasLimit = 100_000, GasPrice = 100, MethodName = "TestMethod", WalletName = "wallet", Password = "******", Sender = senderAddress, Outpoints = new List <OutpointRequest> { new OutpointRequest { Index = utxoIndex, TransactionId = utxoId.ToString() }, } }; this.walletManager.Setup(x => x.GetAddressBalance(request.Sender)) .Returns(new AddressBalance { Address = senderAddress, AmountConfirmed = new Money(100, MoneyUnit.BTC) }); this.walletManager.Setup(x => x.GetSpendableTransactionsInWallet(It.IsAny <string>(), 0)) .Returns(new List <UnspentOutputReference> { new UnspentOutputReference { Address = new HdAddress { Address = senderAddress }, Transaction = new TransactionData { Id = utxoId, Index = utxoIndex, } }, new UnspentOutputReference { Address = new HdAddress { Address = senderAddress }, Transaction = new TransactionData { Id = utxoIdUnused, Index = utxoIndex, } } }); var wallet = new Features.Wallet.Wallet(); wallet.AccountsRoot.Add(new AccountRoot(wallet)); var account0 = new HdAccount(wallet.AccountsRoot.First().Accounts) { Name = request.AccountName }; account0.ExternalAddresses.Add(new HdAddress() { Address = senderAddress }); this.walletManager.Setup(x => x.GetWallet(request.WalletName)) .Returns(wallet); var reserveUtxoService = new ReserveUtxoService(this.loggerFactory, new Mock <ISignals>().Object); var service = new SmartContractTransactionService( this.network, this.walletManager.Object, this.walletTransactionHandler.Object, this.stringSerializer.Object, this.callDataSerializer.Object, this.addressGenerator.Object, this.stateRepository.Object, reserveUtxoService); BuildCallContractTransactionResponse result = service.BuildCallTx(request); this.walletTransactionHandler.Verify(x => x.BuildTransaction(It.Is <TransactionBuildContext>(y => y.SelectedInputs.Count == 1))); }
public CcjCoordinator(Network network, string folderPath, RPCClient rpc, CcjRoundConfig roundConfig) { Network = Guard.NotNull(nameof(network), network); FolderPath = Guard.NotNullOrEmptyOrWhitespace(nameof(folderPath), folderPath, trim: true); RpcClient = Guard.NotNull(nameof(rpc), rpc); RoundConfig = Guard.NotNull(nameof(roundConfig), roundConfig); Rounds = new List <CcjRound>(); RoundsListLock = new AsyncLock(); CoinJoins = new List <uint256>(); UnconfirmedCoinJoins = new List <uint256>(); CoinJoinsLock = new AsyncLock(); Directory.CreateDirectory(FolderPath); UtxoReferee = new UtxoReferee(Network, FolderPath, RpcClient); // Initialize RsaKey string rsaKeyPath = Path.Combine(FolderPath, "RsaKey.json"); if (File.Exists(rsaKeyPath)) { string rsaKeyJson = File.ReadAllText(rsaKeyPath, encoding: Encoding.UTF8); RsaKey = BlindingRsaKey.CreateFromJson(rsaKeyJson); } else { RsaKey = new BlindingRsaKey(); File.WriteAllText(rsaKeyPath, RsaKey.ToJson(), encoding: Encoding.UTF8); Logger.LogInfo <CcjCoordinator>($"Created RSA key at: {rsaKeyPath}"); } if (File.Exists(CoinJoinsFilePath)) { try { var toRemove = new List <string>(); string[] allLines = File.ReadAllLines(CoinJoinsFilePath); foreach (string line in allLines) { uint256 txHash = new uint256(line); RPCResponse getRawTransactionResponse = RpcClient.SendCommand(RPCOperations.getrawtransaction, txHash.ToString(), true); if (string.IsNullOrWhiteSpace(getRawTransactionResponse?.ResultString)) { toRemove.Add(line); } else { CoinJoins.Add(txHash); if (getRawTransactionResponse.Result.Value <int>("confirmations") <= 0) { UnconfirmedCoinJoins.Add(txHash); } } } if (toRemove.Count != 0) // a little performance boost, it'll be empty almost always { var newAllLines = allLines.Where(x => !toRemove.Contains(x)); File.WriteAllLines(CoinJoinsFilePath, newAllLines); } } catch (Exception ex) { Logger.LogWarning <CcjCoordinator>($"CoinJoins file got corrupted. Deleting {CoinJoinsFilePath}. {ex.GetType()}: {ex.Message}"); File.Delete(CoinJoinsFilePath); } } }
public void WriteToString() { Value.ToString(); }
public void LoadConfigWithAssumeValidHexLoads() { var validHexBlock = new uint256("00000000229d9fb87182d73870d53f9fdd9b76bfc02c059e6d9a6c7a3507031d"); Network network = KnownNetworks.TestNet; var nodeSettings = new NodeSettings(network, args: new string[] { $"-assumevalid={validHexBlock.ToString()}" }); var settings = new ConsensusSettings(nodeSettings); Assert.Equal(validHexBlock, settings.BlockAssumedValid); }
public Task<Coins> GetCoinsAsync(uint256 txId) { return Index.GetAsync<Coins>(txId.ToString()); }
public void LoadConfigWithAssumeValidHexLoads() { uint256 validHexBlock = new uint256("00000000229d9fb87182d73870d53f9fdd9b76bfc02c059e6d9a6c7a3507031d"); LoggerFactory loggerFactory = new LoggerFactory(); Network network = Network.TestNet; NodeSettings nodeSettings = new NodeSettings(network.Name, network).LoadArguments(new string[] { $"-assumevalid={validHexBlock.ToString()}" }); ConsensusSettings settings = new ConsensusSettings(nodeSettings, loggerFactory); Assert.Equal(validHexBlock, settings.BlockAssumedValid); }
public static string ToId(uint256 hash) { return($"{Prefix}{hash.ToString()}"); }
public void MerkleRootComputationNotMutated() { var leaves = new List <uint256>() { new uint256("281f5acb40a15640bc48b90b5296a87d09341e3510608b191c9bc3a511f8e436"), new uint256("f4570fd8c54fded84b696ba3eb986a5421b0a41109dea6e10ba96aec70f78f00") }; bool mutated; uint256 root = ComputeMerkleRoot(leaves, out mutated); Assert.Equal("cd00f5d5aada62c8e49a9f01378998cbd016d04b725d0d8497877e5f75ffc722", root.ToString()); Assert.False(mutated); }
/// <summary> /// Get the a whole block /// </summary> /// <param name="blockId"></param> /// <returns></returns> public async Task <Block> GetBlockAsync(uint256 blockId) { var resp = await SendCommandAsync("getblock", blockId.ToString(), false).ConfigureAwait(false); return(new Block(Encoders.Hex.DecodeData(resp.Result.ToString()))); }
public void MerkleRootComputationMutated() { var leaves = new List <uint256>() { new uint256("281f5acb40a65640bc48b90b5296a87d09341e3510608b191c9bc3a511f8e436"), new uint256("d0249653efaaa999f0278bb390c0f4ec3e5465a10f35264ebcfbb6dd6a677abd"), new uint256("7897c117fddbf98ea9749cc868a9d1e663b198dd3ac0ae5837734007f0060b20"), new uint256("ced314892a97f342a136269e2842fd0dbd1cab1fa84557bc48420f7cf96f0bc7"), new uint256("5b98af3d7554916483bca1a52f16570a93f07c95d6aeb8d08b0794c86cf58128"), new uint256("5b98af3d7554916483bca1a52f16570a93f07c95d6aeb8d08b0794c86cf58128"), new uint256("5b98af3d7554916483bca1a52f16570a93f07c95d6aeb8d08b0794c86cf58128"), new uint256("91be5a63b4b70c8329f20960e49a8bd3adeb77fcbadf78014ac54efaf1647a31"), new uint256("ac2dcf5c46d9a801389b6c0630b435ce5c2fa850cfac5456f16937dd8ae697d3") }; bool mutated; uint256 root = this.ComputeMerkleRoot(leaves, out mutated); Assert.Equal("95aa5bba66381c3817df338895349acd3fc3e8ce226e04a5e2acbb53db18b9c0", root.ToString()); Assert.True(mutated); }
public async Task <BlockHeader> GetBlockHeaderAsync(uint256 blockHash) { var resp = await SendCommandAsync("getblock", blockHash.ToString()).ConfigureAwait(false); return(ParseBlockHeader(resp)); }
public Coins GetCoins(uint256 txId) { return(Index.GetAsync <Coins>(txId.ToString()).GetAwaiter().GetResult()); }
/// <summary> /// Gets blocks headers. /// </summary> /// <param name="blockId">The initial block identifier.</param> /// <param name="count">how many headers to get.</param> /// <returns>Given a block hash (blockId) returns as much block headers as specified.</returns> /// <exception cref="System.ArgumentNullException">blockId cannot be null</exception> /// <exception cref="System.ArgumentOutOfRangeException">count must be greater or equal to one.</exception> public async Task <IEnumerable <BlockHeader> > GetBlockHeadersAsync(uint256 blockId, int count) { if (blockId == null) { throw new ArgumentNullException("blockId"); } if (count < 1) { throw new ArgumentOutOfRangeException("count", "count must be greater or equal to one."); } var result = await SendRequestAsync("headers", RestResponseFormat.Bin, count.ToString(CultureInfo.InvariantCulture), blockId.ToString()).ConfigureAwait(false); const int hexSize = (BlockHeader.Size); return(Enumerable .Range(0, result.Length / hexSize) .Select(i => new BlockHeader(result.SafeSubarray(i * hexSize, hexSize)))); }
public BlockHeader GetBlockHeader(uint256 blockHash) { var resp = SendCommand("getblock", blockHash.ToString()); BlockHeader header = new BlockHeader(); header.Version = (int)resp.Result["version"]; header.Nonce = (uint)resp.Result["nonce"]; header.Bits = new Target(Encoders.Hex.DecodeData((string)resp.Result["bits"])); if(resp.Result["previousblockhash"] != null) { header.HashPrevBlock = new uint256(Encoders.Hex.DecodeData((string)resp.Result["previousblockhash"]),false); } if(resp.Result["time"] != null) { header.BlockTime = Utils.UnixTimeToDateTime((uint)resp.Result["time"]); } if(resp.Result["merkleroot"] != null) { header.HashMerkleRoot = new uint256(Encoders.Hex.DecodeData((string)resp.Result["merkleroot"]),false); } return header; }