Example #1
0
        // Returns the number of empty and full blocks, based on PoW field
        public List <int> getBlocksCount()
        {
            int empty_blocks = 0;
            int full_blocks  = 0;

            ulong lastBlockNum        = Node.blockChain.getLastBlockNum();
            ulong oldestRedactedBlock = 0;

            if (lastBlockNum > ConsensusConfig.getRedactedWindowSize())
            {
                oldestRedactedBlock = lastBlockNum - ConsensusConfig.getRedactedWindowSize();
            }

            for (ulong i = lastBlockNum; i > oldestRedactedBlock; i--)
            {
                Block block = Node.blockChain.getBlock(i, false, false);
                if (block == null)
                {
                    continue;
                }
                if (block.powField == null)
                {
                    empty_blocks++;
                }
                else
                {
                    full_blocks++;
                }
            }
            List <int> result = new List <int>();

            result.Add(empty_blocks);
            result.Add(full_blocks);
            return(result);
        }
Example #2
0
        // Reverts redaction for a single block
        private bool unredactChain()
        {
            lock (blocks)
            {
                int redacted_window_size = (int)ConsensusConfig.getRedactedWindowSize(getLastBlockVersion());
                if (blocks.Count() == redacted_window_size)
                {
                    Logging.warn("Won't unredact chain, block count is already correct.");
                    return(false);
                }

                while (blocks.Count() < redacted_window_size)
                {
                    if (lastBlockNum < (ulong)redacted_window_size)
                    {
                        return(false);
                    }

                    ulong block_num_to_unredact = lastBlockNum - (ulong)blocks.Count();

                    Block b = getBlock(block_num_to_unredact, true, true);

                    lock (blocksDictionary)
                    {
                        if (blocksDictionary.ContainsKey(block_num_to_unredact))
                        {
                            Logging.warn("Won't unredact chain, block #{0} is already in memory.", block_num_to_unredact);
                            return(false);
                        }
                    }

                    if (!TransactionPool.unredactTransactionsForBlock(b))
                    {
                        TransactionPool.redactTransactionsForBlock(b);
                        return(false);
                    }

                    blocks.Insert(0, b);
                    lock (blocksDictionary)
                    {
                        blocksDictionary.Add(block_num_to_unredact, b);
                    }

                    if (b.powField != null)
                    {
                        increaseSolvedBlocksCount();
                    }

                    Logging.info("UNREDACTED block #{0} to keep the chain length appropriate.", block_num_to_unredact);
                }
            }

            return(true);
        }
Example #3
0
        public static void processPendingTransactions()
        {
            // TODO TODO improve to include failed transactions
            ulong last_block_height = IxianHandler.getLastBlockHeight();

            lock (PendingTransactions.pendingTransactions)
            {
                long cur_time = Clock.getTimestamp();
                List <PendingTransaction> tmp_pending_transactions = new List <PendingTransaction>(PendingTransactions.pendingTransactions);
                int idx = 0;
                foreach (var entry in tmp_pending_transactions)
                {
                    Transaction t       = entry.transaction;
                    long        tx_time = entry.addedTimestamp;

                    if (t.applied != 0)
                    {
                        PendingTransactions.pendingTransactions.RemoveAll(x => x.transaction.id.SequenceEqual(t.id));
                        continue;
                    }

                    // if transaction expired, remove it from pending transactions
                    if (last_block_height > ConsensusConfig.getRedactedWindowSize() && t.blockHeight < last_block_height - ConsensusConfig.getRedactedWindowSize())
                    {
                        ActivityStorage.updateStatus(t.id, ActivityStatus.Error, 0);
                        PendingTransactions.pendingTransactions.RemoveAll(x => x.transaction.id.SequenceEqual(t.id));
                        continue;
                    }

                    if (cur_time - tx_time > 40) // if the transaction is pending for over 40 seconds, resend
                    {
                        CoreProtocolMessage.broadcastProtocolMessage(new char[] { 'M', 'H' }, ProtocolMessageCode.transactionData, t.getBytes(), null);
                        entry.addedTimestamp = cur_time;
                        entry.confirmedNodeList.Clear();
                    }

                    if (entry.confirmedNodeList.Count() >= 3) // if we get transaction from 3 nodes, we can consider it as confirmed
                    {
                        if (entry.messageId != null)
                        {
                            StreamProcessor.confirmMessage(entry.messageId);
                        }
                        continue;
                    }

                    if (cur_time - tx_time > 20) // if the transaction is pending for over 20 seconds, send inquiry
                    {
                        CoreProtocolMessage.broadcastGetTransaction(t.id, 0, null, false);
                    }

                    idx++;
                }
            }
        }
