Exemplo n.º 1
0
        public bool DailyRewardStat()
        {
            try
            {
                bool          exist   = true;
                List <string> listSql = new List <string>();
                // Start quotation marks for the next round of calculations.
                // if the program had been interrupted,
                // the next compute will be after the next digit of the serial number of the previous round of calculations
                int lastIndex = dataProvider.ReturnIntValue("select max(id) from DposRewardDetails where reward_state=1");
                if (lastIndex > 0)
                {
                    startIndex = lastIndex + 1;
                }

                int endIndex = dataProvider.ReturnIntValue("select max(id) from (select id from DposRewardDetails where reward_state=0 order by id limit 1000) t");
                if (endIndex <= 0)
                {
                    Console.WriteLine("[Daily Reward] waiting ...");
                    Debuger.TraceAlone("[Daily Reward] waiting ...", "daily");
                    return(false);
                }

                Console.WriteLine("[Daily Reward] Scope of index : [" + startIndex + " ——>> " + endIndex + "]");
                Debuger.TraceAlone("[Daily Reward] Scope of index : [" + startIndex + " ——>> " + endIndex + "]", "daily");
                dataProvider.AddParam("?startIndex", startIndex);
                dataProvider.AddParam("?endIndex", endIndex);
                DataTable dt = dataProvider.ExecDataSet(@"select dpos_addr,client_addr,sum(reward_money) as reward,reward_date from DposRewardDetails where reward_state=0 and id between ?startIndex and ?endIndex group by dpos_addr,reward_date,client_addr").Tables[0];
                foreach (DataRow r in dt.Rows)
                {
                    //  Summary of historical income data and dynamic summary of day income
                    var reward_date = DateTime.Parse(r["reward_date"].ToString()).ToString("yyyy-MM-dd");
                    exist = dataProvider.Exist("select id from DposDailyReward where dpos_addr='" + r["dpos_addr"].ToString() + "' and client_addr='" + r["client_addr"].ToString() + "' and payment_date='" + reward_date + "'");
                    if (exist)
                    {
                        listSql.Add("update DposDailyReward set payment_money=payment_money+" + r["reward"].ToString() + " where dpos_addr='" + r["dpos_addr"].ToString() + "' and client_addr='" + r["client_addr"].ToString() + "' and payment_date='" + reward_date + "'");
                    }
                    else
                    {
                        listSql.Add("insert into DposDailyReward(dpos_addr,client_addr,payment_date,payment_money) values('" + r["dpos_addr"].ToString() + "','" + r["client_addr"].ToString() + "','" + reward_date + "'," + r["reward"].ToString() + ")");
                    }
                }

                if (listSql.Count <= 0)
                {
                    return(false);
                }

                listSql.Add("update DposRewardDetails set reward_state=1 where id between " + startIndex + " and " + endIndex);
                return(dataProvider.ExecSqlTran(listSql));
            }
            catch (Exception ex)
            {
                Console.WriteLine("[Daily Reward Exception] " + ex.Message);
                Debuger.TraceAlone("[Daily Reward Exception] " + ex.Message, "daily");
                return(false);
            }
        }
