internal static void Receive(TcpReceiveState e, PoolCommand cmd)
        {
            var msg   = new NonceDataMsg();
            int index = 0;

            msg.Deserialize(cmd.Payload, ref index);

            var miner = PoolCache.WorkingMiners.FirstOrDefault(m => m.ClientAddress == e.Address);

            if (miner == null)
            {
                RejectCommand.Send(e);
                return;
            }

            var data = POC.CalculateScoopData(miner.WalletAddress, msg.MaxNonce, miner.CheckScoopNumber);

            if (Base16.Encode(data) == Base16.Encode(msg.ScoopData))
            {
                miner.IsConnected         = true;
                miner.ConnectedTime       = Time.EpochTime;
                miner.LatestHeartbeatTime = Time.EpochTime;
                LoginCommand.SendLoginResult(e, true);
                LogHelper.Info(miner.ClientAddress + " login success");

                StartCommand.Send(e);
            }
            else
            {
                LoginCommand.SendLoginResult(e, false);
                RejectCommand.Send(e);
                LogHelper.Info(miner.ClientAddress + " login fail");
            }
        }
        public IRpcMethodResult GetDifficulty()
        {
            try
            {
                var blockComponent = new BlockComponent();
                var height         = blockComponent.GetLatestHeight();
                var newHeight      = height + 1;

                var previousBlockMsg = blockComponent.GetBlockMsgByHeight(height);
                var prevStepBlockMsg = blockComponent.GetBlockMsgByHeight(newHeight - POC.DIFFIUCLTY_ADJUST_STEP - 1);
                var bits             = POC.CalculateBaseTarget(height, previousBlockMsg, prevStepBlockMsg).ToString();

                var result = new GetDifficultyOM()
                {
                    height     = newHeight,
                    hashTarget = bits
                };
                return(Ok(result));
            }
            catch (CommonException ce)
            {
                return(Error(ce.ErrorCode, ce.Message, ce));
            }
            catch (Exception ex)
            {
                return(Error(ErrorCode.UNKNOWN_ERROR, ex.Message, ex));
            }
        }
        public IRpcMethodResult GetBaseTarget(long blockHeight)
        {
            try
            {
                var      blockComponent = new BlockComponent();
                BlockMsg lastBlock      = null;
                BlockMsg prevStepBlock  = null;

                if (blockHeight > 0)
                {
                    lastBlock     = blockComponent.GetBlockMsgByHeight(blockHeight - 1);
                    prevStepBlock = blockComponent.GetBlockMsgByHeight(blockHeight - POC.DIFFIUCLTY_ADJUST_STEP);
                }
                long baseTarget;
                if (lastBlock != null)
                {
                    baseTarget = POC.CalculateBaseTarget(blockHeight, lastBlock, prevStepBlock);
                }
                else
                {
                    baseTarget = POC.CalculateBaseTarget(0, null, null);
                }
                return(Ok(baseTarget));
            }
            catch (CommonException ce)
            {
                return(Error(ce.ErrorCode, ce.Message, ce));
            }
            catch (Exception ex)
            {
                return(Error(ErrorCode.UNKNOWN_ERROR, ex.Message, ex));
            }
        }
Exemple #4
0
 public IRpcMethodResult GetNewBlockReward()
 {
     try
     {
         var block = BlockDac.Default.SelectLast();
         if (block == null)
         {
             var reward = POC.GetNewBlockReward(0);
             return(Ok(reward));
         }
         else
         {
             var reward = POC.GetNewBlockReward(block.Header.Height);
             return(Ok(reward));
         }
     }
     catch (CommonException ce)
     {
         return(Error(ce.ErrorCode, ce.Message, ce));
     }
     catch (Exception ex)
     {
         return(Error(ErrorCode.UNKNOWN_ERROR, ex.Message, ex));
     }
 }
Exemple #5
0
        public async Task <bool> Update(POC poc)
        {
            ReplaceOneResult updated = await context1.POCs.ReplaceOneAsync(filter
                                                                           : g => g.Id == poc.Id,
                                                                           replacement : poc);

            return(updated.IsAcknowledged && updated.ModifiedCount > 0);
        }
Exemple #6
0
        public bool ForgeBlock(BlockMsg blockMsg)
        {
            LogHelper.Info("Forge Block 8");
            var hashResult = BlockHelper.GetMiningWorkResult(blockMsg);

            LogHelper.Info("Height:" + blockMsg.Header.Height);
            LogHelper.Info("Bits:" + POC.ConvertBitsToBigInt(blockMsg.Header.Bits).ToString("X").PadLeft(64, '0'));
            LogHelper.Info("Hash:" + Base16.Encode(hashResult));
            LogHelper.Debug("Nonce:" + blockMsg.Header.Nonce);
            LogHelper.Debug("Address:" + blockMsg.Header.GeneratorId);
            if (!POC.Verify(blockMsg.Header.Bits, hashResult))
            {
                LogHelper.Info("POC Verify Failed");
                return(false);
            }

            LogHelper.Info("Forge Block 9");
            var result = false;

            try
            {
                if (this.SubmitBlock(blockMsg))
                {
                    result = true;
                }
                LogHelper.Info($"Forge Block 10, {result}");
            }
            catch (Exception ex)
            {
                LogHelper.Error(ex.ToString());
            }
            finally
            {
                if (!result)
                {
                    Thread.Sleep(60 * 1000);
                    var nodeHeight = GetBlockHeight();

                    LogHelper.Info($"DB nodeHeight:{nodeHeight}, currentHeight:{blockMsg.Header.Height}");
                    if (nodeHeight >= blockMsg.Header.Height)
                    {
                        result = true;
                    }
                    else
                    {
                        result = false;
                    }
                }
            }

            return(result);
        }
Exemple #7
0
        public bool VerifyBlock(BlockMsg newBlock)
        {
            //校验区块的基本信息
            var result = VerifyBlockBasic(newBlock);

            if (!result)
            {
                return(false);
            }

            var txComponent    = new TransactionComponent();
            var blockComponent = new BlockComponent();

            //校验交易信息
            var totalFee = 0L;
            VerifyTransactionModel model = new VerifyTransactionModel();

            model.block       = newBlock;
            model.localHeight = blockComponent.GetLatestHeight();
            foreach (var item in newBlock.Transactions)
            {
                long fee;
                model.transaction = item;

                if (txComponent.VerifyTransactionMsg(model, out fee))
                {
                    totalFee += fee;
                }
                else
                {
                    return(false);
                }
            }

            if (Heights.Contains(newBlock.Header.Height))
            {
                return(true);
            }

            var newBlockReward = POC.GetNewBlockReward(newBlock.Header.Height);
            var coinbaseAmount = newBlock.Transactions[0].Outputs[0].Amount;

            if (coinbaseAmount < 0 || coinbaseAmount != (totalFee + newBlockReward))
            {
                throw new CommonException(ErrorCode.Engine.Transaction.Verify.COINBASE_OUTPUT_AMOUNT_ERROR);
            }
            return(true);
        }
