示例#1
0
 private void PayTransactionFee(TotalResourceTokensMaps billMaps, bool isMainChain)
 {
     foreach (var bill in billMaps.Value)
     {
         foreach (var feeMap in bill.TokensMap.Value)
         {
             if (feeMap.Value > 0)
             {
                 ModifyBalance(bill.ContractAddress, feeMap.Key, -feeMap.Value);
                 if (isMainChain)
                 {
                     Context.LogDebug(() => $"Adding {feeMap.Value} of {feeMap.Key}s to dividend pool.");
                     // Main Chain.
                     ModifyBalance(Context.Self, feeMap.Key, feeMap.Value);
                     State.TreasuryContract.Donate.Send(new DonateInput
                     {
                         Symbol = feeMap.Key,
                         Amount = feeMap.Value
                     });
                 }
                 else
                 {
                     Context.LogDebug(() => $"Adding {feeMap.Value} of {feeMap.Key}s to consensus address account.");
                     // Side Chain
                     var consensusContractAddress =
                         Context.GetContractAddressByName(SmartContractConstants.ConsensusContractSystemName);
                     ModifyBalance(consensusContractAddress, feeMap.Key, feeMap.Value);
                 }
             }
         }
     }
 }
示例#2
0
        public override Empty DonateResourceToken(TotalResourceTokensMaps input)
        {
            Context.LogDebug(() => $"Start donate resource token. {input}");
            State.LatestTotalResourceTokensMapsHash.Value = Hash.FromMessage(input);
            var isMainChain = true;

            if (State.TreasuryContract.Value == null)
            {
                var treasuryContractAddress =
                    Context.GetContractAddressByName(SmartContractConstants.TreasuryContractSystemName);
                if (treasuryContractAddress == null)
                {
                    isMainChain = false;
                }
                else
                {
                    State.TreasuryContract.Value = treasuryContractAddress;
                }
            }

            PayTransactionFee(input, isMainChain);

            if (!isMainChain)
            {
                PayRental();
            }

            return(new Empty());
        }
示例#3
0
        public async Task <List <Transaction> > GenerateTransactionsAsync(Address @from, long preBlockHeight,
                                                                          Hash preBlockHash)
        {
            var generatedTransactions = new List <Transaction>();

            var chainContext = new ChainContext
            {
                BlockHash   = preBlockHash,
                BlockHeight = preBlockHeight
            };

            var tokenContractAddress =
                await _smartContractAddressService.GetAddressByContractNameAsync(chainContext,
                                                                                 TokenSmartContractAddressNameProvider.StringName);

            if (tokenContractAddress == null)
            {
                return(generatedTransactions);
            }

            var totalResourceTokensMaps = await _totalResourceTokensMapsProvider.GetTotalResourceTokensMapsAsync(
                chainContext);

            ByteString input;

            if (totalResourceTokensMaps != null && totalResourceTokensMaps.BlockHeight == preBlockHeight &&
                totalResourceTokensMaps.BlockHash == preBlockHash)
            {
                // If totalResourceTokensMaps match current block.
                input = totalResourceTokensMaps.ToByteString();
            }
            else
            {
                input = new TotalResourceTokensMaps
                {
                    BlockHash   = preBlockHash,
                    BlockHeight = preBlockHeight
                }.ToByteString();
            }

            generatedTransactions.AddRange(new List <Transaction>
            {
                new Transaction
                {
                    From           = from,
                    MethodName     = nameof(TokenContractImplContainer.TokenContractImplStub.DonateResourceToken),
                    To             = tokenContractAddress,
                    RefBlockNumber = preBlockHeight,
                    RefBlockPrefix = BlockHelper.GetRefBlockPrefix(preBlockHash),
                    Params         = input
                }
            });

            Logger.LogTrace("Tx DonateResourceToken generated.");
            return(generatedTransactions);
        }
