/// <summary> /// 获取转账的这笔钱能分到的分红 [start,end) /// </summary> /// <param name="blockHeight">上次claim的高度</param> /// <param name="value">账户拥有的nnc数量</param> /// <returns>可以领取的值</returns> private static Info updateCanClaim(BigInteger curHeight, Info info, BigInteger balance, BigInteger value) { //获取上一个有完整记录的块的记录值 CoinPoolInfo coinPoolInfo = getCoinPoolInfo(); var fullblockHeight = coinPoolInfo.fullblock; var lastblockHeight = coinPoolInfo.lastblock; var endHeight = fullblockHeight; if (curHeight > lastblockHeight) //如果当前高度大于lastblock 证明lastblock的记录已经完成 把last赋值给full { endHeight = lastblockHeight; } var key_EndHeight = new byte[] { 0x12 }.Concat(endHeight.AsByteArray().Concat(quadZero).Range(0, 4)); var totalMoney_end = Storage.Get(Storage.CurrentContext, key_EndHeight).AsBigInteger(); //获取上一次领奖的块的总系统费 var key_StartHeight = new byte[] { 0x12 }.Concat(((BigInteger)info.block).AsByteArray().Concat(quadZero).Range(0, 4)); //start == end 不领取 if (key_EndHeight == key_StartHeight) { return(info); } var totalMoney_start = Storage.Get(Storage.CurrentContext, key_StartHeight).AsBigInteger(); //(totalMoneyB-totalMoneyA)*info.balance/发行量 就是这个块现在的余额可以领取的分红 var canclaim = (totalMoney_end - totalMoney_start) * balance / totalCoin; info.cancaim += canclaim; info.block = (uint)endHeight; return(info); }
public static bool transfer(byte[] from, byte[] to, BigInteger value) { if (value <= 0) { return(false); } if (from == to) { return(true); } //获得当前块的高度 var height = Blockchain.GetHeight(); //为了保护每个有交易的区块高度都有系统费的值 多了1.x个gas var curMoney = getCurMoney(height); CoinPoolInfo coinPoolInfo = getCoinPoolInfo(); if (curMoney == 0) { curMoney = getCurMoney(coinPoolInfo.lastblock); var bytes_CurHeight = ((BigInteger)height).AsByteArray().Concat(quadZero).Range(0, 4); var key_CurHeight = new byte[] { 0x12 }.Concat(bytes_CurHeight); Storage.Put(Storage.CurrentContext, key_CurHeight, curMoney); //这个地方可以不更新coinpoolinfo的值 不更新没有影响 updateCoinPoolInfo(coinPoolInfo, height); } //付款方 if (from.Length > 0) { var keyFrom = new byte[] { 0x11 }.Concat(from); Info fromInfo = getInfo(from); var from_value = fromInfo.balance; if (from_value < value) { return(false); } fromInfo = updateCanClaim(height, fromInfo, from_value, value); fromInfo.balance = from_value - value; Storage.Put(Storage.CurrentContext, keyFrom, Helper.Serialize(fromInfo)); } //收款方 if (to.Length > 0) { var keyTo = new byte[] { 0x11 }.Concat(to); Info toInfo = getInfo(to); var to_value = toInfo.balance; toInfo = updateCanClaim(height, toInfo, to_value, value); toInfo.balance = to_value + value; Storage.Put(Storage.CurrentContext, keyTo, Helper.Serialize(toInfo)); } //notify Transferred(from, to, value); return(true); }
public static object getTotalMoney(byte[] height) { var key_Height = new byte[] { 0x12 }.Concat(height.Concat(quadZero).Range(0, 4)); var totalmoney = Storage.Get(Storage.CurrentContext, key_Height).AsBigInteger(); if (totalmoney == 0) { CoinPoolInfo coinPoolInfo = getCoinPoolInfo(); var lastblock = coinPoolInfo.lastblock; var key_fullblock = new byte[] { 0x12 }.Concat(lastblock.AsByteArray().Concat(quadZero).Range(0, 4)); totalmoney = Storage.Get(Storage.CurrentContext, key_fullblock).AsBigInteger(); } return(totalmoney); }
private static CoinPoolInfo getCoinPoolInfo() { byte[] data = Storage.Get(Storage.CurrentContext, "CoinPoolInfo"); if (data.Length > 0) { return(Helper.Deserialize(data) as CoinPoolInfo); } else { var coinPoolInfo = new CoinPoolInfo(); coinPoolInfo.fullblock = 0; coinPoolInfo.lastblock = 0; return(coinPoolInfo); } }
/** * 奖池信息查询 **/ public static CoinPoolInfo getCoinPoolInfo(BigInteger coinId) { byte[] key = "coin_".AsByteArray().Concat(coinId.AsByteArray()); byte[] data = Storage.Get(Storage.CurrentContext, key); CoinPoolInfo info = null; if (data.Length > 0) { info = Helper.Deserialize(data) as CoinPoolInfo; } else { info = new CoinPoolInfo(); } info.nowBlock = Blockchain.GetHeight(); return(info); }
/* * 每一个块存储的是目前为止所有收到的系统费用 先判断当前高度大于lastblock的高度 就把lastblock赋值给fullblock lastblock=当前高度 * 如果没有则加上之前的所有费用记录下来 * 如果有记录 就直接+= */ private static bool useGas(byte[] txid) { TransferInfo transferInfo = getTxInfo(txid); if (transferInfo.value <= 0) { return(false); } if (transferInfo.to.AsBigInteger() != ExecutionEngine.ExecutingScriptHash.AsBigInteger()) { return(false); } //获取当前块的高度 uint cur_height = Blockchain.GetHeight(); var bytes_CurHeight = ((BigInteger)cur_height).AsByteArray().Concat(quadZero).Range(0, 4); var key_CurHeight = new byte[] { 0x12 }.Concat(bytes_CurHeight); //先获取当前块所能统计到的总系统费 var curMoney = getCurMoney((BigInteger)cur_height); //获取当前的coinpoolinfo的值 CoinPoolInfo coinPoolInfo = getCoinPoolInfo(); //如果curmoney是0 代表是新高度 总系统费拿coinpool里的lastblock的高度 if (curMoney == 0) { curMoney = getCurMoney(coinPoolInfo.lastblock); //新高度就需要更新coinpool的值 updateCoinPoolInfo(coinPoolInfo, (BigInteger)cur_height); } BigInteger totalMoney = curMoney + transferInfo.value; //记录当前高度的系统费 Storage.Put(Storage.CurrentContext, key_CurHeight, totalMoney); //标记这个txid 已经处理过了 Storage.Put(Storage.CurrentContext, new byte[] { 0x13 }.Concat(txid), 1); //更新coinpoolinfo的值 Storage.Put(Storage.CurrentContext, "CoinPoolInfo", Helper.Serialize(coinPoolInfo)); return(true); }
private static void updateCoinPoolInfo(CoinPoolInfo coinPoolInfo, BigInteger height) { coinPoolInfo.fullblock = coinPoolInfo.lastblock; coinPoolInfo.lastblock = height; Storage.Put(Storage.CurrentContext, "CoinPoolInfo", Helper.Serialize(coinPoolInfo)); }
/** * 购买解禁BPEC */ public static bool transferBPEC(byte[] sender, BigInteger value) { bool bol = false; if (sender.Length != 20 || value <= 0) { Runtime.Log("Owner error."); return(false); } if (Runtime.CheckWitness(sender)) { var height = Blockchain.GetHeight(); CoinPoolInfo coinPoolInfo = getCoinPoolInfo(0); if (coinPoolInfo.coinCode == 0) { coinPoolInfo.coinCode = 1; coinPoolInfo.lastBlock = height; coinPoolInfo.nowBlock = height; coinPoolInfo.nextBlock = height + BASE_BLOCK; coinPoolInfo.coinPool = 0; coinPoolInfo.claimState = 0; coinPoolInfo.claimEnd = 0; } // if (height > coinPoolInfo.nextBlock) { if (coinPoolInfo.claimState == 0) { object[] args = new object[0] { }; object[] res = (object[])bpecCall("getBPECPoolInfo", args); if (res.Length > 0) { BigInteger claimCode = (BigInteger)res[4]; byte[] endAddress = (byte[])res[5]; byte obpecOver = (byte)res[6]; BigInteger coin = 0; object[] args2 = new object[1] { claimCode }; object[] res2 = (object[])bpecCall("getClaimPoolInfo", args2); if (res2.Length > 0) { byte[] endBuyAddress = (byte[])res2[7]; if (coinPoolInfo.claimEnd == 0) { if (obpecOver == 0) { coin = coinPoolInfo.coinPool; coinPoolInfo.claimEnd = 1; coinPoolInfo.winAddress = endAddress; } else { coin = coinPoolInfo.coinPool / 2; coinPoolInfo.winAddress = endBuyAddress; } } else { coin = coinPoolInfo.coinPool / 2; coinPoolInfo.winAddress = endBuyAddress; } //创建保存最新的奖池 CoinPoolInfo coinPoolInfoTemp = new CoinPoolInfo(); coinPoolInfoTemp.coinCode = coinPoolInfo.coinCode + 1; coinPoolInfoTemp.lastBlock = height; coinPoolInfo.nowBlock = height; coinPoolInfoTemp.nextBlock = height + BASE_BLOCK; coinPoolInfoTemp.coinPool = coinPoolInfo.coinPool - coin; coinPoolInfoTemp.claimState = 0; coinPoolInfoTemp.claimEnd = coinPoolInfo.claimEnd; coinPoolInfoTemp.winAddress = endBuyAddress; BigInteger n = 0; var key = "coin_".AsByteArray().Concat(n.AsByteArray()); Storage.Put(Storage.CurrentContext, key, Helper.Serialize(coinPoolInfoTemp)); //分离奖池并开奖 coinPoolInfo.claimState = 1; coinPoolInfo.coinPool = coinPoolInfoTemp.coinPool; byte[] key2 = "coin_".AsByteArray().Concat(coinPoolInfo.coinCode.AsByteArray()); Storage.Put(Storage.CurrentContext, key2, Helper.Serialize(coinPoolInfo)); //发放奖励 UserInfo userInfo = getUserInfo(coinPoolInfo.winAddress); userInfo.balance += coin; var keyWho = new byte[] { 0x11 }.Concat(coinPoolInfo.winAddress); Storage.Put(Storage.CurrentContext, keyWho, Helper.Serialize(userInfo)); //notify TransferBPECed(2, sender, coinPoolInfo.coinPool, coinPoolInfo.coinCode); bol = true; } } } } else { BigInteger cgas = value * CGAS_CLAIM_RATE / 100; BigInteger claimV = cgas * CLAIM_RATE / 100; BigInteger coinV = cgas * COIN_RATE / 100; BigInteger feeV = cgas - claimV - coinV; UserInfo userInfo = getUserInfo(sender); if (userInfo.balance >= cgas) { object[] args = new object[4] { sender, 2, value, claimV }; bool res = (bool)bpecCall("transferOpen", args); if (res) { // _subTotal(feeV); // coinPoolInfo.coinPool += coinV; coinPoolInfo.nextBlock += ADD_BLOCK; coinPoolInfo.nowBlock = height; //判断最大值 if (height > coinPoolInfo.nextBlock) { coinPoolInfo.nextBlock = coinPoolInfo.lastBlock + MAX_BLOCK; } BigInteger n = 0; var key = "coin_".AsByteArray().Concat(n.AsByteArray()); Storage.Put(Storage.CurrentContext, key, Helper.Serialize(coinPoolInfo)); // userInfo.balance -= cgas; var keyWho = new byte[] { 0x11 }.Concat(sender); Storage.Put(Storage.CurrentContext, keyWho, Helper.Serialize(userInfo)); bol = true; } } if (bol == true) { TransferBPECed(1, sender, value, coinPoolInfo.coinCode); } else { TransferBPECed(0, sender, value, coinPoolInfo.coinCode); } } } return(bol); }