Exemple #8
0
        //public List<MiningMsg> UpdateMiningPoolsBackup(List<MiningMsg> miningMsgs)
        //{
        //    List<MiningMsg> newMsgs = new List<MiningMsg>();
        //    if (miningMsgs == null || miningMsgs.Count == 0)
        //        return newMsgs;

        //    var items = miningMsgs.Where(x => HasMiningPool(x.Name, x.PublicKey));

        //    if (!items.Any())
        //        return newMsgs;

        //    MiningPoolDac.Default.Put(items);
        //    newMsgs.AddRange(miningMsgs);
        //    CurrentMiningPools = this.GetAllMiningPoolsInDb();
        //    return newMsgs;
        //}

        public bool AddMiningToPool(MiningMsg msg)
        {
            if (HasMiningPool(msg.Name, msg.PublicKey))
            {
                return(false);
            }

            if (!POC.VerifyMiningPoolSignature(msg.PublicKey, msg.Signature))
            {
                return(false);
            }

            MiningPoolDac.Default.Put(msg);
            CurrentMiningPools = GetAllMiningPoolsInDb();
            return(true);
        }
Exemple #9
0
        public static byte[] GetMiningWorkResult(BlockMsg block)
        {
            var listBytes = new List <Byte>();

            listBytes.AddRange(Base16.Decode(block.Header.PayloadHash));
            listBytes.AddRange(BitConverter.GetBytes(block.Header.Height));
            var         genHash         = Sha3Helper.Hash(listBytes.ToArray());
            var         scoopNumber     = POC.GetScoopNumber(block.Header.PayloadHash, block.Header.Height);
            var         scoopData       = POC.CalculateScoopData(block.Header.GeneratorId, block.Header.Nonce, scoopNumber);
            List <byte> targetByteLists = new List <byte>();

            targetByteLists.AddRange(scoopData);
            targetByteLists.AddRange(genHash);
            var baseTarget = Sha3Helper.Hash(targetByteLists.ToArray());

            return(baseTarget);
        }
        public IRpcMethodResult GetBaseTarget(long blockHeight)
        {
            try
            {
                var      blockComponent = new BlockComponent();
                BlockMsg lastBlock      = null;
                BlockMsg prevStepBlock  = null;

                if (blockHeight > 0)
                {
                    lastBlock = blockComponent.GetBlockMsgByHeight(blockHeight - 1);
                    if (blockHeight >= POC.DIFFIUCLTY_ADJUST_STEP)
                    {
                        long prevStepHeight = 0;
                        if (!GlobalParameters.IsTestnet && blockHeight <= POC.DIFFICULTY_CALCULATE_LOGIC_ADJUST_HEIGHT)
                        {
                            prevStepHeight = blockHeight - POC.DIFFIUCLTY_ADJUST_STEP - 1;
                        }
                        else
                        {
                            prevStepHeight = blockHeight - POC.DIFFIUCLTY_ADJUST_STEP;
                        }
                        prevStepBlock = blockComponent.GetBlockMsgByHeight(prevStepHeight);
                    }
                }
                long baseTarget;
                if (lastBlock != null)
                {
                    baseTarget = POC.CalculateBaseTarget(blockHeight, lastBlock, prevStepBlock);
                }

                else
                {
                    baseTarget = POC.CalculateBaseTarget(0, null, null);
                }
                return(Ok(baseTarget));
            }
            catch (CommonException ce)
            {
                return(Error(ce.ErrorCode, ce.Message, ce));
            }
            catch (Exception ex)
            {
                return(Error(ErrorCode.UNKNOWN_ERROR, ex.Message, ex));
            }
        }
Exemple #11
0
        public List <Block> GetBlockEntityByHash(IEnumerable <string> hashes)
        {
            var          blockMsgs = BlockDac.Default.SelectByHashes(hashes);
            List <Block> result    = new List <Block>();

            foreach (var msg in blockMsgs)
            {
                var entity = new Block
                {
                    Hash              = msg.Header.Hash,
                    Version           = msg.Header.Version,
                    Height            = msg.Header.Height,
                    PreviousBlockHash = msg.Header.PreviousBlockHash,
                    Bits              = msg.Header.Bits,
                    Nonce             = msg.Header.Nonce,
                    Timestamp         = msg.Header.Timestamp,
                    TotalAmount       = msg.Transactions.SelectMany(x => x.Outputs).Sum(x => x.Amount),
                    GeneratorId       = msg.Header.GeneratorId,
                    BlockSignature    = msg.Header.BlockSignature,
                    IsDiscarded       = false,
                    IsVerified        = GlobalParameters.LocalHeight - msg.Header.Height >= 6
                };

                var totalfee = msg.Transactions[0].Outputs[0].Amount - POC.GetNewBlockReward(msg.Header.Height);
                if (totalfee > 0)
                {
                    entity.TotalFee = totalfee;
                }

                var nextBlockMsg = blockMsgs.FirstOrDefault(x => x.Header.Height == entity.Height + 1);
                if (nextBlockMsg == null)
                {
                    nextBlockMsg = BlockDac.Default.SelectByHeight(msg.Header.Height + 1);
                }

                if (entity != null)
                {
                    entity.NextBlockHash = nextBlockMsg.Header.Hash;
                }

                result.Add(entity);
            }
            return(result);
        }
        public IRpcMethodResult GetDifficulty()
        {
            try
            {
                var blockComponent = new BlockComponent();
                var height         = blockComponent.GetLatestHeight();
                var newHeight      = height + 1;

                var      previousBlockEntity = blockComponent.GetBlockMsgByHeight(height);
                BlockMsg prevStepBlock       = null;
                if (newHeight >= POC.DIFFIUCLTY_ADJUST_STEP)
                {
                    var prevStepHeight = 0L;
                    if (!GlobalParameters.IsTestnet && newHeight <= POC.DIFFICULTY_CALCULATE_LOGIC_ADJUST_HEIGHT)
                    {
                        prevStepHeight = newHeight - POC.DIFFIUCLTY_ADJUST_STEP - 1;
                    }
                    else
                    {
                        prevStepHeight = newHeight - POC.DIFFIUCLTY_ADJUST_STEP;
                    }
                    prevStepBlock = blockComponent.GetBlockMsgByHeight(prevStepHeight);
                }

                var bits = POC.CalculateBaseTarget(height, previousBlockEntity, prevStepBlock).ToString();

                var result = new GetDifficultyOM()
                {
                    height     = newHeight,
                    hashTarget = bits
                };
                return(Ok(result));
            }
            catch (CommonException ce)
            {
                return(Error(ce.ErrorCode, ce.Message, ce));
            }
            catch (Exception ex)
            {
                return(Error(ErrorCode.UNKNOWN_ERROR, ex.Message, ex));
            }
        }