Example #4
0
        public static void addTransactionToActivityStorage(Transaction transaction)
        {
            Activity      activity    = null;
            int           type        = -1;
            IxiNumber     value       = transaction.amount;
            List <byte[]> wallet_list = null;

            byte[] wallet          = null;
            byte[] primary_address = (new Address(transaction.pubKey)).address;
            if (IxianHandler.getWalletStorage().isMyAddress(primary_address))
            {
                wallet = primary_address;
                type   = (int)ActivityType.TransactionSent;
                if (transaction.type == (int)Transaction.Type.PoWSolution)
                {
                    type  = (int)ActivityType.MiningReward;
                    value = ConsensusConfig.calculateMiningRewardForBlock(BitConverter.ToUInt64(transaction.data, 0));
                }
            }
            else
            {
                wallet_list = IxianHandler.getWalletStorage().extractMyAddressesFromAddressList(transaction.toList);
                if (wallet_list != null)
                {
                    type = (int)ActivityType.TransactionReceived;
                    if (transaction.type == (int)Transaction.Type.StakingReward)
                    {
                        type = (int)ActivityType.StakingReward;
                    }
                }
            }
            if (type != -1)
            {
                int status = (int)ActivityStatus.Pending;
                if (transaction.applied > 0)
                {
                    status = (int)ActivityStatus.Final;
                }
                if (wallet_list != null)
                {
                    foreach (var entry in wallet_list)
                    {
                        activity = new Activity(IxianHandler.getWalletStorage().getSeedHash(), Base58Check.Base58CheckEncoding.EncodePlain(entry), Base58Check.Base58CheckEncoding.EncodePlain(primary_address), transaction.toList, type, transaction.id, transaction.toList[entry].ToString(), transaction.timeStamp, status, transaction.applied, Transaction.txIdV8ToLegacy(transaction.id));
                        ActivityStorage.insertActivity(activity);
                    }
                }
                else if (wallet != null)
                {
                    activity = new Activity(IxianHandler.getWalletStorage().getSeedHash(), Base58Check.Base58CheckEncoding.EncodePlain(wallet), Base58Check.Base58CheckEncoding.EncodePlain(primary_address), transaction.toList, type, transaction.id, value.ToString(), transaction.timeStamp, status, transaction.applied, Transaction.txIdV8ToLegacy(transaction.id));
                    ActivityStorage.insertActivity(activity);
                }
            }
        }
Example #5
0
        public static void processPendingTransactions()
        {
            // TODO TODO improve to include failed transactions
            ulong last_block_height = IxianHandler.getLastBlockHeight();

            lock (PendingTransactions.pendingTransactions)
            {
                long cur_time = Clock.getTimestamp();
                List <PendingTransaction> tmp_pending_transactions = new List <PendingTransaction>(PendingTransactions.pendingTransactions);
                int idx = 0;
                foreach (var entry in tmp_pending_transactions)
                {
                    Transaction t       = entry.transaction;
                    long        tx_time = entry.addedTimestamp;

                    if (t.applied != 0)
                    {
                        PendingTransactions.pendingTransactions.RemoveAll(x => x.transaction.id.SequenceEqual(t.id));
                        continue;
                    }

                    // if transaction expired, remove it from pending transactions
                    if (last_block_height > ConsensusConfig.getRedactedWindowSize() && t.blockHeight < last_block_height - ConsensusConfig.getRedactedWindowSize())
                    {
                        Console.WriteLine("Error sending the transaction {0}", Transaction.txIdV8ToLegacy(t.id));
                        PendingTransactions.pendingTransactions.RemoveAll(x => x.transaction.id.SequenceEqual(t.id));
                        continue;
                    }

                    if (cur_time - tx_time > 40) // if the transaction is pending for over 40 seconds, resend
                    {
                        CoreProtocolMessage.broadcastProtocolMessage(new char[] { 'M', 'H' }, ProtocolMessageCode.transactionData, t.getBytes(), null);
                        entry.addedTimestamp = cur_time;
                        entry.confirmedNodeList.Clear();
                    }

                    if (entry.confirmedNodeList.Count() > 3) // already received 3+ feedback
                    {
                        continue;
                    }

                    if (cur_time - tx_time > 20) // if the transaction is pending for over 20 seconds, send inquiry
                    {
                        CoreProtocolMessage.broadcastGetTransaction(Transaction.txIdV8ToLegacy(t.id), 0);
                    }

                    idx++;
                }
            }
        }
