Esempio n. 1
0
        public override ConsumedResourceTokens ChargeResourceToken(ChargeResourceTokenInput input)
        {
            var consumedResourceTokens = new ConsumedResourceTokens();

            Context.LogDebug(() => $"Start executing ChargeResourceToken.{input}");
            if (input.Equals(new ChargeResourceTokenInput()))
            {
                return(consumedResourceTokens);
            }

            var symbolToAmount = new Dictionary <string, long>
            {
                { "READ", input.ReadCost },
                { "TRAFFIC", input.TrafficCost },
                { "STORAGE", input.StorageCost },
                { "WRITE", input.WriteCost }
            };

            var bill = new TransactionFeeBill();

            foreach (var pair in symbolToAmount)
            {
                Context.LogDebug(() => $"Charging {pair.Value} {pair.Key} tokens.");
                var existingBalance = State.Balances[Context.Sender][pair.Key];
                if (existingBalance < pair.Value)
                {
                    bill.TokenToAmount.Add(pair.Key, existingBalance);
                    var owningBalance = State.OwningResourceToken[Context.Sender][pair.Key]
                                        .Add(pair.Value.Sub(existingBalance));
                    State.OwningResourceToken[Context.Sender][pair.Key] = owningBalance;

                    consumedResourceTokens.IsFailedToCharge = true;
                    consumedResourceTokens.Owning.Add(pair.Key, owningBalance);

                    Context.LogDebug(() => $"Insufficient resource. {pair.Key}: {existingBalance} / {pair.Value}");
                }
                else
                {
                    bill.TokenToAmount.Add(pair.Key, pair.Value);
                }
            }

            foreach (var pair in bill.TokenToAmount)
            {
                State.ChargedResourceTokens[input.Caller][Context.Sender][pair.Key] =
                    State.ChargedResourceTokens[input.Caller][Context.Sender][pair.Key].Add(pair.Value);
                consumedResourceTokens.Value.Add(pair.Key, pair.Value);
            }

            Context.LogDebug(() => $"Finished executing ChargeResourceToken.{consumedResourceTokens}");

            return(consumedResourceTokens);
        }
Esempio n. 2
0
        private async Task <bool> ExecutePluginOnPostTransactionStageAsync(IExecutive executive,
                                                                           ITransactionContext txContext,
                                                                           Timestamp currentBlockTime,
                                                                           IChainContext internalChainContext,
                                                                           TieredStateCache internalStateCache,
                                                                           CancellationToken cancellationToken)
        {
            var trace = txContext.Trace;

            if (!trace.IsSuccessful())
            {
                internalStateCache = new TieredStateCache(txContext.StateCache);
                foreach (var preTrace in txContext.Trace.PreTraces)
                {
                    var stateSets = preTrace.GetStateSets();
                    internalStateCache.Update(stateSets);
                }

                internalChainContext.StateCache = internalStateCache;
            }

            foreach (var plugin in _postPlugins)
            {
                var transactions = await plugin.GetPostTransactionsAsync(executive.Descriptors, txContext);

                foreach (var postTx in transactions)
                {
                    var singleTxExecutingDto = new SingleTransactionExecutingDto
                    {
                        Depth            = 0,
                        ChainContext     = internalChainContext,
                        Transaction      = postTx,
                        CurrentBlockTime = currentBlockTime
                    };
                    var postTrace = await ExecuteOneAsync(singleTxExecutingDto, cancellationToken);

                    if (postTrace == null)
                    {
                        return(false);
                    }
                    trace.PostTransactions.Add(postTx);
                    trace.PostTraces.Add(postTrace);

                    if (postTx.MethodName == "ChargeResourceToken")
                    {
                        var consumedResourceTokens = new ConsumedResourceTokens();
                        consumedResourceTokens.MergeFrom(postTrace.ReturnValue);
                        trace.ConsumedResourceTokens = consumedResourceTokens;
                    }

                    if (!postTrace.IsSuccessful())
                    {
                        return(false);
                    }

                    internalStateCache.Update(postTrace.GetStateSets());
                }
            }

            return(true);
        }