Exemple #13
0
        public BlockDetail GetBlockDetail(string hash)
        {
            var block = BlockDac.Default.SelectByHash(hash);

            if (block == null)
            {
                return(null);
            }

            BlockDetail detail = new BlockDetail();

            detail.TradeCount  = block.Header.TotalTransaction;
            detail.TotalOutput = block.Transactions.SelectMany(x => x.Outputs).Where(x => x.Amount > 0).Sum(x => x.Amount);
            var reward = POC.GetNewBlockReward(block.Header.Height);

            detail.Height            = block.Header.Height;
            detail.Timestamp         = block.Header.Timestamp;
            detail.Difficulty        = POC.CalculateDifficulty(block.Header.Bits);
            detail.Bits              = block.Header.Bits;
            detail.Version           = block.Header.Version;
            detail.Nonce             = block.Header.Nonce;
            detail.BlockReward       = reward;
            detail.Hash              = block.Header.Hash;
            detail.PreviousBlockHash = block.Header.PreviousBlockHash;
            var nextHash = BlockDac.Default.GetBlockHashByHeight(detail.Height + 1);

            detail.NextBlockHash = nextHash;


            detail.TranList = new List <TransOM>();

            block.Transactions.ForEach(x => {
                detail.TranList.Add(x.ConvertToDetail());
            });

            var tx       = detail.TranList.Skip(0);
            var totalFee = tx.SelectMany(x => x.OutputList).Sum(x => x.Amount) - tx.SelectMany(x => x.InputList).Sum(x => x.Amount);

            detail.TransactionFees = totalFee;
            return(detail);
        }
Exemple #14
0
        public static void SaveBlockRates()
        {
            long difficulty = 0;

            if (PoolCenterJob.Current.CurrentStartMiningMsg != null)
            {
                var block = RedisManager.Current.GetDataInRedis <BlockMsg>(PoolCenterJob.Current.CurrentStartMiningMsg.Id);
                difficulty = Convert.ToInt64(POC.CalculateDifficulty(block.Header.Bits));
            }
            else
            {
                var height = NodeApi.Current.GetBlockHeight();
                var block  = NodeApi.Current.GetBlockByHeight(height);
                difficulty = Convert.ToInt64(POC.CalculateDifficulty(block.Header.Bits));
            }

            BlockRatesComponent component = new BlockRatesComponent();

            component.SaveBlockRates(CenterCache.GenarateBlockCount, difficulty);
            CenterCache.GenarateBlockCount = 0;
        }
Exemple #15
0
        public bool AddMiningToPool(MiningMsg msg)
        {
            if (!POC.VerifyMiningPoolSignature(msg.PublicKey, msg.Signature))
            {
                return(false);
            }

            var result = false;
            var item   = currentMiningPools.FirstOrDefault(x => x.PublicKey == msg.PublicKey && x.Signature == msg.Signature);

            if (item == null)
            {
                MiningPoolDac miningPoolDac = new MiningPoolDac();
                MiningPool    miningPool    = ConvertToMiningPool(msg);
                result = miningPoolDac.SaveToDB(miningPool) > 0;
            }
            else if (item.Name != msg.Name)
            {
                MiningPoolDac miningPoolDac = new MiningPoolDac();
                MiningPool    miningPool    = new MiningPool()
                {
                    Name = msg.Name, PublicKey = msg.PublicKey, Signature = msg.Signature
                };
                miningPoolDac.UpdateMiningPool(miningPool);
                result = true;
            }
            if (result && OnNewMiningPoolHandle != null)
            {
                NewMiningPoolMsg newMsg = new NewMiningPoolMsg();
                newMsg.MinerInfo = new MiningMsg()
                {
                    Name = msg.Name, PublicKey = msg.PublicKey, Signature = msg.Signature
                };
                OnNewMiningPoolHandle(newMsg);
            }

            return(false);
        }
Exemple #16
0
        private void StartMining()
        {
            var block = NodeApi.Current.GenerateMiningBlock(_startArgs.Name, _startArgs.Account);
            var currentScoopNumber = POC.GetScoopNumber(block.Header.PayloadHash, block.Header.Height);

            _startTime             = Time.EpochTime;
            block.Header.Timestamp = _startTime;

            if (block.Header.Height != this.currentBlockHeight || this.currentBlockStartTime <= 0)
            {
                this.currentBlockStartTime = _startTime;
                this.currentBlockHeight    = block.Header.Height;
            }

            StartMiningMsg startMiningMsg = StartMiningMsg.CreateNew();

            startMiningMsg.BlockHeight = block.Header.Height;
            startMiningMsg.ScoopNumber = currentScoopNumber;
            startMiningMsg.StartTime   = _startTime;
            var genHash = BlockHelper.GenHash(block.Header.PayloadHash, block.Header.Height);

            startMiningMsg.GenHash    = Base16.Encode(genHash);
            startMiningMsg.BaseTarget = NodeApi.Current.GetBaseTarget(block.Header.Height);

            var blockKey = KeyHelper.GetBlockKey(startMiningMsg.Id);

            RedisManager.Current.SaveDataToRedis(blockKey, block);
            //MQApi.SendStartMsg(startMiningMsg);
            RabbitMQApi.SendStartMsg(startMiningMsg);

            CurrentStartMiningMsg = startMiningMsg;
            LogHelper.Info("Start MiningTask Id=" + startMiningMsg.Id + " ScoopNumber = " + startMiningMsg.ScoopNumber + " Height= " + startMiningMsg.BlockHeight);
            LogHelper.Info($"Block bits is {POC.ConvertBitsToBigInt(block.Header.Bits).ToString("X").PadLeft(64, '0')}");
            LogHelper.Info($"StartMiningMsg.BaseTarget is {POC.ConvertBitsToBigInt(startMiningMsg.BaseTarget).ToString("X").PadLeft(64, '0')}");
            LogHelper.Info($"Block height is {block.Header.Height}");
        }
