예제 #1
0
        public Block TryLoadBlock(ByteString id, byte[] data)
        {
            // Data should not exceed the maximum size.
            if (data.Length > MaximumBlockSize)
            {
                throw new ArgumentException(nameof(data));
            }

            // Integrity check.
            var computedId = BlockchainUtil.ComputeBlockId(data);

            if (!ByteString.CopyFrom(computedId).Equals(id))
            {
                throw new ArgumentException(nameof(id));
            }

            // Try to deserialize the data for format validity check.
            var block = BlockchainUtil.DeserializeBlock(data);

            lock (Blocks)
            {
                if (Blocks.ContainsKey(id))
                {
                    return(null);
                }
                Blocks.Add(id, data);
            }

            // Schedule the block for execution.
            Executor.ProcessBlock(block);

            return(block);
        }
예제 #2
0
파일: Storage.cs 프로젝트: smasuda/MinChain
        public IEnumerable <(ByteString, byte[])> LoadAll()
        {
            foreach (var file in Directory.GetFiles(storagePath))
            {
                var bytes = File.ReadAllBytes(file);
                var block = BlockchainUtil.DeserializeBlock(bytes);

                yield return(block.Id, bytes);
            }
        }
예제 #3
0
        //初期化
        bool LoadConfiguration(string[] args)
        {
            if (args.Length == 0)
            {
                Console.WriteLine("Should provide configuration file path.");
                return(false);
            }

            // config読み込み
            try
            {
                config = JsonConvert.DeserializeObject <Configuration>(
                    File.ReadAllText(Path.GetFullPath(args[0])));
            }
            catch (Exception exp)
            {
                logger.LogError(
                    "Failed to load configuration file. Run 'config' command.",
                    exp);
                return(false);
            }

            // config内の鍵情報を読み込み
            try
            {
                myKeys = KeyPair.LoadFrom(config.KeyPairPath);
            }
            catch (Exception exp)
            {
                logger.LogError(
                    $"Failed to load key from {config.KeyPairPath}.",
                    exp);
                return(false);
            }

            // genesis.binの読み込み
            try
            {
                var bytes = File.ReadAllBytes(config.GenesisPath);
                genesis = BlockchainUtil.DeserializeBlock(bytes);
            }
            catch (Exception exp)
            {
                logger.LogError(
                    $"Failed to load the genesis from {config.GenesisPath}.",
                    exp);
                return(false);
            }

            return(true);
        }
예제 #4
0
파일: Runner.cs 프로젝트: smasuda/MinChain
        bool LoadConfiguration(string[] args)
        {
            if (args.Length == 0)
            {
                Console.WriteLine("Should provide configuration file path.");
                return(false);
            }

            try
            {
                config = JsonConvert.DeserializeObject <Configuration>(
                    File.ReadAllText(Path.GetFullPath(args[0])));
            }
            catch (Exception exp)
            {
                logger.LogError(
                    "Failed to load configuration file. Run 'config' command.",
                    exp);
                return(false);
            }

            try
            {
                KeyPair seedKeyPair = KeyPair.LoadFrom(config.KeyPairPath);
                hwallet = new Wallet.HierachicalWallet(seedKeyPair);
                hwallet.init(10);
                hwallet.dumpAll();
                System.Threading.Thread.Sleep(3000);
            }
            catch (Exception exp)
            {
                logger.LogError(
                    $"Failed to load key from {config.KeyPairPath}.",
                    exp);
                return(false);
            }
            try
            {
                var bytes = File.ReadAllBytes(config.GenesisPath);
                genesis = BlockchainUtil.DeserializeBlock(bytes);
            }
            catch (Exception exp)
            {
                logger.LogError(
                    $"Failed to load the genesis from {config.GenesisPath}.",
                    exp);
                return(false);
            }

            return(true);
        }
예제 #5
0
        void CheckFloatingBlocks(ByteString waitingBlockId)
        {
            List <ByteString> pendingBlocks;

            if (floatingBlocks.TryGetValue(waitingBlockId, out pendingBlocks))
            {
                foreach (var floatBlockId in pendingBlocks)
                {
                    byte[] data = null;
                    try
                    {
                        lock (InventoryManager.Blocks)
                            data = InventoryManager.Blocks[floatBlockId];
                    }
                    catch { }

                    if (data.IsNull())
                    {
                        continue;
                    }
                    ProcessBlockLocked(BlockchainUtil.DeserializeBlock(data));
                }
            }
        }