示例#4
0
        public override async Task ProcessAsync(Block block, Dictionary <TransactionResult, List <LogEvent> > logEventsMap)
        {
            var blockHash               = block.GetHash();
            var blockHeight             = block.Height;
            var totalResourceTokensMaps = new TotalResourceTokensMaps
            {
                BlockHash   = blockHash,
                BlockHeight = blockHeight
            };

            foreach (var logEvent in logEventsMap.Values.SelectMany(logEvents => logEvents))
            {
                var eventData = new ResourceTokenCharged();
                eventData.MergeFrom(logEvent);
                if (eventData.Symbol == null || eventData.Amount == 0)
                {
                    continue;
                }

                if (totalResourceTokensMaps.Value.Any(b => b.ContractAddress == eventData.ContractAddress))
                {
                    var oldBill =
                        totalResourceTokensMaps.Value.First(b => b.ContractAddress == eventData.ContractAddress);
                    if (oldBill.TokensMap.Value.ContainsKey(eventData.Symbol))
                    {
                        oldBill.TokensMap.Value[eventData.Symbol] += eventData.Amount;
                    }
                    else
                    {
                        oldBill.TokensMap.Value.Add(eventData.Symbol, eventData.Amount);
                    }
                }
                else
                {
                    var contractTotalResourceTokens = new ContractTotalResourceTokens
                    {
                        ContractAddress = eventData.ContractAddress,
                        TokensMap       = new TotalResourceTokensMap
                        {
                            Value =
                            {
                                { eventData.Symbol, eventData.Amount }
                            }
                        }
                    };
                    totalResourceTokensMaps.Value.Add(contractTotalResourceTokens);
                }
            }

            await _totalTotalResourceTokensMapsProvider.SetTotalResourceTokensMapsAsync(new BlockIndex
            {
                BlockHash   = blockHash,
                BlockHeight = blockHeight
            }, totalResourceTokensMaps);
        }
示例#5
0
        private void PayResourceTokens(TotalResourceTokensMaps billMaps, bool isMainChain)
        {
            foreach (var bill in billMaps.Value)
            {
                foreach (var feeMap in bill.TokensMap.Value)
                {
                    var symbol = feeMap.Key;
                    var amount = feeMap.Value;
                    // Check balance in case of insufficient balance.
                    var existingBalance = GetBalance(bill.ContractAddress, symbol);
                    if (amount > existingBalance)
                    {
                        var owned         = amount.Sub(existingBalance);
                        var currentOwning = State.OwningResourceToken[bill.ContractAddress][symbol].Add(owned);
                        State.OwningResourceToken[bill.ContractAddress][symbol] = currentOwning;
                        Context.Fire(new ResourceTokenOwned
                        {
                            Symbol          = symbol,
                            Amount          = currentOwning,
                            ContractAddress = bill.ContractAddress
                        });
                        amount = existingBalance;
                    }

                    if (amount > 0)
                    {
                        ModifyBalance(bill.ContractAddress, symbol, -amount);
                        if (isMainChain)
                        {
                            Context.LogDebug(() => $"Adding {amount} of {symbol}s to dividend pool.");
                            // Main Chain.
                            ModifyBalance(Context.Self, symbol, amount);
                            State.DividendPoolContract.Donate.Send(new DonateInput
                            {
                                Symbol = symbol,
                                Amount = amount
                            });
                        }
                        else
                        {
                            Context.LogDebug(() => $"Adding {amount} of {symbol}s to consensus address account.");
                            // Side Chain
                            var consensusContractAddress =
                                Context.GetContractAddressByName(SmartContractConstants.ConsensusContractSystemName);
                            ModifyBalance(consensusContractAddress, symbol, amount);
                        }
                    }
                }
            }
        }
示例#6
0
        public async Task DonateResourceToken_Test(long[] initialBalances, long[] tokenFee, long[] lastBalances,
                                                   bool isMainChain)
        {
            var symbolList = new [] { "WEO", "CWJ", "YPA" };
            var feeMap     = new TotalResourceTokensMaps();

            for (var i = 0; i < symbolList.Length; i++)
            {
                await CreateTokenAsync(DefaultSender, symbolList[i]);
                await IssueTokenAsync(symbolList[i], initialBalances[i]);

                feeMap.Value.Add(new ContractTotalResourceTokens
                {
                    ContractAddress = DefaultSender,
                    TokensMap       = new TotalResourceTokensMap
                    {
                        Value = { { symbolList[i], tokenFee[i] } }
                    }
                });
            }

            if (!isMainChain)
            {
                var defaultParliament = await ParliamentContractStub.GetDefaultOrganizationAddress.CallAsync(new Empty());
                await SubmitAndPassProposalOfDefaultParliamentAsync(TokenContractAddress,
                                                                    nameof(TokenContractContainer.TokenContractStub.InitializeFromParentChain),
                                                                    new InitializeFromParentChainInput
                {
                    Creator = defaultParliament
                });
            }
            await TokenContractStub.DonateResourceToken.SendAsync(feeMap);

            for (var i = 0; i < symbolList.Length; i++)
            {
                var balance = await GetBalanceAsync(DefaultSender, symbolList[i]);

                balance.ShouldBe(lastBalances[i]);
                if (!isMainChain)
                {
                    var consensusBalance = await GetBalanceAsync(ConsensusContractAddress, symbolList[i]);

                    consensusBalance.ShouldBe(initialBalances[i] - lastBalances[i]);
                }
            }
        }