Exemple #17
0
        /// <summary>
        /// Called on each bar update event (incoming tick)
        /// </summary>
        protected override void OnBarUpdate()
        {
            int    i;
            double AvgPrice          = 0.0;
            double Variance          = 0.0;
            double StandardDeviation = 0.0;

            if (CurrentBar < 10)
            {
                return;
            }

            if (InitializeEndTime)
            {
                if (Time[0].CompareTo(StartTime) >= 0)
                {
                    InitializeEndTime = false;
                    StartTime         = new DateTime(Time[0].Year, Time[0].Month, Time[0].Day, OpenHour, OpenMinute, 0, 0, DateTimeKind.Utc);
                    if (sessionLengthInHours >= 24.0)
                    {
                        EndTime = StartTime.AddHours(24.0 - 1.0 / 60.0);
                    }
                    else
                    {
                        EndTime = StartTime.AddHours(sessionLengthInHours);
                    }
                }
            }

            if (!InitializeEndTime && Time[1].CompareTo(EndTime) <= 0 && Time[0].CompareTo(EndTime) > 0)
            {
                DetermineHighLowOfSession(StartTime);
                if (LastBarOfSession < 0)
                {
                    return;
                }

                StartTime = new DateTime(Time[0].Year, Time[0].Month, Time[0].Day, OpenHour, OpenMinute, 0, 0, DateTimeKind.Utc);
                if (sessionLengthInHours >= 24)
                {
                    EndTime = StartTime.AddHours(24.0 - 1.0 / 60.0);
                }
                else
                {
                    EndTime = StartTime.AddHours(sessionLengthInHours);
                }


                int TicksInRange = (int)Math.Round((TheSessionHigh - TheSessionLow) / TickSize, 0);
                if (TicksInRange >= 1000)
                {
                    Log("Potential data problem in CalculateValueArea at " + Time[0].ToString() + " Session H/L: " + TheSessionHigh.ToString(FormatString) + " / " + TheSessionLow.ToString(FormatString), LogLevel.Warning);
                }
                if (TicksInRange < 0)
                {
                    Log("Potential data problem in CalculateValueArea at " + Time[0].ToString() + " Session H/L: " + TheSessionHigh.ToString(FormatString) + " / " + TheSessionLow.ToString(FormatString), LogLevel.Warning);
                }
                for (i = 0; i < 1000; i++)
                {
                    PriceHitsArray[0, i] = (i * TickSize + TheSessionLow);
                    PriceHitsArray[1, i] = 0.0;
                }

                int index = 0;
                i = 1;
                while (i <= LastBarOfSession)                 //Accumulate the volume for each previous days bar into PriceVolume array
                {
                    if (!inclWeekendVol && (Time[i].DayOfWeek == DayOfWeek.Saturday || Time[i].DayOfWeek == DayOfWeek.Sunday))
                    {
                        i++;
                    }
                    else
                    {
                        if (profileType == "VOC")                        //Volume On Close - puts all the volume for that bar on the close price
                        {
                            index = (int)Math.Round((Close[i] - TheSessionLow) / TickSize, 0);
                            PriceHitsArray[1, index] = PriceHitsArray[1, index] + Volume[i];
                        }
                        if (profileType == "TPO")                         //Time Price Opportunity - disregards volume, only counts number of times prices are touched
                        {
                            double BarH = High[i]; double BarP = Low[i];
                            while (BarP <= BarH + TickSize / 2.0)
                            {
                                index = (int)Math.Round((BarP - TheSessionLow) / TickSize, 0);
                                PriceHitsArray[1, index] = PriceHitsArray[1, index] + 1;
                                BarP = BarP + TickSize;
                            }
                        }
                        if (profileType == "VWTPO")                         //Volume Weighted Time Price Opportunity - Disperses the Volume of the bar over the range of the bar so each price touched is weighted with volume
                        {
                            double BarH = High[i]; double BarP = Low[i];
                            int    TicksInBar = (int)Math.Round((BarH - Low[i]) / TickSize + 1, 0);
                            while (BarP <= BarH + TickSize / 2.0)
                            {
                                index = (int)Math.Round((BarP - TheSessionLow) / TickSize, 0);
                                PriceHitsArray[1, index] = PriceHitsArray[1, index] + Volume[i] / TicksInBar;
                                BarP = BarP + TickSize;
                            }
                        }
                        i++;
                    }
                }

                //Calculate the Average price as weighted by the hit counts AND find the price with the highest hits (POC price)
                i = 0;
                double THxP = 0.0;               //Total of Hits multiplied by Price at that volume
                HitsTotal  = 0.0;
                PriceOfPOC = 0.0;
                double MaxHits = 0.0;
                while (i <= TicksInRange)              //Sum up Volume*Price in THxP...and sum up Volume in VolumeTotal
                {
                    if (PriceHitsArray[1, i] > 0.0)
                    {
                        THxP      = THxP + PriceHitsArray[1, i] * PriceHitsArray[0, i];
                        HitsTotal = HitsTotal + PriceHitsArray[1, i];
                        if (PriceHitsArray[1, i] > MaxHits)                       //used to determine POC level
                        {
                            MaxHits    = PriceHitsArray[1, i];
                            PriceOfPOC = PriceHitsArray[0, i];
                        }
                    }
                    i++;
                }
                AvgPrice = THxP / HitsTotal;

                VAtop = AvgPrice;
                VAbot = AvgPrice;

                double ViA = 0.0;               //This loop calculates the percentage of hits contained within the Value Area
                double TV  = 0.00001;
                double Adj = 0.0;
                while (ViA / TV < pctOfVolumeInVA)
                {
                    VAbot = VAbot - Adj;
                    VAtop = VAtop + Adj;
                    ViA   = 0.0;
                    TV    = 0.00001;
                    for (i = 0; i < 1000; i++)
                    {
                        if (PriceHitsArray[0, i] > VAbot - Adj && PriceHitsArray[0, i] < VAtop + Adj)
                        {
                            ViA = PriceHitsArray[1, i] + ViA;
                        }
                        TV = TV + PriceHitsArray[1, i];
                    }
                    Adj = TickSize;
                }
//DrawText("PctInValueArea",(ViA/TV).ToString("0.00"),50,TheSessionHigh,Color.Red);
            }

            if (VAtop > 0.0)
            {
                VAt.Set(VAtop);
                VAb.Set(VAbot);
                POC.Set(PriceOfPOC);
            }
            StartTime = new DateTime(Time[0].Year, Time[0].Month, Time[0].Day, OpenHour, OpenMinute, 0, 0, DateTimeKind.Utc);
            if (sessionLengthInHours >= 24.0)
            {
                EndTime = StartTime.AddHours(24.0 - 1.0 / 60.0);
            }
            else
            {
                EndTime = StartTime.AddHours(sessionLengthInHours);
            }
        }