Example #6
0
        private ulong getLowestBlockNum()
        {
            ulong lowestBlockNum = 1;

            if (Config.fullStorageDataVerification)
            {
                return(lowestBlockNum);
            }

            ulong syncToBlock = wsSyncConfirmedBlockNum;

            if (syncToBlock > ConsensusConfig.getRedactedWindowSize())
            {
                lowestBlockNum = syncToBlock - ConsensusConfig.getRedactedWindowSize();
            }
            return(lowestBlockNum);
        }
Example #7
0
        public static void processPendingTransactions()
        {
            // TODO TODO improve to include failed transactions
            ulong last_block_height = IxianHandler.getLastBlockHeight();

            lock (PendingTransactions.pendingTransactions)
            {
                long            cur_time = Clock.getTimestamp();
                List <object[]> tmp_pending_transactions = new List <object[]>(PendingTransactions.pendingTransactions);
                int             idx = 0;
                foreach (var entry in tmp_pending_transactions)
                {
                    Transaction t       = (Transaction)entry[0];
                    long        tx_time = (long)entry[1];
                    if ((int)entry[2] > 3) // already received 3+ feedback
                    {
                        continue;
                    }

                    if (t.applied != 0)
                    {
                        PendingTransactions.pendingTransactions.RemoveAll(x => ((Transaction)x[0]).id.SequenceEqual(t.id));
                        continue;
                    }

                    // if transaction expired, remove it from pending transactions
                    if (last_block_height > ConsensusConfig.getRedactedWindowSize() && t.blockHeight < last_block_height - ConsensusConfig.getRedactedWindowSize())
                    {
                        Console.WriteLine("Error processing the transaction {0}", Encoding.UTF8.GetBytes(t.id));
                        PendingTransactions.pendingTransactions.RemoveAll(x => ((Transaction)x[0]).id.SequenceEqual(t.id));
                        continue;
                    }

                    if (cur_time - tx_time > 40) // if the transaction is pending for over 40 seconds, resend
                    {
                        CoreProtocolMessage.broadcastProtocolMessage(new char[] { 'M', 'H' }, ProtocolMessageCode.newTransaction, t.getBytes(), null);
                        PendingTransactions.pendingTransactions[idx][1] = cur_time;
                    }
                    idx++;
                }
            }
        }
Example #8
0
        public void checkActiveBlockSolved()
        {
            if (currentBlockNum > 0)
            {
                if (currentBlockNum > ConsensusConfig.getRedactedWindowSize() &&
                    currentBlockNum + ConsensusConfig.getRedactedWindowSize() - 100 <= Node.blockChain.getLastBlockNum())
                {
                    blockFound = false;
                }
                else
                {
                    Block tmpBlock = Node.blockChain.getBlock(currentBlockNum, false, false);
                    if (tmpBlock == null || tmpBlock.powField != null)
                    {
                        blockFound = false;
                    }
                }
            }

            lock (activePoolBlockLock)
            {
                if (activePoolBlock != null)
                {
                    if (activePoolBlock.blockNum > ConsensusConfig.getRedactedWindowSize() &&
                        activePoolBlock.blockNum + ConsensusConfig.getRedactedWindowSize() - 100 <= Node.blockChain.getLastBlockNum())
                    {
                        activePoolBlock = null;
                    }
                    else
                    {
                        Block tmpBlock = Node.blockChain.getBlock(activePoolBlock.blockNum, false, false);
                        if (tmpBlock == null || tmpBlock.powField != null)
                        {
                            activePoolBlock = null;
                        }
                    }
                }
            }
        }