예제 #6
0
        async Task HandleBody(InventoryMessage message, int peerId)
        {
            // Data should not exceed the maximum size.
            var data = message.Data;

            if (data.Length > MaximumBlockSize)
            {
                throw new ArgumentException();
            }

            // ハッシュ値正しい?
            var id = message.IsBlock ?
                     BlockchainUtil.ComputeBlockId(data) :
                     Hash.ComputeDoubleSHA256(data);

            if (!ByteString.CopyFrom(id).Equals(message.ObjectId))
            {
                return;
            }

            if (message.IsBlock)
            {
                // ミューテックス
                lock (Blocks)
                {
                    if (Blocks.ContainsKey(message.ObjectId))
                    {
                        return;
                    }
                    // ハッシュテーブルに追加
                    Blocks.Add(message.ObjectId, data);
                }

                var block = BlockchainUtil.DeserializeBlock(data);
                // 前のブロックも知らなかったら前のももらう
                var prevId = block.PreviousHash;
                if (!Blocks.ContainsKey(prevId))
                {
                    await ConnectionManager.SendAsync(new InventoryMessage
                    {
                        Type     = Request,
                        IsBlock  = true,
                        ObjectId = prevId,
                    }, peerId);
                }
                Executor.ProcessBlock(block);
            }
            else
            {
                if (MemoryPool.ContainsKey(message.ObjectId))
                {
                    return;
                }

                var tx = BlockchainUtil.DeserializeTransaction(data);

                // Ignore the coinbase transactions.
                if (tx.InEntries.Count == 0)
                {
                    return;
                }

                lock (MemoryPool)
                {
                    if (MemoryPool.ContainsKey(message.ObjectId))
                    {
                        return;
                    }
                    MemoryPool.Add(message.ObjectId, tx);
                }
            }

            message.Type = Advertise;
            message.Data = null;
            // 他の人に教えてあげる
            await ConnectionManager.BroadcastAsync(message, peerId);
        }
예제 #7
0
파일: Runner.cs 프로젝트: Jah524/MinChain
        bool LoadConfiguration(string[] args)
        {
            if (args.Length == 0)
            {
                Console.WriteLine("Should provide configuration file path.");
                return false;
            }

            try
            {
                config = JsonConvert.DeserializeObject<Configuration>(
                    File.ReadAllText(Path.GetFullPath(args[0])));
            }
            catch (Exception exp)
            {
                logger.LogError(
                    "Failed to load configuration file. Run 'config' command.",
                    exp);
                return false;
            }

            try
            {
                myKeys = KeyPair.LoadFrom(config.KeyPairPath);
            }
            catch (Exception exp)
            {
                logger.LogError(
                    $"Failed to load key from {config.KeyPairPath}.",
                    exp);
                return false;
            }

            try
            {
                var bytes = File.ReadAllBytes(config.GenesisPath);
                genesis = BlockchainUtil.DeserializeBlock(bytes);
            }
            catch (Exception exp)
            {
                logger.LogError(
                    $"Failed to load the genesis from {config.GenesisPath}.",
                    exp);
                return false;
            }

            try
            {
                if (!string.IsNullOrEmpty(config.StoragePath))
                    storage = new Storage(config.StoragePath);
            }
            catch (Exception exp)
            {
                logger.LogError(
                    $@"Failed to set up blockchain storage at {
                        config.StoragePath}.",
                    exp);
                return false;
            }

            return true;
        }
예제 #8
0
        void ProcessBlockLocked(byte[] data, ByteString prevId)
        {
            Block prev;

            if (!Blocks.TryGetValue(prevId, out prev))
            {
                // If the previous block is not under the block tree, mark the
                // block as floating.
                List <ByteString> blocks;
                if (!floatingBlocks.TryGetValue(prevId, out blocks))
                {
                    floatingBlocks[prevId] = blocks = new List <ByteString>();
                }
                blocks.Add(prevId);
                return;
            }

            // Mark the block as the connected block.
            var block = BlockchainUtil.DeserializeBlock(data);

            block.Height          = prev.Height + 1;
            block.TotalDifficulty = prev.TotalDifficulty + block.Difficulty;
            Blocks.Add(block.Id, block);

            // If the block difficulty does not surpass the current latest,
            // skip the execution.  Once the descendant block comes later,
            // evaluate the difficulty then again.
            if (Latest.TotalDifficulty >= block.TotalDifficulty)
            {
                CheckFloatingBlocks(block.Id);
                return;
            }

            // Otherwise, try to execute the block.  Considering the block folk,
            // first revert all the applied blocks prior to the fork point in
            // past blocks, if exists.  Then apply blocks after the fork.
            var fork = BlockchainUtil.LowestCommonAncestor(
                Latest, block, Blocks);
            var revertingChain = Latest.Ancestors(Blocks)
                                 .TakeWhile(x => !x.Id.Equals(fork.Id))
                                 .ToList();
            var applyingChain = block.Ancestors(Blocks)
                                .TakeWhile(x => !x.Id.Equals(fork.Id))
                                .Reverse()
                                .ToList();

            revertingChain.ForEach(Revert);

            int?failureIndex = null;

            for (var i = 0; i < applyingChain.Count; i++)
            {
                var applyBlock = applyingChain[i];
                try { Run(applyBlock); }
                catch
                {
                    // The block was invalid.  Revert.
                    PurgeBlock(applyBlock.Id);

                    failureIndex = i;
                    break;
                }

                Apply(applyBlock);
            }

            if (failureIndex.HasValue)
            {
                // Failure occurred during the block execution.  Perform
                // opposite to revert to the state before the execution.
                applyingChain.Take(failureIndex.Value)
                .Reverse().ToList().ForEach(Revert);

                revertingChain.Reverse();
                revertingChain.ForEach(Apply);
                return;
            }

            CheckFloatingBlocks(block.Id);
        }