Exemple #18
0
        public bool VerifyBlockBasic(BlockMsg newBlock)
        {
            if (newBlock.Header.Hash != newBlock.Header.GetHash())
            {
                throw new CommonException(ErrorCode.Engine.Block.Verify.BLOCK_HASH_ERROR);
            }

            bool hasPreviousBlock       = false;
            long previousBlockTimestamp = -1;
            long previousBlockBits      = -1;
            long previousBlockHeight    = newBlock.Header.Height - 1;

            var cacheBlockKey = $"{newBlock.Header.Hash}_{newBlock.Header.Height - 1}";

            var previousBlockMsg = BlockDac.Default.SelectByHash(newBlock.Header.PreviousBlockHash);

            if (previousBlockMsg != null)
            {
                hasPreviousBlock       = true;
                previousBlockTimestamp = previousBlockMsg.Header.Timestamp;
                previousBlockBits      = previousBlockMsg.Header.Bits;
            }
            else
            {
                var previousBlock = BlockDac.Default.SelectByHash(newBlock.Header.PreviousBlockHash);
                hasPreviousBlock = previousBlock != null;
                if (hasPreviousBlock)
                {
                    previousBlockTimestamp = previousBlock.Header.Timestamp;
                    previousBlockBits      = previousBlock.Header.Bits;
                }
            }

            if (newBlock.Header.Height > 0 && !hasPreviousBlock)
            {
                throw new CommonException(ErrorCode.Engine.Block.Verify.PREV_BLOCK_NOT_EXISTED);
            }

            if ((newBlock.Header.Timestamp - Time.EpochTime) > 2 * 60 * 60 * 1000 ||
                (hasPreviousBlock && newBlock.Header.Timestamp <= previousBlockTimestamp))
            {
                throw new CommonException(ErrorCode.Engine.Block.Verify.BLOCK_TIME_IS_ERROR);
            }

            if (newBlock.Serialize().Length > Consensus.BlockSetting.MAX_BLOCK_SIZE)
            {
                throw new CommonException(ErrorCode.Engine.Block.Verify.BLOCK_SIZE_LARGE_THAN_LIMIT);
            }

            BlockMsg prevStepBlock = null;

            if (newBlock.Header.Height >= POC.DIFFIUCLTY_ADJUST_STEP)
            {
                var prevStepHeight = 0L;
                if (!GlobalParameters.IsTestnet &&
                    newBlock.Header.Height <= POC.DIFFICULTY_CALCULATE_LOGIC_ADJUST_HEIGHT)
                {
                    prevStepHeight = newBlock.Header.Height - POC.DIFFIUCLTY_ADJUST_STEP - 1;
                }
                else
                {
                    prevStepHeight = newBlock.Header.Height - POC.DIFFIUCLTY_ADJUST_STEP;
                }
                prevStepBlock = BlockDac.Default.SelectByHeight(prevStepHeight);
            }

            //区块必须包含交易,否则错误
            if (newBlock.Transactions == null || newBlock.Transactions.Count == 0)
            {
                throw new CommonException(ErrorCode.Engine.Transaction.Verify.NOT_FOUND_COINBASE);
            }

            //第一个一定是coinbase,奖励+手续费
            var coinbase = newBlock.Transactions[0];
            //校验打包区块的矿池是否经过验证
            var minerInfo = Encoding.UTF8.GetString(Base16.Decode(coinbase.Inputs[0].UnlockScript)).Split("`")[0];
            var pool      = MiningPoolComponent.CurrentMiningPools.FirstOrDefault(x => x.Name == minerInfo);

            if (pool == null)
            {
                throw new CommonException(ErrorCode.Engine.Block.Verify.MINING_POOL_NOT_EXISTED);
            }

            //校验区块的签名信息
            if (!POC.VerifyBlockSignature(newBlock.Header.PayloadHash, newBlock.Header.BlockSignature, pool.PublicKey))
            {
                LogHelper.Warn($"PayloadHash::{newBlock.Header.PayloadHash}");
                LogHelper.Warn($"BlockSignature::{newBlock.Header.BlockSignature}");
                LogHelper.Warn($"PublicKey::{pool.PublicKey}");
                throw new CommonException(ErrorCode.Engine.Block.Verify.BLOCK_SIGNATURE_IS_ERROR);
            }

            if (POC.CalculateBaseTarget(newBlock.Header.Height, previousBlockBits, previousBlockTimestamp,
                                        prevStepBlock) != newBlock.Header.Bits)
            {
                throw new CommonException(ErrorCode.Engine.Block.Verify.BITS_IS_WRONG);
            }

            var targetResult = POC.CalculateTargetResult(newBlock);

            if (newBlock.Header.Height == 17687 || POC.Verify(newBlock.Header.Bits, targetResult))
            {
                return(true);
            }
            else
            {
                throw new CommonException(ErrorCode.Engine.Block.Verify.POC_VERIFY_FAIL);
            }
        }
Exemple #19
0
        /// <summary>
        /// 创建新的区块
        /// </summary>
        /// <param name="minerName"></param>
        /// <param name="generatorId"></param>
        /// <param name="accountId"></param>
        /// <returns></returns>
        public BlockMsg CreateNewBlock(string minerName, string generatorId, string remark = null, string accountId = null)
        {
            var accountDac      = AccountDac.Default;
            var blockDac        = BlockDac.Default;
            var txDac           = TransactionDac.Default;
            var txPool          = TransactionPool.Instance;
            var txComponent     = new TransactionComponent();
            var transactionMsgs = new List <TransactionMsg>();

            long   lastBlockHeight    = -1;
            string lastBlockHash      = Base16.Encode(HashHelper.EmptyHash());
            long   lastBlockBits      = -1;
            string lastBlockGenerator = null;

            //获取最后一个区块
            var blockEntity = blockDac.SelectLast();

            if (blockEntity != null)
            {
                lastBlockHeight    = blockEntity.Header.Height;
                lastBlockHash      = blockEntity.Header.Hash;
                lastBlockBits      = blockEntity.Header.Bits;
                lastBlockGenerator = blockEntity.Header.GeneratorId;
            }

            long totalSize   = 0;
            long totalInput  = 0;
            long totalOutput = 0;
            long totalAmount = 0;
            long totalFee    = 0;

            long maxSize = Consensus.BlockSetting.MAX_BLOCK_SIZE - (1 * 1024);

            //获取待打包的交易
            var txs = txPool.GetTxsWithoutRepeatCost(10, maxSize);

            var hashIndexs = new List <string>();

            foreach (var tx in txs)
            {
                totalSize   += tx.Size;
                totalInput  += tx.InputCount;
                totalOutput += tx.OutputCount;
                hashIndexs.AddRange(tx.Inputs.Select(x => $"{x.OutputTransactionHash}_{x.OutputIndex}"));
                long totalOutputAmount = tx.Outputs.Sum(x => x.Amount);
                totalAmount += totalOutputAmount;
            }
            var utxos            = UtxoSetDac.Default.Get(hashIndexs);
            var totalInputAmount = utxos.Sum(x => x.Amount);

            totalFee = totalInputAmount - totalAmount;

            transactionMsgs.AddRange(txs);

            var accounts     = AccountDac.Default.SelectAll();
            var minerAccount = accounts.OrderBy(x => x.Timestamp).FirstOrDefault();

            if (accountId != null)
            {
                var account = accounts.FirstOrDefault(x => x.Id == accountId);

                if (account != null && !string.IsNullOrWhiteSpace(account.PrivateKey))
                {
                    minerAccount = account;
                }
            }

            var            minerAccountId = minerAccount.Id;
            BlockMsg       newBlockMsg    = new BlockMsg();
            BlockHeaderMsg headerMsg      = new BlockHeaderMsg();

            headerMsg.Hash              = Base16.Encode(HashHelper.EmptyHash());
            headerMsg.GeneratorId       = generatorId;
            newBlockMsg.Header          = headerMsg;
            headerMsg.Height            = lastBlockHeight + 1;
            headerMsg.PreviousBlockHash = lastBlockHash;

            if (headerMsg.Height == 0)
            {
                minerAccountId = Consensus.BlockSetting.GenesisBlockReceiver;
                remark         = Consensus.BlockSetting.GenesisBlockRemark;
            }

            BlockMsg prevBlockMsg     = null;
            BlockMsg prevStepBlockMsg = null;

            if (blockEntity != null)
            {
                prevBlockMsg = blockEntity;
            }

            if (headerMsg.Height >= POC.DIFFIUCLTY_ADJUST_STEP)
            {
                var prevStepHeight = 0L;
                if (!GlobalParameters.IsTestnet && headerMsg.Height <= POC.DIFFICULTY_CALCULATE_LOGIC_ADJUST_HEIGHT)
                {
                    prevStepHeight = headerMsg.Height - POC.DIFFIUCLTY_ADJUST_STEP - 1;
                }
                else
                {
                    prevStepHeight = headerMsg.Height - POC.DIFFIUCLTY_ADJUST_STEP;
                }
                prevStepBlockMsg = blockDac.SelectByHeight(prevStepHeight);
            }

            var newBlockReward = POC.GetNewBlockReward(headerMsg.Height);

            headerMsg.Bits             = POC.CalculateBaseTarget(headerMsg.Height, prevBlockMsg, prevStepBlockMsg);
            headerMsg.TotalTransaction = transactionMsgs.Count + 1;

            var coinbaseTxMsg = new TransactionMsg();

            coinbaseTxMsg.Timestamp = Time.EpochTime;
            coinbaseTxMsg.Locktime  = 0;

            var coinbaseInputMsg = new InputMsg();

            coinbaseTxMsg.Inputs.Add(coinbaseInputMsg);
            coinbaseInputMsg.OutputIndex           = 0;
            coinbaseInputMsg.OutputTransactionHash = Base16.Encode(HashHelper.EmptyHash());
            coinbaseInputMsg.UnlockScript          = Script.BuildMinerScript(minerName, remark);
            coinbaseInputMsg.Size = coinbaseInputMsg.UnlockScript.Length;

            var coinbaseOutputMsg = new OutputMsg();

            coinbaseTxMsg.Outputs.Add(coinbaseOutputMsg);
            coinbaseOutputMsg.Amount     = newBlockReward + totalFee;
            coinbaseOutputMsg.LockScript = Script.BuildLockScipt(minerAccountId);
            coinbaseOutputMsg.Size       = coinbaseOutputMsg.LockScript.Length;
            coinbaseOutputMsg.Index      = 0;

            if (newBlockReward < 0 || totalFee < 0 || coinbaseOutputMsg.Amount < 0)
            {
                LogHelper.Warn($"newBlockReward:{newBlockReward}");
                LogHelper.Warn($"totalFee:{totalFee}");
                LogHelper.Warn($"coinbaseOutputMsg.Amount:{coinbaseOutputMsg.Amount}");
                throw new CommonException(ErrorCode.Engine.Transaction.Verify.COINBASE_OUTPUT_AMOUNT_ERROR);
            }

            coinbaseTxMsg.Hash = coinbaseTxMsg.GetHash();

            newBlockMsg.Transactions.Insert(0, coinbaseTxMsg);


            foreach (var tx in transactionMsgs)
            {
                newBlockMsg.Transactions.Add(tx);
            }

            headerMsg.PayloadHash = newBlockMsg.GetPayloadHash();

            LogHelper.Warn($"{headerMsg.Height}::{headerMsg.PayloadHash}");
            LogHelper.Warn($"PayloadHash::{headerMsg.PayloadHash}");
            LogHelper.Warn($"BlockSignature::{headerMsg.BlockSignature}");
            LogHelper.Warn($"miner::{minerName}");

            headerMsg.BlockSignature   = Base16.Encode(HashHelper.EmptyHash());
            headerMsg.BlockSigSize     = headerMsg.BlockSignature.Length;
            headerMsg.TotalTransaction = newBlockMsg.Transactions.Count;
            return(newBlockMsg);
        }