Example #9
0
        // Start the node
        public void start(bool verboseConsoleOutput)
        {
            char node_type = 'M'; // TODO TODO TODO TODO change this to 'W' or 'C' after the upgrade

            if (Config.disableMiner)
            {
                node_type = 'M';
            }

            // Check if we're in worker-only mode
            if (Config.workerOnly)
            {
                // Enable miner
                Config.disableMiner = false;
                node_type           = 'W';
                CoreConfig.simultaneousConnectedNeighbors = 4;
            }

            // Generate presence list
            PresenceList.init(IxianHandler.publicIP, Config.serverPort, node_type);

            // Initialize storage
            Storage.prepareStorage();

            ActivityStorage.prepareStorage();

            // Initialize the block chain
            blockChain = new BlockChain();

            //runDiffTests();
            //return;

            // Create the block processor and sync
            blockProcessor = new BlockProcessor();
            blockSync      = new BlockSync();


            if (Config.devInsertFromJson)
            {
                Console.WriteLine("Inserting from JSON");
                devInsertFromJson();
                Program.noStart = true;
                return;
            }

            if (Config.apiBinds.Count == 0)
            {
                Config.apiBinds.Add("http://localhost:" + Config.apiPort + "/");
            }

            // Start the HTTP JSON API server
            apiServer = new APIServer(Config.apiBinds, Config.apiUsers, Config.apiAllowedIps);

            if (IXICore.Platform.onMono() == false && !Config.disableWebStart)
            {
                System.Diagnostics.Process.Start(Config.apiBinds[0]);
            }

            miner = new Miner();

            // Start the network queue
            NetworkQueue.start();

            // prepare stats screen
            ConsoleHelpers.verboseConsoleOutput = verboseConsoleOutput;
            Logging.consoleOutput = verboseConsoleOutput;
            Logging.flush();
            if (ConsoleHelpers.verboseConsoleOutput == false)
            {
                statsConsoleScreen.clearScreen();
            }

            // Distribute genesis funds
            IxiNumber genesisFunds = new IxiNumber(Config.genesisFunds);

            // Check if this is a genesis node
            if (genesisFunds > (long)0)
            {
                Logging.info(String.Format("Genesis {0} specified. Starting operation.", genesisFunds));

                distributeGenesisFunds(genesisFunds);

                genesisNode = true;
                blockProcessor.resumeOperation();
                serverStarted = true;
                if (!isMasterNode())
                {
                    Logging.info("Network server is not enabled in modes other than master node.");
                }
                else
                {
                    NetworkServer.beginNetworkOperations();
                }
            }
            else
            {
                if (File.Exists(Config.genesisFile))
                {
                    Block genesis = new Block(Crypto.stringToHash(File.ReadAllText(Config.genesisFile)));
                    blockChain.setGenesisBlock(genesis);
                }
                ulong lastLocalBlockNum = Meta.Storage.getLastBlockNum();
                if (lastLocalBlockNum > 6)
                {
                    lastLocalBlockNum = lastLocalBlockNum - 6;
                }
                if (Config.lastGoodBlock > 0 && Config.lastGoodBlock < lastLocalBlockNum)
                {
                    lastLocalBlockNum = Config.lastGoodBlock;
                }
                if (lastLocalBlockNum > 0)
                {
                    Block b = blockChain.getBlock(lastLocalBlockNum, true);
                    if (b != null)
                    {
                        ConsensusConfig.minRedactedWindowSize = ConsensusConfig.getRedactedWindowSize(b.version);
                        ConsensusConfig.redactedWindowSize    = ConsensusConfig.getRedactedWindowSize(b.version);
                    }
                }

                if (Config.recoverFromFile)
                {
                    Block b = Meta.Storage.getBlock(lastLocalBlockNum);
                    blockSync.onHelloDataReceived(b.blockNum, b.blockChecksum, b.version, b.walletStateChecksum, b.getSignatureCount(), lastLocalBlockNum);
                }
                else
                {
                    ulong blockNum = WalletStateStorage.restoreWalletState(lastLocalBlockNum);
                    if (blockNum > 0)
                    {
                        Block b = blockChain.getBlock(blockNum, true);
                        if (b != null)
                        {
                            blockSync.onHelloDataReceived(blockNum, b.blockChecksum, b.version, b.walletStateChecksum, b.getSignatureCount(), lastLocalBlockNum);
                        }
                        else
                        {
                            walletState.clear();
                        }
                    }
                    else
                    {
                        blockSync.lastBlockToReadFromStorage = lastLocalBlockNum;
                    }

                    // Start the server for ping purposes
                    serverStarted = true;
                    if (!isMasterNode())
                    {
                        Logging.info("Network server is not enabled in modes other than master node.");
                    }
                    else
                    {
                        NetworkServer.beginNetworkOperations();
                    }

                    // Start the network client manager
                    NetworkClientManager.start();
                }
            }

            PresenceList.startKeepAlive();

            TLC = new ThreadLiveCheck();
            // Start the maintenance thread
            maintenanceThread      = new Thread(performMaintenance);
            maintenanceThread.Name = "Node_Maintenance_Thread";
            maintenanceThread.Start();
        }
