private List <Task <InteropBlock> > CreateTaskList(BigInteger batchCount, BigInteger[] blockIds = null) { List <Task <InteropBlock> > taskList = new List <Task <InteropBlock> >(); if (blockIds == null) { var _interopBlockHeight = BigInteger.Parse(OracleReader.GetCurrentHeight("neo", "neo")); var nextCurrentBlockHeight = _interopBlockHeight + batchCount; for (var i = _interopBlockHeight; i < nextCurrentBlockHeight; i++) { var url = DomainExtensions.GetOracleBlockURL( "neo", "neo", PBigInteger.FromUnsignedArray(i.ToByteArray(), true)); taskList.Add(CreateTask(url)); } } else { foreach (var blockId in blockIds) { var url = DomainExtensions.GetOracleBlockURL( "neo", "neo", PBigInteger.FromUnsignedArray(blockId.ToByteArray(), true)); taskList.Add(CreateTask(url)); } } return(taskList); }
public BSCInterop(TokenSwapper swapper, EthAPI ethAPI, PBigInteger interopBlockHeight, string[] contracts, uint confirmations) : base(swapper, BSCWallet.BSCPlatform) { string lastBlockHeight = OracleReader.GetCurrentHeight(BSCWallet.BSCPlatform, BSCWallet.BSCPlatform); if (string.IsNullOrEmpty(lastBlockHeight)) { OracleReader.SetCurrentHeight(BSCWallet.BSCPlatform, BSCWallet.BSCPlatform, new BigInteger(interopBlockHeight.ToSignedByteArray()).ToString()); } Logger.Message($"interopHeight: {OracleReader.GetCurrentHeight(BSCWallet.BSCPlatform, BSCWallet.BSCPlatform)}"); Console.WriteLine("encoded bsc: " + BSCWallet.EncodeAddress("0x44E8743A6CAC3E59594C19DD462863A5AA5E06BB")); Console.WriteLine("encoded eth: " + EthereumWallet.EncodeAddress("0x44E8743A6CAC3E59594C19DD462863A5AA5E06BB")); Console.WriteLine("from encoded bsc: " + BSCWallet.EncodeAddress("0xA89a34c37Da826085E458c17067DA2F38b6e4763")); Console.WriteLine("from encoded eth: " + EthereumWallet.EncodeAddress("0xA89a34c37Da826085E458c17067DA2F38b6e4763")); this.contracts = contracts.ToList(); // add local swap address to contracts this.contracts.Add(LocalAddress); this.confirmations = confirmations; this.ethAPI = ethAPI; }
public NeoInterop(TokenSwapper swapper, NeoAPI neoAPI, PBigInteger interopBlockHeight, bool quickSync) : base(swapper, NeoWallet.NeoPlatform) { string lastBlockHeight = OracleReader.GetCurrentHeight("neo", "neo"); if (string.IsNullOrEmpty(lastBlockHeight)) { OracleReader.SetCurrentHeight("neo", "neo", new BigInteger(interopBlockHeight.ToUnsignedByteArray()).ToString()); } this.quickSync = quickSync; Logger.Message($"interopHeight: {OracleReader.GetCurrentHeight("neo", "neo")}"); this.neoAPI = neoAPI; this.lastScan = DateTime.UtcNow.AddYears(-1);; }
public EthereumInterop(TokenSwapper swapper, EthAPI ethAPI, PBigInteger interopBlockHeight, string[] contracts, uint confirmations) : base(swapper, EthereumWallet.EthereumPlatform) { string lastBlockHeight = OracleReader.GetCurrentHeight(EthereumWallet.EthereumPlatform, EthereumWallet.EthereumPlatform); if (string.IsNullOrEmpty(lastBlockHeight)) { OracleReader.SetCurrentHeight(EthereumWallet.EthereumPlatform, EthereumWallet.EthereumPlatform, new BigInteger(interopBlockHeight.ToSignedByteArray()).ToString()); } Logger.Message($"interopHeight: {OracleReader.GetCurrentHeight(EthereumWallet.EthereumPlatform, EthereumWallet.EthereumPlatform)}"); this.contracts = contracts.ToList(); // add local swap address to contracts this.contracts.Add(LocalAddress); this.confirmations = confirmations; this.ethAPI = ethAPI; }
public override IEnumerable <PendingSwap> Update() { lock (String.Intern("PendingSetCurrentHeight_" + "neo")) { var result = new List <PendingSwap>(); try { var _interopBlockHeight = BigInteger.Parse(OracleReader.GetCurrentHeight("neo", "neo")); // initial start, we have to verify all processed swaps if (initialStart) { Logger.Debug($"Read all neo blocks now."); // TODO check if quick sync nodes are configured, if so use quick sync // we need to find a better solution for that though var allInteropBlocks = OracleReader.ReadAllBlocks("neo", "neo"); Logger.Debug($"Found {allInteropBlocks.Count} blocks"); foreach (var block in allInteropBlocks) { try { ProcessBlock(block, result); } catch (Exception e) { Logger.Debug($"Block {block.Hash} was not processed correctly: " + e); } } initialStart = false; Logger.Debug($"QuickSync: " + quickSync); // quick sync is only done once after startup if (quickSync) { // if quick sync is active, we can use a specific plugin installed on the nodes (EventTracker) try { var blockIds = neoAPI.GetSwapBlocks("ed07cffad18f1308db51920d99a2af60ac66a7b3", LocalAddress, _interopBlockHeight.ToString()); Logger.Debug($"Found {blockIds.Count} blocks to process "); List <InteropBlock> blockList = new List <InteropBlock>(); foreach (var entry in blockIds) { //logger.Debug($"read block {entry.Value}"); var url = DomainExtensions.GetOracleBlockURL("neo", "neo", PBigInteger.Parse(entry.Value.ToString())); blockList.Add(OracleReader.Read <InteropBlock>(DateTime.Now, url)); } // get blocks and order them for processing var blocksToProcess = blockList.Where(x => blockIds.ContainsKey(x.Hash.ToString())) .Select(x => new { block = x, id = blockIds[x.Hash.ToString()] }) .OrderBy(x => x.id); Logger.Debug($"blocks to process: {blocksToProcess.Count()}"); foreach (var entry in blocksToProcess.OrderBy(x => x.id)) { Logger.Debug($"process block {entry.id}"); ProcessBlock(entry.block, result); OracleReader.SetCurrentHeight("neo", "neo", _interopBlockHeight.ToString()); _interopBlockHeight = BigInteger.Parse(entry.id.ToString()); } } catch (Exception e) { Logger.Error("Inital start failed: " + e.ToString()); } } // return after the initial start to be able to process all swaps that happend in the mean time. return(result); } var blockIterator = new BlockIterator(neoAPI); var blockDifference = blockIterator.currentBlock - _interopBlockHeight; var batchCount = (blockDifference > 8) ? 8 : blockDifference; //TODO make it a constant, should be no more than 8 while (blockIterator.currentBlock > _interopBlockHeight) { if (_resyncBlockIds.Any()) { for (var i = 0; i < _resyncBlockIds.Count; i++) { var blockId = _resyncBlockIds.ElementAt(i); if (blockId > _interopBlockHeight) { Logger.Debug($"NeoInterop: Update() resync block {blockId} higher than current interop height, can't resync."); _resyncBlockIds.RemoveAt(i); continue; } try { Logger.Debug($"NeoInterop: Update() resync block {blockId} now."); var interopBlock = GetInteropBlock(blockId); ProcessBlock(interopBlock, result); } catch (Exception e) { Logger.Error($"NeoInterop: Update() resync block {blockId} failed: " + e); } _resyncBlockIds.RemoveAt(i); } } Logger.Debug($"Swaps: Current Neo chain height: {blockIterator.currentBlock}, interop: {_interopBlockHeight}, delta: {blockIterator.currentBlock - _interopBlockHeight}"); blockDifference = blockIterator.currentBlock - _interopBlockHeight; batchCount = (blockDifference > 8) ? 8 : blockDifference; if (batchCount > 1) { List <Task <InteropBlock> > taskList = CreateTaskList(batchCount); foreach (var task in taskList) { task.Start(); } Task.WaitAll(taskList.ToArray()); foreach (var task in taskList) { var block = task.Result; ProcessBlock(block, result); } OracleReader.SetCurrentHeight("neo", "neo", _interopBlockHeight.ToString()); _interopBlockHeight += batchCount; } else { var interopBlock = GetInteropBlock(_interopBlockHeight); ProcessBlock(interopBlock, result); OracleReader.SetCurrentHeight("neo", "neo", _interopBlockHeight.ToString()); _interopBlockHeight++; } } } catch (Exception e) { Logger.Error("Neo block sync failed: " + e); } return(result); } }
public override IEnumerable <PendingSwap> Update() { // wait another 10s to execute eth interop //Task.Delay(10000).Wait(); try { lock (String.Intern("PendingSetCurrentHeight_" + BSCWallet.BSCPlatform)) { var result = new List <PendingSwap>(); // initial start, we have to verify all processed swaps if (initialStart) { Logger.Debug($"Read all bsc blocks now."); var allInteropBlocks = OracleReader.ReadAllBlocks(BSCWallet.BSCPlatform, BSCWallet.BSCPlatform); Logger.Debug($"Found {allInteropBlocks.Count} blocks"); foreach (var block in allInteropBlocks) { ProcessBlock(block, ref result); } initialStart = false; // return after the initial start to be able to process all swaps that happend in the mean time. return(result); } var currentHeight = ethAPI.GetBlockHeight(); var _interopBlockHeight = BigInteger.Parse(OracleReader.GetCurrentHeight(BSCWallet.BSCPlatform, BSCWallet.BSCPlatform)); Logger.Debug($"Swaps: Current Eth chain height: {currentHeight}, interop: {_interopBlockHeight}, delta: {currentHeight - _interopBlockHeight}"); var blocksProcessedInOneBatch = 0; while (blocksProcessedInOneBatch < 50) { if (_resyncBlockIds.Any()) { for (var i = 0; i < _resyncBlockIds.Count; i++) { var blockId = _resyncBlockIds.ElementAt(i); if (blockId > _interopBlockHeight) { this.Logger.Warning($"EthInterop:Update() resync block {blockId} higher than current interop height, can't resync."); _resyncBlockIds.RemoveAt(i); continue; } try { this.Logger.Debug($"EthInterop:Update() resync block {blockId} now."); var block = GetInteropBlock(blockId); ProcessBlock(block, ref result); } catch (Exception e) { this.Logger.Error($"EthInterop:Update() resync block {blockId} failed: " + e); } _resyncBlockIds.RemoveAt(i); } } blocksProcessedInOneBatch++; var blockDifference = currentHeight - _interopBlockHeight; if (blockDifference < confirmations) { // no need to query the node yet break; } //TODO quick sync not done yet, requieres a change to the oracle impl to fetch multiple blocks //var nextHeight = (blockDifference > 50) ? 50 : blockDifference; //TODO //var transfers = new Dictionary<string, Dictionary<string, List<InteropTransfer>>>(); //if (nextHeight > 1) //{ // var blockCrawler = new EthBlockCrawler(logger, contracts.ToArray(), 0/*confirmations*/, ethAPI); //TODO settings confirmations // blockCrawler.Fetch(currentHeight, nextHeight); // transfers = blockCrawler.ExtractInteropTransfers(logger, LocalAddress); // foreach (var entry in transfers) // { // foreach (var txInteropTransfer in entry.Value) // { // foreach (var interopTransfer in txInteropTransfer.Value) // { // result.Add(new PendingSwap( // this.PlatformName // ,Hash.Parse(entry.Key) // ,interopTransfer.sourceAddress // ,interopTransfer.interopAddress) // ); // } // } // } // _interopBlockHeight = nextHeight; // oracleReader.SetCurrentHeight(BSCWallet.BSCPlatform, BSCWallet.BSCPlatform, _interopBlockHeight.ToString()); //} //else //{ /* Future improvement, implement oracle call to fetch multiple blocks */ var url = DomainExtensions.GetOracleBlockURL( BSCWallet.BSCPlatform, BSCWallet.BSCPlatform, PBigInteger.FromUnsignedArray(_interopBlockHeight.ToByteArray(), true)); var interopBlock = OracleReader.Read <InteropBlock>(DateTime.Now, url); ProcessBlock(interopBlock, ref result); _interopBlockHeight++; //} } OracleReader.SetCurrentHeight(BSCWallet.BSCPlatform, BSCWallet.BSCPlatform, _interopBlockHeight.ToString()); var total = result.Count(); if (total > 0) { Logger.Message($"startup: found {total} bsc swaps"); } else { Logger.Debug($"did not find any bsc swaps"); } return(result); } } catch (Exception e) { var logMessage = "BSCInterop.Update() exception caught:\n" + e.Message; var inner = e.InnerException; while (inner != null) { logMessage += "\n---> " + inner.Message + "\n\n" + inner.StackTrace; inner = inner.InnerException; } logMessage += "\n\n" + e.StackTrace; Logger.Error(logMessage); return(new List <PendingSwap>()); } }