Exemple #20
0
        internal static void Received(TcpReceiveState e, PoolCommand cmd)
        {
            var miner = PoolCache.WorkingMiners.FirstOrDefault(m => m.ClientAddress == e.Address && m.IsConnected);

            if (miner == null)
            {
                LogHelper.Info("Received invalid scoop data from " + e.Address);
                LogHelper.Info("Miner logout");
                PoolJob.TcpServer.CloseSocket(e);
                return;
            }

            if (PoolCache.CurrentTask == null || PoolCache.CurrentTask.State != MiningState.Mining)
            {
                return;
            }

            var msg   = new ScoopDataMsg();
            int index = 0;

            msg.Deserialize(cmd.Payload, ref index);


            PoolCache.CurrentTask.LastReceiveTime = Time.EpochTime;

            var minerinfo = PoolCache.CurrentTask.MinerEfforts.FirstOrDefault(x => x.Account == miner.WalletAddress);

            if (minerinfo == null)
            {
                PoolCache.CurrentTask.MinerEfforts.Add(new Models.MinerEffort {
                    Account = miner.WalletAddress, Effort = 1
                });
            }
            else
            {
                if (minerinfo.Effort == Setting.MaxNonceCount)
                {
                    RejectCommand.Send(e);
                    return;
                }
                minerinfo.Effort++;
            }

            if (msg.BlockHeight != PoolCache.CurrentTask.CurrentBlockHeight)
            {
                LogHelper.Info("Received invalid scoop data from " + e.Address + ", nonce is " + msg.Nonce + ", height is " + msg.BlockHeight);
                LogHelper.Info("Block Height invalid , Stop and Send StartMsg");

                var stopMsg = new StopMsg
                {
                    BlockHeight = msg.BlockHeight,
                    Result      = false,
                    StartTime   = Time.EpochTime,
                    StopTime    = Time.EpochTime
                };
                StopCommand.Send(e, stopMsg);
                Task.Delay(1000).Wait();
                var startMsg = PoolCache.CurrentTask.CurrentStartMsg;
                if (startMsg != null)
                {
                    StartCommand.Send(e, startMsg);
                }
                return;
            }

            LogHelper.Info("Received scoop data from " + miner.ClientAddress + ", nonce is " + msg.Nonce + ", scoop number is " + msg.ScoopNumber + ", block height is " + msg.BlockHeight);

            if (msg.ScoopNumber != PoolCache.CurrentTask.CurrentScoopNumber)
            {
                LogHelper.Info("Received invalid scoop data from " + e.Address + ", nonce is " + msg.Nonce + ", ScoopNumber is " + PoolCache.CurrentTask.CurrentScoopNumber + "/" + msg.ScoopNumber);
                LogHelper.Info("Scoop Number invalid");
                return;
            }

            var verResult = POC.Verify(PoolCache.CurrentTask.BaseTarget, msg.Target);

            LogHelper.Debug("Bits:" + POC.ConvertBitsToBigInt(PoolCache.CurrentTask.BaseTarget).ToString("X").PadLeft(64, '0'));
            LogHelper.Debug("Hash:" + Base16.Encode(msg.Target));
            LogHelper.Debug("Verify Result is " + verResult);

            if (!verResult)
            {
                return;
            }

            ForgeMsg forgeMsg = new ForgeMsg();

            forgeMsg.Account    = msg.WalletAddress;
            forgeMsg.Nonce      = msg.Nonce;
            forgeMsg.StartMsgId = PoolCache.CurrentTask.Id;

            //MQApi.SendForgeBlock(msg.WalletAddress, msg.Nonce, PoolCache.CurrentTask.Id);
            RabbitMQApi.SendForgeBlock(msg.WalletAddress, msg.Nonce, PoolCache.CurrentTask.Id);
        }