示例#7
0
        public override Empty DonateResourceToken(TotalResourceTokensMaps input)
        {
            AssertSenderIsCurrentMiner();
            var donateResourceTokenExecuteHeight = State.DonateResourceTokenExecuteHeight.Value;

            if (donateResourceTokenExecuteHeight == 0)
            {
                donateResourceTokenExecuteHeight = Context.CurrentHeight;
            }

            Assert(donateResourceTokenExecuteHeight == Context.CurrentHeight,
                   $"This method already executed in height {State.DonateResourceTokenExecuteHeight.Value}");
            State.DonateResourceTokenExecuteHeight.Value = donateResourceTokenExecuteHeight.Add(1);
            Context.LogDebug(() => $"Start donate resource token. {input}");
            State.LatestTotalResourceTokensMapsHash.Value = HashHelper.ComputeFrom(input);
            Context.LogDebug(() =>
                             $"Now LatestTotalResourceTokensMapsHash is {State.LatestTotalResourceTokensMapsHash.Value}");

            var isMainChain = true;

            if (State.DividendPoolContract.Value == null)
            {
                var treasuryContractAddress =
                    Context.GetContractAddressByName(SmartContractConstants.TreasuryContractSystemName);
                if (treasuryContractAddress == null)
                {
                    isMainChain = false;
                }
                else
                {
                    State.DividendPoolContract.Value = treasuryContractAddress;
                }
            }

            PayResourceTokens(input, isMainChain);

            if (!isMainChain)
            {
                PayRental();
            }

            return(new Empty());
        }
示例#8
0
        public async Task ProcessAsync(Block block, TransactionResult transactionResult, LogEvent logEvent)
        {
            var eventData = new ResourceTokenCharged();

            eventData.MergeFrom(logEvent);
            if (eventData.Symbol == null || eventData.Amount == 0)
            {
                return;
            }

            var blockHash   = block.GetHash();
            var blockHeight = block.Height;
            // TODO: Get -> Modify -> Set is slow, consider collect all logEvents then generate the totalResourceTokensMap at once.
            var totalResourceTokensMaps =
                await _totalTotalResourceTokensMapsProvider.GetTotalResourceTokensMapsAsync(
                    new ChainContext
            {
                BlockHash   = block.GetHash(),
                BlockHeight = block.Height,
            });

            // Initial totalTxFeesMap if necessary (either never initialized or not initialized for current block link)
            if (totalResourceTokensMaps == null)
            {
                totalResourceTokensMaps = new TotalResourceTokensMaps
                {
                    BlockHash   = blockHash,
                    BlockHeight = blockHeight
                };
            }
            else if (totalResourceTokensMaps.BlockHash != blockHash || totalResourceTokensMaps.BlockHeight != blockHeight)
            {
                totalResourceTokensMaps = new TotalResourceTokensMaps
                {
                    BlockHash   = blockHash,
                    BlockHeight = blockHeight
                };
            }

            if (totalResourceTokensMaps.Value.Any() &&
                totalResourceTokensMaps.Value.Any(b => b.ContractAddress == eventData.ContractAddress))
            {
                var oldBill = totalResourceTokensMaps.Value.First(b => b.ContractAddress == eventData.ContractAddress);
                if (oldBill.TokensMap.Value.ContainsKey(eventData.Symbol))
                {
                    oldBill.TokensMap.Value[eventData.Symbol] += eventData.Amount;
                }
                else
                {
                    oldBill.TokensMap.Value.Add(eventData.Symbol, eventData.Amount);
                }
            }
            else
            {
                var contractTotalResourceTokens = new ContractTotalResourceTokens
                {
                    ContractAddress = eventData.ContractAddress,
                    TokensMap       = new TotalResourceTokensMap
                    {
                        Value =
                        {
                            { eventData.Symbol, eventData.Amount }
                        }
                    }
                };
                totalResourceTokensMaps.Value.Add(contractTotalResourceTokens);
            }

            await _totalTotalResourceTokensMapsProvider.SetTotalResourceTokensMapsAsync(new BlockIndex
            {
                BlockHash   = blockHash,
                BlockHeight = blockHeight
            }, totalResourceTokensMaps);
        }