Exemplo n.º 2
0
        /// <summary>
        ///  Calculate the reward according to the edpos block of each node
        /// </summary>
        public bool BlockRewardStat()
        {
            try
            {
                // Start quotation marks for the next round of calculations.
                // if the program had been interrupted,
                // the next compute will be after the next digit of the serial number of the previous round of calculations
                int lastBlockHeight = dataProvider.ReturnIntValue("select max(block_height) from DposRewardDetails");
                if (lastBlockHeight > 0)
                {
                    startHeight = lastBlockHeight + 1;
                }

                //Get effective height
                int newHeight = dataProvider.ReturnIntValue(@"select height from Block where is_useful = 1 order by height desc limit 1 ");
                dataProvider.AddParam("?startHeight", startHeight);
                dataProvider.AddParam("?endHeight", newHeight - ConfirmHeight);
                DataTable dt = dataProvider.ExecDataSet(
                    @"select id,hash,FROM_UNIXTIME(time,'%Y-%m-%d') as time,height,reward_address,reward_money from Block 
                      where type = 'primary-dpos' 
                      and is_useful = 1 
                      and reward_state = 0 
                      and height between ?startHeight and ?endHeight 
                      order by height asc 
                      limit 1000").Tables[0];

                if (dt.Rows.Count > 0)
                {
                    lastBlockHeight = dt.AsEnumerable().Max(x => x.Field <int>("height"));
                    string msg = "[Block Reward] Scope of index : [" + startHeight + " ——>> " + lastBlockHeight + "]";
                    Console.WriteLine(msg);
                    Debuger.Trace(msg);
                }
                else
                {
                    string msg = "[Block Reward] waiting for the next DPoS block. The next round of the compute will starts at the height of " + startHeight;
                    Console.WriteLine(msg);
                    Debuger.Trace(msg);
                    return(false);
                }

                int minid = GetTxMinID();
                foreach (DataRow r in dt.Rows)
                {
                    // Voters is used to record the number of voters and casts
                    Dictionary <string, decimal> voters = new Dictionary <string, decimal>();
                    // Redem_voters is used to record the number of the voters and tokens who have redeemed
                    Dictionary <string, decimal> redem_voters = new Dictionary <string, decimal>();
                    // The voting result set and the redemption result set are merged and combined
                    // Adding and subtracting can be done which have the same key
                    Dictionary <string, decimal> merge_voters = new Dictionary <string, decimal>();
                    List <string> listSql = new List <string>();
                    int           maxid   = GetTxMaxID(r["hash"].ToString());

                    decimal selfVote = 0, selfIn = 0, selfOut = 0;

                    if (int.Parse(r["height"].ToString()) <= 248997)
                    {
                        dataProvider.AddParam("?block_hash", r["hash"].ToString());
                        dataProvider.AddParam("?address", r["reward_address"].ToString());
                        selfVote = dataProvider.ReturnDecimalValue("select amount from Tx where block_hash=?block_hash and `to`=?address and type='certification' and n=0");
                        if (selfVote == 0)
                        {
                            dataProvider.AddParam("?address", r["reward_address"].ToString());
                            selfVote = dataProvider.ReturnDecimalValue("select vote_amount from DposRewardDetails where dpos_addr=?address and client_addr=?address order by block_height desc limit 1");

                            string msg = "[" + r["reward_address"].ToString() + "] height: " + r["height"].ToString() + ", selfVote: " + selfVote.ToString();
                            Console.WriteLine(msg);
                            Debuger.Trace(msg);
                        }
                    }
                    else
                    {
                        dataProvider.AddParam("?minid", minid);
                        dataProvider.AddParam("?maxid", maxid - 1);
                        dataProvider.AddParam("?address", r["reward_address"].ToString());

                        selfIn = dataProvider.ReturnDecimalValue("select sum(amount) from Tx where `to`=?address and (form<>?address or (type='certification' and n=1)) and id between ?minid and ?maxid");

                        dataProvider.AddParam("?minid", minid);
                        dataProvider.AddParam("?maxid", maxid);
                        dataProvider.AddParam("?address", r["reward_address"].ToString());

                        selfOut  = dataProvider.ReturnDecimalValue("select sum(amount) from Tx where form=?address and `to`<>?address and id between ?minid and ?maxid");
                        selfVote = selfIn - selfOut;
                        string msg = "[" + r["reward_address"].ToString() + "] height: " + r["height"].ToString() + ",selfVote: " + selfVote.ToString() + " selfIn:" + selfIn.ToString() + " selfOut: " + selfOut.ToString();

                        Console.WriteLine(msg);
                        Debuger.Trace(msg);
                    }

                    if (voters.ContainsKey(r["reward_address"].ToString()))
                    {
                        voters[r["reward_address"].ToString()] = selfVote;
                    }
                    else
                    {
                        // self-cast tokens
                        voters.Add(r["reward_address"].ToString(), selfVote);
                    }

                    dataProvider.AddParam("?address", r["reward_address"].ToString());
                    dataProvider.AddParam("?id", maxid);
                    DataSet ds = dataProvider.ExecDataSet(
                        @"select client_in,ifnull(sum(amount),0) as amount from Tx 
                          where dpos_in=?address and id <=?id group by client_in;
                          select client_out,ifnull(sum(amount+free),0) as amount from Tx 
                          where dpos_out=?address and id <=?id group by client_out;");

                    DataTable dtVotes = ds.Tables[0];
                    DataTable dtRedem = ds.Tables[1];
                    foreach (DataRow voter in dtVotes.Rows)
                    {
                        if (voters.ContainsKey(voter["client_in"].ToString()))
                        {
                            voters[voter["client_in"].ToString()] += decimal.Parse(voter["amount"].ToString());
                        }
                        else
                        {
                            voters.Add(voter["client_in"].ToString(), decimal.Parse(voter["amount"].ToString()));
                        }
                    }

                    foreach (DataRow voter in dtRedem.Rows)
                    {
                        if (redem_voters.ContainsKey(voter["client_out"].ToString()))
                        {
                            redem_voters[voter["client_out"].ToString()] -= decimal.Parse(voter["amount"].ToString());
                        }
                        else
                        {
                            redem_voters.Add(voter["client_out"].ToString(), -decimal.Parse(voter["amount"].ToString()));
                        }
                    }

                    // The voting result set and the redemption result set are merged and combined
                    // Adding and subtracting can be done which have the same key
                    var m = voters.Keys.Union(redem_voters.Keys);
                    foreach (var v in m)
                    {
                        merge_voters.Add(v, (voters.ContainsKey(v) ? voters[v] : 0) + (redem_voters.ContainsKey(v) ? redem_voters[v] : 0));
                    }
                    decimal total = merge_voters.Select(x => x.Value).Sum();

                    var reward_address = r["reward_address"].ToString();
                    var reward_money   = Decimal.Parse(r["reward_money"].ToString());
                    var reward_date    = DateTime.Parse(r["time"].ToString()).ToString("yyyy-MM-dd");
                    var block_height   = r["height"].ToString();

                    foreach (KeyValuePair <string, decimal> kv in merge_voters)
                    {
                        if (kv.Value != 0)
                        {
                            listSql.Add(@"insert into DposRewardDetails(dpos_addr,client_addr,vote_amount,reward_money,reward_date,block_height) values('" + reward_address + "','" + kv.Key + "'," + kv.Value + "," + kv.Value / total * reward_money + ",'" + reward_date + "'," + block_height + ")");

                            // 本节点单位收益 = reward_money / total
                            // 平均单位收益 =
                        }
                    }
                    // Set the state of the block as 1,it shows that this block has been used
                    listSql.Add("update Block set reward_state=1 where id='" + r["id"].ToString() + "'");
                    dataProvider.ExecSqlTran(listSql);
                }

                return(true);
            }
            catch (Exception ex)
            {
                string msg = "[Block Reward Exception] " + ex.Message;
                Console.WriteLine(msg);
                Debuger.Error(msg);
                return(false);
            }
        }
Exemplo n.º 3
0
        /// <summary>
        ///  Calculate the reward according to the edpos block of each node
        /// </summary>
        public bool BlockRewardStat()
        {
            try
            {
                // Start quotation marks for the next round of calculations.
                // if the program had been interrupted,
                // the next compute will be after the next digit of the serial number of the previous round of calculations
                int lastBlockHeight = dataProvider.ReturnIntValue("select max(block_height) from DposRewardDetails");
                if (lastBlockHeight > 0)
                {
                    startHeight = lastBlockHeight + 1;
                }

                //Get effective height, 有效高度
                int newHeight = dataProvider.ReturnIntValue(@"select height from Block where is_useful = 1 order by height desc limit 1 ");
                dataProvider.AddParam("?startHeight", startHeight);
                dataProvider.AddParam("?endHeight", newHeight - ConfirmHeight);
                DataTable dposBlocks = dataProvider.ExecDataSet(
                    @"select id,hash,FROM_UNIXTIME(time,'%Y-%m-%d') as time,height,reward_address,reward_money from Block 
                      where type = 'primary-dpos' 
                      and is_useful = 1 
                      and reward_state = 0 
                      and height between ?startHeight and ?endHeight 
                      order by height asc 
                      limit 1000").Tables[0]; //dpos出块奖励blocks, id,hash,time,height,reward_address,money

                if (dposBlocks.Rows.Count > 0)
                {
                    lastBlockHeight = dposBlocks.AsEnumerable().Max(x => x.Field <int>("height")); //max height in result
                    string msg = "[Block Reward] Scope of index : [" + startHeight + " ——>> " + lastBlockHeight + "]";
                    Console.WriteLine(msg);
                    Debuger.Trace(msg);
                }
                else
                {
                    string msg = "[Block Reward] waiting for the next DPoS block. The next round of the compute will starts at the height of " + startHeight;
                    Console.WriteLine(msg);
                    Debuger.Trace(msg);
                    return(false);
                }

                int minid = GetTxMinID();                     //高度为248969 的交易的最小id??
                foreach (DataRow blockRow in dposBlocks.Rows) //range blocks
                {
                    // Voters is used to record the number of voters and casts
                    Dictionary <string, decimal> voters = new Dictionary <string, decimal>();        //key: 投票人, value: 投票金额
                    // Redem_voters is used to record the number of the voters and tokens who have redeemed
                    Dictionary <string, decimal> redeem_voters = new Dictionary <string, decimal>(); //key: 投票人, value: 赎回金额 (负数)
                    // The voting result set and the redemption result set are merged and combined
                    // Adding and subtracting can be done which have the same key
                    Dictionary <string, decimal> merge_voters = new Dictionary <string, decimal>(); //投票-赎回
                    List <string> listSql          = new List <string>();
                    int           maxIdOfTxInBlock = GetTxMaxID(blockRow["hash"].ToString());       //max(id) from tx where hash = ?

                    //计算节点自身投票:start
                    decimal selfVote = 0, selfIn = 0, selfOut = 0;          //节点自身的有效投票金额,投入,赎回

                    if (int.Parse(blockRow["height"].ToString()) <= 248997) //2020-05-14 23:38:13, blockHash: 0003cca552ae27b26db2339c8180b007c2ded18f92027fe381a30f3cca16262f
                    {                                                       //高度小于248997 时,用 certification 交易确定节点自投金额,(取这个区块的cert交易的n=0的utxo的金额
                        dataProvider.AddParam("?block_hash", blockRow["hash"].ToString());
                        dataProvider.AddParam("?address", blockRow["reward_address"].ToString());
                        selfVote = dataProvider.ReturnDecimalValue("select amount from Tx where block_hash=?block_hash and `to`=?address and type='certification' and n=0"); //TODO ? n=0似乎有不少金额为0.000001的情况,这个可能有问题,要确认下
                        if (selfVote == 0)                                                                                                                                   //实际的数据里似乎不存在为0的情况
                        {
                            dataProvider.AddParam("?address", blockRow["reward_address"].ToString());
                            selfVote = dataProvider.ReturnDecimalValue("select vote_amount from DposRewardDetails where dpos_addr=?address and client_addr=?address order by block_height desc limit 1");

                            string msg = "[" + blockRow["reward_address"].ToString() + "] height: " + blockRow["height"].ToString() + ", selfVote: " + selfVote.ToString();
                            Console.WriteLine(msg);
                            Debuger.Trace(msg);
                        }
                    }
                    else //区块高度>=248997时,计算节点在这个区块时的自投金额公式: 自投-自投赎回
                    {
                        dataProvider.AddParam("?minid", minid);
                        dataProvider.AddParam("?maxid", maxIdOfTxInBlock - 1);
                        dataProvider.AddParam("?address", blockRow["reward_address"].ToString());

                        selfIn = dataProvider.ReturnDecimalValue(@"
                        select sum(amount) 
                        from Tx 
                        where `to`=?address and (form<>?address or (type='certification' and n=1)) and id between ?minid and ?maxid"); //投给节点本身的票

                        dataProvider.AddParam("?minid", minid);
                        dataProvider.AddParam("?maxid", maxIdOfTxInBlock);
                        dataProvider.AddParam("?address", blockRow["reward_address"].ToString());

                        selfOut  = dataProvider.ReturnDecimalValue(@"
                        select sum(amount) 
                        from Tx 
                        where form=?address and `to`<>?address and id between ?minid and ?maxid"); //节点本身的投票赎回
                        selfVote = selfIn - selfOut;
                        string msg = "[" + blockRow["reward_address"].ToString() + "] height: " + blockRow["height"].ToString() + ",selfVote: " + selfVote.ToString() + " selfIn:" + selfIn.ToString() + " selfOut: " + selfOut.ToString();

                        Console.WriteLine(msg);
                        Debuger.Trace(msg);
                    }

                    if (voters.ContainsKey(blockRow["reward_address"].ToString()))
                    {
                        voters[blockRow["reward_address"].ToString()] = selfVote;
                    }
                    else
                    {
                        voters.Add(blockRow["reward_address"].ToString(), selfVote);//delegate vote to self
                    }
                    //计算节点自身投票:end

                    dataProvider.AddParam("?address", blockRow["reward_address"].ToString());
                    dataProvider.AddParam("?id", maxIdOfTxInBlock);
                    DataSet ds = dataProvider.ExecDataSet(
                        @"select client_in,ifnull(sum(amount),0) as amount 
                          from Tx 
                          where dpos_in=?address and id <=?id 
                          group by client_in;

                          select client_out,ifnull(sum(amount+free),0) as amount 
                          from Tx 
                          where dpos_out=?address and id <=?id group by client_out;");

                    DataTable dtVotes  = ds.Tables[0];      //一般地址投票
                    DataTable dtRedeem = ds.Tables[1];      //一般地址赎回 (撤回投票实际的票数为:转出金额+手续费, 手续费后续作为区块打包节点的自投票)
                    foreach (DataRow voter in dtVotes.Rows) //range votes
                    {
                        if (voters.ContainsKey(voter["client_in"].ToString()))
                        {
                            voters[voter["client_in"].ToString()] += decimal.Parse(voter["amount"].ToString());
                        }
                        else
                        {
                            voters.Add(voter["client_in"].ToString(), decimal.Parse(voter["amount"].ToString()));
                        }
                    }

                    foreach (DataRow voter in dtRedeem.Rows) //range redeem
                    {
                        if (redeem_voters.ContainsKey(voter["client_out"].ToString()))
                        {
                            redeem_voters[voter["client_out"].ToString()] -= decimal.Parse(voter["amount"].ToString());
                        }
                        else
                        {
                            redeem_voters.Add(voter["client_out"].ToString(), -decimal.Parse(voter["amount"].ToString()));
                        }
                    }

                    // The voting result set and the redemption result set are merged and combined
                    // Adding and subtracting can be done which have the same key
                    var m = voters.Keys.Union(redeem_voters.Keys);
                    foreach (var v in m)
                    {
                        merge_voters.Add(v, (voters.ContainsKey(v) ? voters[v] : 0) + (redeem_voters.ContainsKey(v) ? redeem_voters[v] : 0));
                    }
                    //计算合并后的投票(merge_voters) end
                    decimal totalVoteAmount = merge_voters.Select(x => x.Value).Sum(); //节点合计投票总额

                    var dpos_miner_address    = blockRow["reward_address"].ToString();
                    var block_coinbase_amount = Decimal.Parse(blockRow["reward_money"].ToString());
                    var reward_date           = DateTime.Parse(blockRow["time"].ToString()).ToString("yyyy-MM-dd");
                    var block_height          = blockRow["height"].ToString();

                    foreach (KeyValuePair <string, decimal> kv in merge_voters)
                    {
                        string  voterAddress = kv.Key;
                        decimal voteAmount   = kv.Value;
                        if (voteAmount != 0)
                        {
                            decimal voteRewardAmount = voteAmount / totalVoteAmount * block_coinbase_amount;
                            listSql.Add(@"insert into DposRewardDetails(dpos_addr,client_addr,vote_amount,reward_money,reward_date,block_height) 
                            values('" + dpos_miner_address + "','" + voterAddress + "'," + voteAmount + "," + voteRewardAmount + ",'" + reward_date + "'," + block_height + ")");
                        }
                    }
                    // Set the state of the block as 1,it shows that this block has been used
                    listSql.Add("update Block set reward_state=1 where id='" + blockRow["id"].ToString() + "'");
                    dataProvider.ExecSqlTran(listSql);
                }

                return(true);
            }
            catch (Exception ex)
            {
                string msg = "[Block Reward Exception] " + ex.Message;
                Console.WriteLine(msg);
                Debuger.Error(msg);
                return(false);
            }
        }