Exemple #21
0
        public static void SaveRewards(string startMsgId, long nonce, int height)
        {
            try
            {
                var block = RedisManager.Current.GetDataInRedis <BlockMsg>(startMsgId);
                if (block == null || block.Header.Height == 0)
                {
                    return;
                }

                var miners          = GetAllMiners();
                var rewardAddresses = miners.Select(x => x.Address);


                Blocks blocks = new Blocks();
                blocks.Generator = block.Header.GeneratorId;
                blocks.Hash      = block.Header.GetHash();
                blocks.Height    = block.Header.Height;
                blocks.Nonce     = nonce;

                var baseReward  = POC.GetNewBlockReward(block.Header.Height);
                var totalReward = block.Transactions[0].Outputs[0].Amount;

                if (totalReward < baseReward)
                {
                    totalReward = baseReward;
                }
                var totalRewardAllMiner        = totalReward * 0.4;
                var totalRewardSuperNode       = totalReward * 0.2;
                var totalRewardDepositInterest = totalReward * 0.4;//存币利息,需要派分到当前存币大于1的地址

                var rewards = new List <RewardList>();
                //矿工部分
                long totalEffort = 0;
                foreach (var address in rewardAddresses)
                {
                    var key      = "Pool:MinerMaxNonce:" + address;
                    var maxNonce = RedisManager.Current.GetDataInRedis <string>(key);
                    if (string.IsNullOrEmpty(maxNonce))
                    {
                        continue;
                    }
                    var        effort     = int.Parse(maxNonce);
                    RewardList rewardList = new RewardList();
                    rewardList.BlockHash       = blocks.Hash;
                    rewardList.GenerateTime    = blocks.Timstamp;
                    rewardList.MinerAddress    = address;
                    rewardList.Hashes          = effort;
                    rewardList.TransactionHash = "";
                    rewardList.RewardType      = 0;
                    rewards.Add(rewardList);
                    totalEffort += effort;
                }
                rewards.ForEach(x =>
                {
                    x.OriginalReward = (long)Math.Floor(totalRewardAllMiner * ((double)x.Hashes / (double)totalEffort));
                    x.ActualReward   = x.OriginalReward;
                });
                blocks.TotalHash   = totalEffort;
                blocks.TotalReward = totalReward;
                //SuperNode部分
                AwardSetting setting         = ConfigurationTool.GetAppSettings <AwardSetting>("OmniCoin.MiningPool.Business.conf.json", "AwardSetting");
                var          superNodeReward = (long)totalRewardSuperNode;
                rewards.Add(new RewardList
                {
                    OriginalReward  = superNodeReward,
                    ActualReward    = superNodeReward,
                    BlockHash       = blocks.Hash,
                    GenerateTime    = blocks.Timstamp,
                    MinerAddress    = setting.SuperNodeAddress,
                    Hashes          = 0,
                    TransactionHash = "",
                    RewardType      = 1
                });
                //DepositInterest部分
                var currentDepositLists = new RewardListComponent().GetAllNotExpiredDeposit();
                if (currentDepositLists != null && currentDepositLists.Any())
                {
                    var totalDepositAmount = currentDepositLists.Sum(x => x.Amount);
                    currentDepositLists.ForEach(x =>
                    {
                        //利息 = 当前数量 / 总数量 * (Coinbase * 40 % 奖励)
                        var interest = (long)Math.Floor(totalRewardDepositInterest * ((double)x.Amount / (double)totalDepositAmount));
                        rewards.Add(new RewardList
                        {
                            OriginalReward            = interest,
                            ActualReward              = interest,
                            BlockHash                 = blocks.Hash,
                            GenerateTime              = blocks.Timstamp,
                            MinerAddress              = x.Address,
                            Hashes                    = 0,
                            TransactionHash           = "",
                            AddressDepositTotalAmount = x.Amount,
                            DepositTotalAmount        = totalDepositAmount,
                            RewardType                = 2,
                            DepositTransactionHash    = x.TransactionHash
                        });
                    });
                }
                var blockComponent = new BlocksComponent();
                blockComponent.SaveBlockAndRewardLists(blocks, rewards);
            }
            catch (Exception ex)
            {
                LogHelper.Error(ex.ToString());
            }
        }
Exemple #22
0
        /// <summary>
        /// 创建新的区块
        /// </summary>
        /// <param name="minerName"></param>
        /// <param name="generatorId"></param>
        /// <param name="accountId"></param>
        /// <returns></returns>
        public BlockMsg CreateNewBlock(string minerName, string generatorId, string remark = null, string accountId = null)
        {
            var accountDac      = new AccountDac();
            var blockDac        = new BlockDac();
            var outputDac       = new OutputDac();
            var txDac           = new TransactionDac();
            var txPool          = TransactionPool.Instance;
            var transactionMsgs = new List <TransactionMsg>();

            long   lastBlockHeight    = -1;
            string lastBlockHash      = Base16.Encode(HashHelper.EmptyHash());
            long   lastBlockBits      = -1;
            string lastBlockGenerator = null;

            //获取最后一个区块
            var blockEntity = blockDac.SelectLast();

            if (blockEntity != null)
            {
                lastBlockHeight    = blockEntity.Height;
                lastBlockHash      = blockEntity.Hash;
                lastBlockBits      = blockEntity.Bits;
                lastBlockGenerator = blockEntity.GeneratorId;
            }

            long totalSize    = 0;
            long maxSize      = BlockSetting.MAX_BLOCK_SIZE - (1 * 1024);
            var  poolItemList = txPool.MainPool.OrderByDescending(t => t.FeeRate).ToList();
            var  index        = 0;

            while (totalSize < maxSize && index < poolItemList.Count)
            {
                var tx = poolItemList[index].Transaction;

                if (tx != null && transactionMsgs.Where(t => t.Hash == tx.Hash).Count() == 0)
                {
                    if (txDac.SelectByHash(tx.Hash) == null)
                    {
                        transactionMsgs.Add(tx);
                        totalSize += tx.Size;
                    }
                    else
                    {
                        txPool.RemoveTransaction(tx.Hash);
                    }
                }
                else
                {
                    break;
                }

                index++;
            }


            var minerAccount = accountDac.SelectDefaultAccount();

            if (accountId != null)
            {
                var account = accountDac.SelectById(accountId);

                if (account != null && !string.IsNullOrWhiteSpace(account.PrivateKey))
                {
                    minerAccount = account;
                }
            }

            var minerAccountId = minerAccount.Id;

            BlockMsg       newBlockMsg = new BlockMsg();
            BlockHeaderMsg headerMsg   = new BlockHeaderMsg();

            headerMsg.Hash              = Base16.Encode(HashHelper.EmptyHash());
            headerMsg.GeneratorId       = generatorId;
            newBlockMsg.Header          = headerMsg;
            headerMsg.Height            = lastBlockHeight + 1;
            headerMsg.PreviousBlockHash = lastBlockHash;

            if (headerMsg.Height == 0)
            {
                minerAccountId = BlockSetting.GenesisBlockReceiver;
                remark         = BlockSetting.GenesisBlockRemark;
            }

            long totalAmount = 0;
            long totalFee    = 0;

            foreach (var tx in transactionMsgs)
            {
                long totalInputsAmount = 0L;
                long totalOutputAmount = 0L;

                foreach (var input in tx.Inputs)
                {
                    var utxo = outputDac.SelectByHashAndIndex(input.OutputTransactionHash, input.OutputIndex);

                    if (utxo != null)
                    {
                        totalInputsAmount += utxo.Amount;
                    }
                }

                foreach (var output in tx.Outputs)
                {
                    totalOutputAmount += output.Amount;
                }

                totalAmount += totalOutputAmount;
                totalFee    += (totalInputsAmount - totalOutputAmount);
            }

            //var work = new POW(headerMsg.Height);
            BlockMsg prevBlockMsg     = null;
            BlockMsg prevStepBlockMsg = null;

            if (blockEntity != null)
            {
                prevBlockMsg = this.convertEntityToBlockMsg(blockEntity);
            }

            if (headerMsg.Height >= POC.DIFFIUCLTY_ADJUST_STEP)
            {
                prevStepBlockMsg = this.GetBlockMsgByHeight(headerMsg.Height - POC.DIFFIUCLTY_ADJUST_STEP - 1);
            }

            var newBlockReward = POC.GetNewBlockReward(headerMsg.Height);

            headerMsg.Bits             = POC.CalculateBaseTarget(headerMsg.Height, prevBlockMsg, prevStepBlockMsg);
            headerMsg.TotalTransaction = transactionMsgs.Count + 1;

            var coinbaseTxMsg = new TransactionMsg();

            coinbaseTxMsg.Timestamp = Time.EpochTime;
            coinbaseTxMsg.Locktime  = 0;

            var coinbaseInputMsg = new InputMsg();

            coinbaseTxMsg.Inputs.Add(coinbaseInputMsg);
            coinbaseInputMsg.OutputIndex           = 0;
            coinbaseInputMsg.OutputTransactionHash = Base16.Encode(HashHelper.EmptyHash());
            coinbaseInputMsg.UnlockScript          = Script.BuildMinerScript(minerName, remark);
            coinbaseInputMsg.Size = coinbaseInputMsg.UnlockScript.Length;

            var coinbaseOutputMsg = new OutputMsg();

            coinbaseTxMsg.Outputs.Add(coinbaseOutputMsg);
            coinbaseOutputMsg.Amount     = newBlockReward + totalFee;
            coinbaseOutputMsg.LockScript = Script.BuildLockScipt(minerAccountId);
            coinbaseOutputMsg.Size       = coinbaseOutputMsg.LockScript.Length;
            coinbaseOutputMsg.Index      = 0;

            coinbaseTxMsg.Hash = coinbaseTxMsg.GetHash();

            newBlockMsg.Transactions.Insert(0, coinbaseTxMsg);

            foreach (var tx in transactionMsgs)
            {
                newBlockMsg.Transactions.Add(tx);
            }

            headerMsg.PayloadHash = newBlockMsg.GetPayloadHash();
            var dsa        = ECDsa.ImportPrivateKey(Base16.Decode(minerAccount.PrivateKey));
            var signResult = dsa.SingnData(Base16.Decode(headerMsg.PayloadHash));

            headerMsg.BlockSignature   = Base16.Encode(signResult);
            headerMsg.BlockSigSize     = headerMsg.BlockSignature.Length;
            headerMsg.TotalTransaction = newBlockMsg.Transactions.Count;
            return(newBlockMsg);
        }