Example #10
0
        public bool revertLastBlock(bool blacklist = true, bool legacy_dual_revert = true)
        {
            if (lastBlockNum == 1)
            {
                Logging.error("Cannot revert block #1.");
                return(false);
            }

            Block block_to_revert     = lastBlock;
            ulong block_num_to_revert = block_to_revert.blockNum;

            if (!Node.walletState.canRevertTransaction(block_num_to_revert))
            {
                Logging.error("Cannot revert block #" + block_num_to_revert + ", WSJ transaction is missing.");
                return(false);
            }

            if (reorgBlockStart == 0)
            {
                reorgBlockStart = block_num_to_revert;
            }

            // Re-org blockchain for max 7 blocks
            if (block_num_to_revert + 7 < reorgBlockStart)
            {
                Logging.error("Cannot revert block #" + block_num_to_revert + ", blockchain re-org started on " + reorgBlockStart);
                return(false);
            }

            Logging.info("Reverting block #" + block_num_to_revert);

            if (blacklist)
            {
                Node.blockProcessor.blacklistBlock(block_to_revert);
            }

            removeBlock(block_num_to_revert);

            lastBlock             = getBlock(block_num_to_revert - 1, true, true);
            lastBlockVersion      = lastBlock.version;
            lastBlockReceivedTime = lastBlock.timestamp;
            lastBlockNum          = lastBlock.blockNum;

            if (lastSuperBlockNum == block_num_to_revert)
            {
                Block super_block = block_to_revert;
                lastSuperBlockNum      = super_block.lastSuperBlockNum;
                lastSuperBlockChecksum = super_block.lastSuperBlockChecksum;
            }

            ConsensusConfig.redactedWindowSize    = ConsensusConfig.getRedactedWindowSize(lastBlockVersion);
            ConsensusConfig.minRedactedWindowSize = ConsensusConfig.getRedactedWindowSize(lastBlockVersion);

            // edge case for first block of block_version 3
            if (lastBlockVersion == 3 && getBlock(lastBlockNum - 1, true, true).version == 2)
            {
                Node.walletState.setCachedBlockVersion(2);
            }
            else
            {
                Node.walletState.setCachedBlockVersion(lastBlock.version);
            }

            unredactChain();

            Node.walletState.revertTransaction(block_num_to_revert);

            revertBlockTransactions(block_to_revert);

            Node.blockProcessor.resetSuperBlockCache();

            if (lastBlock.version >= BlockVer.v5 && lastBlock.lastSuperBlockChecksum == null)
            {
                if (lastBlock.version >= BlockVer.v8)
                {
                    if (!Node.walletState.calculateWalletStateDeltaChecksum(lastBlock.blockNum).SequenceEqual(lastBlock.walletStateChecksum))
                    {
                        Logging.error("Fatal error occured: Delta Wallet state is incorrect after reverting block #{0} - Block's WS Checksum: {1}, WS Checksum: {2}, Wallets: {3}", block_num_to_revert, Crypto.hashToString(lastBlock.walletStateChecksum), Crypto.hashToString(Node.walletState.calculateWalletStateDeltaChecksum(lastBlock.blockNum)), Node.walletState.numWallets);
                        Node.stop();
                        return(false);
                    }
                }
                else if (legacy_dual_revert)
                {
                    revertLastBlock(false, false);
                    return(true);
                }
            }
            else
            {
                if (!Node.walletState.calculateWalletStateChecksum().SequenceEqual(lastBlock.walletStateChecksum))
                {
                    Logging.error("Fatal error occured: Wallet state is incorrect after reverting block #{0} - Block's WS Checksum: {1}, WS Checksum: {2}, Wallets: {3}", block_num_to_revert, Crypto.hashToString(lastBlock.walletStateChecksum), Crypto.hashToString(Node.walletState.calculateWalletStateChecksum()), Node.walletState.numWallets);
                    Node.stop();
                    return(false);
                }
            }
            return(true);
        }
