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); }
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); }