Exemple #23
0
        public bool VerifyBlock(BlockMsg newBlock)
        {
            if (this.exists(newBlock.Header.Hash))
            {
                throw new CommonException(ErrorCode.Engine.Block.Verify.BLOCK_HAS_BEEN_EXISTED);
            }

            if (newBlock.Header.Hash != newBlock.Header.GetHash())
            {
                throw new CommonException(ErrorCode.Engine.Block.Verify.BLOCK_HASH_ERROR);
            }

            var blockComponent = new BlockComponent();
            var previousBlock  = this.GetBlockMsgByHash(newBlock.Header.PreviousBlockHash);

            if (newBlock.Header.Height > 0 && previousBlock == null)
            {
                throw new CommonException(ErrorCode.Engine.Block.Verify.PREV_BLOCK_NOT_EXISTED);
            }

            if ((newBlock.Header.Timestamp > Time.EpochTime && (newBlock.Header.Timestamp - Time.EpochTime) > 2 * 60 * 60 * 1000) ||
                (previousBlock != null && newBlock.Header.Timestamp <= previousBlock.Header.Timestamp))
            {
                throw new CommonException(ErrorCode.Engine.Block.Verify.BLOCK_TIME_IS_ERROR);
            }

            if (newBlock.Serialize().Length > BlockSetting.MAX_BLOCK_SIZE)
            {
                throw new CommonException(ErrorCode.Engine.Block.Verify.BLOCK_SIZE_LARGE_THAN_LIMIT);
            }

            var txComponent = new TransactionComponent();

            var newBlockReward = POC.GetNewBlockReward(newBlock.Header.Height);
            var prevStepBlock  = GetBlockMsgByHeight(newBlock.Header.Height - POC.DIFFIUCLTY_ADJUST_STEP - 1);
            var minerInfo      = string.Empty;

            if (newBlock.Transactions.Count > 0)
            {
                var coinbase = newBlock.Transactions[0];
                var totalFee = 0L;

                minerInfo = Encoding.UTF8.GetString(Base16.Decode(coinbase.Inputs[0].UnlockScript)).Split("`")[0];

                if (newBlock.Transactions.Count > 1)
                {
                    for (int i = 1; i < newBlock.Transactions.Count; i++)
                    {
                        long fee;
                        if (txComponent.VerifyTransaction(newBlock.Transactions[i], out fee))
                        {
                            totalFee += fee;
                        }
                        else
                        {
                            return(false);
                        }
                    }
                }

                if (coinbase.Inputs.Count != 1 || coinbase.Outputs.Count != 1 || coinbase.Inputs[0].OutputTransactionHash != Base16.Encode(HashHelper.EmptyHash()))
                {
                    throw new CommonException(ErrorCode.Engine.Transaction.Verify.COINBASE_FORMAT_ERROR);
                }
                else
                {
                    var output = coinbase.Outputs[0];

                    if (output.Amount > BlockSetting.OUTPUT_AMOUNT_MAX)
                    {
                        throw new CommonException(ErrorCode.Engine.Transaction.Verify.OUTPUT_EXCEEDED_THE_LIMIT);
                    }

                    if (!Script.VerifyLockScriptFormat(output.LockScript))
                    {
                        throw new CommonException(ErrorCode.Engine.Transaction.Verify.SCRIPT_FORMAT_ERROR);
                    }

                    if (output.Amount != (totalFee + newBlockReward))
                    {
                        throw new CommonException(ErrorCode.Engine.Transaction.Verify.COINBASE_OUTPUT_AMOUNT_ERROR);
                    }
                }
            }

            var pool = new MiningPoolComponent().GetMiningPoolByName(minerInfo);

            if (pool == null)
            {
                throw new CommonException(ErrorCode.Engine.Block.Verify.MINING_POOL_NOT_EXISTED);
            }

            if (!POC.VerifyBlockSignature(newBlock.Header.PayloadHash, newBlock.Header.BlockSignature, pool.PublicKey))
            {
                throw new CommonException(ErrorCode.Engine.Block.Verify.BLOCK_SIGNATURE_IS_ERROR);
            }

            long previousBlockHeight = -1;
            long previousBlockBits   = -1;

            if (previousBlock != null)
            {
                previousBlockHeight = previousBlock.Header.Height;
                previousBlockBits   = previousBlock.Header.Bits;
            }

            if (POC.CalculateBaseTarget(newBlock.Header.Height, previousBlock, prevStepBlock) != newBlock.Header.Bits)
            {
                throw new CommonException(ErrorCode.Engine.Block.Verify.BITS_IS_WRONG);
            }

            var targetResult = POC.CalculateTargetResult(newBlock);

            if (POC.Verify(newBlock.Header.Bits, targetResult))
            {
                return(true);
            }
            else
            {
                throw new CommonException(ErrorCode.Engine.Block.Verify.POC_VERIFY_FAIL);
            }
        }
Exemple #24
0
 public async Task Create(POC poc)
 {
     await context1.POCs.InsertOneAsync(poc);
 }