Example #11
0
        public bool appendBlock(Block b, bool add_to_storage = true)
        {
            lock (blocks)
            {
                if (blocks.Count > 0)
                {
                    Block prev_block = blocks[blocks.Count - 1];
                    // check for invalid block appending
                    if (b.blockNum != prev_block.blockNum + 1)
                    {
                        Logging.warn(String.Format("Attempting to add non-sequential block #{0} after block #{1}.",
                                                   b.blockNum,
                                                   prev_block.blockNum));
                        return(false);
                    }
                    if (!b.lastBlockChecksum.SequenceEqual(prev_block.blockChecksum))
                    {
                        Logging.error(String.Format("Attempting to add a block #{0} with invalid lastBlockChecksum!", b.blockNum));
                        return(false);
                    }
                    if (b.signatureFreezeChecksum != null && blocks.Count > 5 && !blocks[blocks.Count - 5].calculateSignatureChecksum().SequenceEqual(b.signatureFreezeChecksum))
                    {
                        Logging.error(String.Format("Attempting to add a block #{0} with invalid sigFreezeChecksum!", b.blockNum));
                        return(false);
                    }
                }
                lastBlock    = b;
                lastBlockNum = b.blockNum;
                if (b.version != lastBlockVersion)
                {
                    lastBlockVersion = b.version;
                }

                if (b.lastSuperBlockChecksum != null || b.blockNum == 1)
                {
                    pendingSuperBlocks.Remove(b.blockNum);

                    lastSuperBlockNum      = b.blockNum;
                    lastSuperBlockChecksum = b.blockChecksum;
                }

                // special case when we are starting up and have an empty chain
                if (blocks.Count == 0)
                {
                    blocks.Add(b);
                    lock (blocksDictionary)
                    {
                        blocksDictionary.Add(b.blockNum, b);
                    }
                    Node.storage.insertBlock(b);
                    return(true);
                }

                blocks.Add(b);
                lock (blocksDictionary)
                {
                    blocksDictionary.Add(b.blockNum, b);
                }

                if (reorgBlockStart <= b.blockNum)
                {
                    reorgBlockStart = 0;
                }
            }

            if (add_to_storage)
            {
                // Add block to storage
                Node.storage.insertBlock(b);
            }

            ConsensusConfig.redactedWindowSize    = ConsensusConfig.getRedactedWindowSize(b.version);
            ConsensusConfig.minRedactedWindowSize = ConsensusConfig.getRedactedWindowSize(b.version);

            redactChain();
            lock (blocks)
            {
                if (blocks.Count > 30)
                {
                    Block tmp_block = getBlock(b.blockNum - 30);
                    if (tmp_block != null)
                    {
                        TransactionPool.compactTransactionsForBlock(tmp_block);
                        tmp_block.compact();
                    }
                }
                compactBlockSigs(b);
            }

            // Cleanup transaction pool
            TransactionPool.performCleanup();

            lastBlockReceivedTime = Clock.getTimestamp();
            return(true);
        }
