public async Task <string> SendTransaction(string transactionHex) { // todo: consider adding support for retries. // todo: check how a failure is porpageted SyncConnection connection = syncConnection; Transaction trx = null; // parse the trx; trx = connection.Network.Consensus.ConsensusFactory.CreateTransaction(transactionHex); trx.PrecomputeHash(false, true); IBlockchainClient client = clientFactory.Create(connection); string trxid = await client.SentRawTransactionAsync(transactionHex); if (trx.GetHash().ToString() != trxid) { throw new Exception($"node trxid = {trxid}, serialized trxid = {trx.GetHash().ToString()}"); } storageOperations.InsertMempoolTransactions(new SyncBlockTransactionsOperation { Transactions = new List <Transaction> { trx } }); return(trxid); }
public async Task <SyncBlockInfo> RewindToBestChain(SyncConnection connection) { IBlockchainClient client = clientFactory.Create(connection); while (true) { SyncBlockInfo block = storage.GetLatestBlock(); if (block == null) { return(null); } string currentHash = await client.GetblockHashAsync(block.BlockIndex); if (currentHash == block.BlockHash) { return(block); } log.LogDebug($"Rewinding block {block.BlockIndex}({block.BlockHash})"); await storage.DeleteBlockAsync(block.BlockHash); } }
public async Task CompareAddressBalances() { IAddressInfoService addressInfoService = Instantiate <IAddressInfoService>(); IBlockchainClient blockchainClient = Instantiate <IBlockchainClient>(); IEnumerable <string> addresses = new List <string>(); using (var uow = NewUnitOfWork()) { addresses = NewRepository <Address>(uow).GetAs(a => true, a => a.BlockchainAddress); } foreach (var address in addresses) { var databaseResult = addressInfoService.GetAddressInfo(address); Assert.True(databaseResult.Successful, $"Retrieving address {address} from database failed."); var blockchainResult = await blockchainClient.GetAddressInfo(address); Assert.True(blockchainResult.Successful, $"Retrieving address {address} from blockchain failed."); var addressInfoDto = databaseResult.Data; var addressBlockchainDto = blockchainResult.Data; Assert.True(addressBlockchainDto.Balance.Available == addressInfoDto.ChxBalanceInfo.AvailableBalance, $"Available CHX for {address} does not match."); Assert.True(addressBlockchainDto.Balance.Deposit == addressInfoDto.ChxBalanceInfo.ValidatorDeposit, $"Deposited CHX for {address} does not match."); Assert.True(addressBlockchainDto.Balance.Staked == addressInfoDto.ChxBalanceInfo.DelegatedStakes, $"Staked CHX for {address} does not match."); } }
private SyncBlockTransactionsOperation SyncPoolInternal(SyncConnection connection, SyncPoolTransactions poolTransactions) { IBlockchainClient client = clientFactory.Create(connection); SyncBlockTransactionsOperation returnBlock = SyncBlockTransactions(client, connection, poolTransactions.Transactions, false); return(returnBlock); }
public string GetRawBlock(string blockHash) { IBlockchainClient client = clientFactory.Create(syncConnection); string res = client.GetBlockHex(blockHash); return(res); }
public override async Task OnExecute() { IBlockchainClient client = clientFactory.Create(connection); List <string> allIndexes = mongoData.GetBlockIndexIndexes(); if (allIndexes.Count == BlockIndexer.ExpectedNumberOfIndexes) { Runner.GlobalState.IndexModeCompleted = true; } Runner.GlobalState.PullingTip = null; Runner.GlobalState.StoreTip = null; Runner.GlobalState.StoreTip = await syncOperations.RewindToLastCompletedBlockAsync(); if (Runner.GlobalState.StoreTip == null) { // No blocks in store start from zero // push the genesis block to store int start = 0; string genesisHash = await client.GetblockHashAsync(start); log.LogInformation($"Processing genesis hash = {genesisHash}"); BlockInfo genesisBlock = await client.GetBlockAsync(genesisHash); SyncBlockTransactionsOperation block = syncOperations.FetchFullBlock(connection, genesisBlock); StorageBatch genesisBatch = new StorageBatch(); storageOperations.AddToStorageBatch(genesisBatch, block); Runner.GlobalState.StoreTip = storageOperations.PushStorageBatch(genesisBatch); } BlockInfo fetchedBlock = await client.GetBlockAsync(Runner.GlobalState.StoreTip.BlockHash); if (fetchedBlock == null) { // check if the fullnode is ahead of the indexer height int fullnodeTipHeight = client.GetBlockCount(); if (fullnodeTipHeight < Runner.GlobalState.StoreTip.BlockIndex) { throw new ApplicationException($"Full node at height {fullnodeTipHeight} which is behind the Indexer at height {Runner.GlobalState.StoreTip.BlockIndex}"); } // reorg happend while indexer was offline rewind the indexer database Runner.GlobalState.PullingTip = null; Runner.GlobalState.StoreTip = null; Runner.GlobalState.StoreTip = await syncOperations.RewindToBestChain(connection); } // update the chains tip Runner.GlobalState.ChainTipHeight = syncOperations.GetBlockCount(client); }
public ImportService( IUnitOfWorkFactory unitOfWorkFactory, IRepositoryFactory repositoryFactory, IBlockchainClient blockchainClient, IActionService actionService) : base(unitOfWorkFactory, repositoryFactory) { _blockchainClient = blockchainClient; _actionService = actionService; }
public ScannerService( IBlockchainClient blockchainClient, IImportService importService, IUnitOfWorkFactory unitOfWorkFactory, IRepositoryFactory repositoryFactory) : base(unitOfWorkFactory, repositoryFactory) { _blockchainClient = blockchainClient; _importService = importService; }
public async Task <StatsConnection> StatsConnection() { SyncConnection connection = syncConnection; IBlockchainClient client = clientFactory.Create(connection); int clientConnection = await client.GetConnectionCountAsync(); return(new StatsConnection { Connections = clientConnection }); }
public long GetBlockCount(IBlockchainClient client) { if (!cache.TryGetValue(CacheKeys.BlockCount, out long cacheEntry)) { cacheEntry = client.GetBlockCount(); // Save data in cache. cache.Set(CacheKeys.BlockCount, cacheEntry, cacheOptions); } return(cacheEntry); }
public string GetRawTransaction(string transactionId) { // Try to find the trx in disk SyncRawTransaction rawtrx = TransactionGetByHash(transactionId); if (rawtrx != null) { return(Encoders.Hex.EncodeData(rawtrx.RawTransaction)); } IBlockchainClient client = clientFactory.Create(syncConnection); Client.Types.DecodedRawTransaction res = client.GetRawTransactionAsync(transactionId, 0).Result; if (res.Hex != null) { return(res.Hex); } return(null); }
private SyncBlockTransactionsOperation SyncBlockTransactions(IBlockchainClient client, SyncConnection connection, IEnumerable <string> transactionsToSync, bool throwIfNotFound) { var itemList = transactionsToSync.Select(t => new tcalc { item = t }).ToList(); var options = new ParallelOptions { MaxDegreeOfParallelism = configuration.ParallelRequestsToTransactionRpc }; Parallel.ForEach(itemList, options, (item) => { try { item.result = client.GetRawTransaction(item.item, 0); } catch (BitcoinClientException bce) { if (!throwIfNotFound && bce.IsTransactionNotFound()) { //// the transaction was not found in the client, //// if this is a pool sync we assume the transaction was initially found in the pool and became invalid. return; } throw; } }); IEnumerable <Transaction> transactions = itemList.Where(t => t.result != null).Select(s => { Transaction trx = connection.Network.Consensus.ConsensusFactory.CreateTransaction(s.result.Hex); trx.PrecomputeHash(false, true); return(trx); }); return(new SyncBlockTransactionsOperation { Transactions = transactions.ToList() }); }
private SyncPoolTransactions FindPoolInternal(SyncConnection connection) { IBlockchainClient client = clientFactory.Create(connection); IEnumerable <string> memPool = client.GetRawMemPool(); var currentMemoryPool = new HashSet <string>(memPool); var currentTable = new HashSet <string>(globalState.LocalMempoolView.Keys); var newTransactions = currentMemoryPool.Except(currentTable).ToList(); var deleteTransaction = currentTable.Except(currentMemoryPool).ToList(); // limit to 1k trx per loop newTransactions = newTransactions.Take(1000).ToList(); // entries deleted from mempool on the node // we also delete it in our store if (deleteTransaction.Any()) { List <string> toRemoveFromMempool = deleteTransaction; FilterDefinitionBuilder <MempoolTable> builder = Builders <MempoolTable> .Filter; FilterDefinition <MempoolTable> filter = builder.In(mempoolItem => mempoolItem.TransactionId, toRemoveFromMempool); db.Mempool.DeleteMany(filter); foreach (string mempooltrx in toRemoveFromMempool) { globalState.LocalMempoolView.Remove(mempooltrx, out _); } } return(new SyncPoolTransactions { Transactions = newTransactions }); }
public async Task CompareAccountHoldings() { IBlockchainInfoService blockchainInfoService = Instantiate <IBlockchainInfoService>(); IBlockchainClient blockchainClient = Instantiate <IBlockchainClient>(); IEnumerable <string> accounts = new List <string>(); using (var uow = NewUnitOfWork()) { accounts = NewRepository <Account>(uow).GetAs(a => true, a => a.Hash); } foreach (var account in accounts) { var databaseResult = blockchainInfoService.GetAccountInfo(account); Assert.True(databaseResult.Successful, $"Retrieving account {account} from database failed."); var blockchainResult = await blockchainClient.GetAccountInfo(account); Assert.True(blockchainResult.Successful, $"Retrieving account {account} from blockchain failed."); var accountInfoDto = databaseResult.Data; var accountBlockchainDto = blockchainResult.Data; Assert.Equal(accountBlockchainDto.Holdings.Count, accountInfoDto.Holdings.Count); foreach (var holdingInfo in accountInfoDto.Holdings) { var holdingBlockchain = accountBlockchainDto.Holdings .FirstOrDefault(h => h.AssetHash == holdingInfo.AssetHash); Assert.NotNull(holdingBlockchain); Assert.Equal(holdingBlockchain.Balance, holdingInfo.Balance); } } }