Example #12
0
        // Returns the most recent block without a PoW flag in the redacted blockchain
        private void searchForBlock()
        {
            lock (solvedBlocks)
            {
                List <ulong> tmpSolvedBlocks = new List <ulong>(solvedBlocks);
                foreach (ulong blockNum in tmpSolvedBlocks)
                {
                    Block b = Node.blockChain.getBlock(blockNum, false, false);
                    if (b == null || b.powField != null)
                    {
                        solvedBlocks.Remove(blockNum);
                    }
                }
            }

            Block candidate_block = null;

            List <Block> blockList = null;

            int block_offset = 1;

            if (Node.blockChain.Count > (long)ConsensusConfig.getRedactedWindowSize())
            {
                block_offset = 1000;
            }

            if (searchMode == BlockSearchMode.lowestDifficulty)
            {
                blockList = Node.blockChain.getBlocks(block_offset, (int)Node.blockChain.Count - block_offset).Where(x => x.powField == null).OrderBy(x => x.difficulty).ToList();
            }
            else if (searchMode == BlockSearchMode.randomLowestDifficulty)
            {
                Random rnd = new Random();
                blockList = Node.blockChain.getBlocks(block_offset, (int)Node.blockChain.Count - block_offset).Where(x => x.powField == null).OrderBy(x => x.difficulty).Skip(rnd.Next(500)).ToList();
            }
            else if (searchMode == BlockSearchMode.latestBlock)
            {
                blockList = Node.blockChain.getBlocks(block_offset, (int)Node.blockChain.Count - block_offset).Where(x => x.powField == null).OrderByDescending(x => x.blockNum).ToList();
            }
            else if (searchMode == BlockSearchMode.random)
            {
                Random rnd = new Random();
                blockList = Node.blockChain.getBlocks(block_offset, (int)Node.blockChain.Count - block_offset).Where(x => x.powField == null).OrderBy(x => rnd.Next()).ToList();
            }

            // Check if the block list exists
            if (blockList == null)
            {
                Logging.error("No block list found while searching. Likely an incorrect miner block search mode.");
                return;
            }

            // Go through each block in the list
            foreach (Block block in blockList)
            {
                if (block.powField == null)
                {
                    ulong solved = 0;
                    lock (solvedBlocks)
                    {
                        solved = solvedBlocks.Find(x => x == block.blockNum);
                    }

                    // Check if this block is in the solved list
                    if (solved > 0)
                    {
                        // Do nothing at this point
                    }
                    else
                    {
                        // Block is not solved, select it
                        candidate_block = block;
                        break;
                    }
                }
            }

            if (candidate_block == null)
            {
                // No blocks with empty PoW field found, wait a bit
                Thread.Sleep(1000);
                return;
            }

            currentBlockNum        = candidate_block.blockNum;
            currentBlockDifficulty = candidate_block.difficulty;
            currentBlockVersion    = candidate_block.version;
            currentHashCeil        = getHashCeilFromDifficulty(currentBlockDifficulty);

            activeBlock = candidate_block;
            byte[] block_checksum = activeBlock.blockChecksum;
            byte[] solver_address = Node.walletStorage.getPrimaryAddress();
            activeBlockChallenge = new byte[block_checksum.Length + solver_address.Length];
            System.Buffer.BlockCopy(block_checksum, 0, activeBlockChallenge, 0, block_checksum.Length);
            System.Buffer.BlockCopy(solver_address, 0, activeBlockChallenge, block_checksum.Length, solver_address.Length);

            blockFound = true;

            return;
        }
Example #13
0
        // Static function used by the getMiningBlock API call
        public static Block getMiningBlock(BlockSearchMode searchMode)
        {
            Block candidate_block = null;

            lock (activePoolBlockLock)
            {
                if (activePoolBlock != null)
                {
                    return(activePoolBlock);
                }
            }

            List <Block> blockList = null;

            int block_offset = 1;

            if (Node.blockChain.Count >= (long)ConsensusConfig.getRedactedWindowSize())
            {
                block_offset = 1000;
            }

            if (searchMode == BlockSearchMode.lowestDifficulty)
            {
                blockList = Node.blockChain.getBlocks(block_offset, (int)Node.blockChain.Count - block_offset).Where(x => x.powField == null).OrderBy(x => x.difficulty).ToList();
            }
            else if (searchMode == BlockSearchMode.randomLowestDifficulty)
            {
                Random rnd = new Random();
                blockList = Node.blockChain.getBlocks(block_offset, (int)Node.blockChain.Count - block_offset).Where(x => x.powField == null).OrderBy(x => x.difficulty).Skip(rnd.Next(200)).ToList();
            }
            else if (searchMode == BlockSearchMode.latestBlock)
            {
                blockList = Node.blockChain.getBlocks(block_offset, (int)Node.blockChain.Count - block_offset).Where(x => x.powField == null).OrderByDescending(x => x.blockNum).ToList();
            }
            else if (searchMode == BlockSearchMode.random)
            {
                Random rnd = new Random();
                blockList = Node.blockChain.getBlocks(block_offset, (int)Node.blockChain.Count - block_offset).Where(x => x.powField == null).OrderBy(x => rnd.Next()).ToList();
            }
            // Check if the block list exists
            if (blockList == null)
            {
                Logging.error("No block list found while searching.");
                return(null);
            }

            // Go through each block in the list
            foreach (Block block in blockList)
            {
                if (block.powField == null)
                {
                    ulong solved = 0;
                    lock (solvedBlocks)
                    {
                        solved = solvedBlocks.Find(x => x == block.blockNum);
                    }

                    // Check if this block is in the solved list
                    if (solved > 0)
                    {
                        // Do nothing at this point
                    }
                    else
                    {
                        // Block is not solved, select it
                        candidate_block = block;

                        if (searchMode == BlockSearchMode.random || searchMode == BlockSearchMode.randomLowestDifficulty)
                        {
                            lock (activePoolBlockLock)
                            {
                                activePoolBlock = candidate_block;
                            }
                        }
                        break;
                    }
                }
            }

            return(candidate_block);
        }