Skip to content

Commit

Permalink
Merge pull request #4758 from tronprotocol/feature/memo_fee
Browse files Browse the repository at this point in the history
feat(memo-fee): add a proposal for memo fee
  • Loading branch information
zhang0125 authored Nov 3, 2022
2 parents e0a910e + 8a3877b commit 1e952f3
Show file tree
Hide file tree
Showing 12 changed files with 165 additions and 4 deletions.
14 changes: 13 additions & 1 deletion actuator/src/main/java/org/tron/core/utils/ProposalUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -575,6 +575,17 @@ public static void validator(DynamicPropertiesStore dynamicPropertiesStore,
}
break;
}
case MEMO_FEE: {
if (!forkController.pass(ForkBlockVersionEnum.VERSION_4_6)) {
throw new ContractValidateException(
"Bad chain parameter id [MEMO_FEE]");
}
if (value < 0 || value > 1_000_000_000) {
throw new ContractValidateException(
"This value[MEMO_FEE] is only allowed to be in the range 0-1000_000_000");
}
break;
}
default:
break;
}
Expand Down Expand Up @@ -639,7 +650,8 @@ public enum ProposalType { // current value, value range
ALLOW_TVM_LONDON(63), // 0, 1
ALLOW_HIGHER_LIMIT_FOR_MAX_CPU_TIME_OF_ONE_TX(65), // 0, 1
ALLOW_ASSET_OPTIMIZATION(66), // 0, 1
ALLOW_NEW_REWARD_ALGO(67); // 0, 1
ALLOW_NEW_REWARD_ALGO(67), // 0, 1
MEMO_FEE(68); // 0, [1, 1000_000_000]

private long code;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ public class ReceiptCapsule {
@Setter
private long multiSignFee;

@Getter
@Setter
private long memoFee;
/**
* Available energy of contract deployer before executing transaction
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,9 +72,9 @@ public static TransactionInfoCapsule buildTransactionInfoInstance(TransactionCap
}
builder.setId(ByteString.copyFrom(trxCap.getTransactionId().getBytes()));
ProgramResult programResult = trace.getRuntimeResult();
long fee =
programResult.getRet().getFee() + traceReceipt.getEnergyFee()
+ traceReceipt.getNetFee() + traceReceipt.getMultiSignFee();
long fee = programResult.getRet().getFee() + traceReceipt.getEnergyFee()
+ traceReceipt.getNetFee() + traceReceipt.getMultiSignFee()
+ traceReceipt.getMemoFee();

boolean supportTransactionFeePool = trace.getTransactionContext().getStoreFactory()
.getChainBaseManager().getDynamicPropertiesStore().supportTransactionFeePool();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,9 @@ public class DynamicPropertiesStore extends TronStoreWithRevoking<BytesCapsule>
private static final byte[] ALLOW_HIGHER_LIMIT_FOR_MAX_CPU_TIME_OF_ONE_TX =
"ALLOW_HIGHER_LIMIT_FOR_MAX_CPU_TIME_OF_ONE_TX".getBytes();

private static final byte[] MEMO_FEE = "MEMO_FEE".getBytes();
private static final byte[] MEMO_FEE_HISTORY = "MEMO_FEE_HISTORY".getBytes();

@Autowired
private DynamicPropertiesStore(@Value("properties") String dbName) {
super(dbName);
Expand Down Expand Up @@ -857,6 +860,14 @@ private DynamicPropertiesStore(@Value("properties") String dbName) {
new BytesCapsule(ByteArray.fromLong(Long.MAX_VALUE)));
}
}

try {
this.getMemoFee();
} catch (IllegalArgumentException e) {
long memoFee = CommonParameter.getInstance().getMemoFee();
this.saveMemoFee(memoFee);
this.saveMemoFeeHistory("0:" + memoFee);
}
}

public String intArrayToString(int[] a) {
Expand Down Expand Up @@ -2528,6 +2539,28 @@ public long getAllowHigherLimitForMaxCpuTimeOfOneTx() {
() -> new IllegalArgumentException(msg));
}

public long getMemoFee() {
return Optional.ofNullable(getUnchecked(MEMO_FEE))
.map(BytesCapsule::getData)
.map(ByteArray::toLong)
.orElseThrow(() -> new IllegalArgumentException("not found MEMO_FEE"));
}

public void saveMemoFee(long value) {
this.put(MEMO_FEE, new BytesCapsule(ByteArray.fromLong(value)));
}

public String getMemoFeeHistory() {
return Optional.ofNullable(getUnchecked(MEMO_FEE_HISTORY))
.map(BytesCapsule::getData)
.map(ByteArray::toStr)
.orElseThrow(() -> new IllegalArgumentException("not found MEMO_FEE_HISTORY"));
}

public void saveMemoFeeHistory(String value) {
this.put(MEMO_FEE_HISTORY, new BytesCapsule(ByteArray.fromString(value)));
}

private static class DynamicResourceProperties {

private static final byte[] ONE_DAY_NET_LIMIT = "ONE_DAY_NET_LIMIT".getBytes();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -561,6 +561,10 @@ public class CommonParameter {
@Setter
public long allowNewRewardAlgorithm;

@Getter
@Setter
public long memoFee = 0L;

private static double calcMaxTimeRatio() {
//return max(2.0, min(5.0, 5 * 4.0 / max(Runtime.getRuntime().availableProcessors(), 1)));
return 5.0;
Expand Down
1 change: 1 addition & 0 deletions common/src/main/java/org/tron/core/Constant.java
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,7 @@ public class Constant {

public static final String ALLOW_ACCOUNT_ASSET_OPTIMIZATION = "committee.allowAccountAssetOptimization";
public static final String ALLOW_ASSET_OPTIMIZATION = "committee.allowAssetOptimization";
public static final String MEMO_FEE = "committee.memoFee";

public static final String LOCAL_HOST = "127.0.0.1";

Expand Down
13 changes: 13 additions & 0 deletions framework/src/main/java/org/tron/core/Wallet.java
Original file line number Diff line number Diff line change
Expand Up @@ -1103,6 +1103,11 @@ public Protocol.ChainParameters getChainParameters() {
.setValue(dbManager.getDynamicPropertiesStore().useNewRewardAlgorithm() ? 1 : 0)
.build());

builder.addChainParameter(Protocol.ChainParameters.ChainParameter.newBuilder()
.setKey("getMemoFee")
.setValue(dbManager.getDynamicPropertiesStore().getMemoFee())
.build());

return builder.build();
}

Expand Down Expand Up @@ -4080,5 +4085,13 @@ public Block getBlock(GrpcAPI.BlockReq request) {
return block.toBuilder().clearTransactions().build();
}

public String getMemoFeePrices() {
try {
return chainBaseManager.getDynamicPropertiesStore().getMemoFeeHistory();
} catch (Exception e) {
logger.error("getMemoFeePrices failed, error is {}", e.getMessage());
}
return null;
}
}

10 changes: 10 additions & 0 deletions framework/src/main/java/org/tron/core/config/args/Args.java
Original file line number Diff line number Diff line change
Expand Up @@ -1034,6 +1034,16 @@ public static void setParam(final String[] args, final String confFileName) {
PARAMETER.blockCacheTimeout = config.getLong(Constant.BLOCK_CACHE_TIMEOUT);
}

if (config.hasPath(Constant.MEMO_FEE)) {
PARAMETER.memoFee = config.getLong(Constant.MEMO_FEE);
if (PARAMETER.memoFee > 1_000_000_000) {
PARAMETER.memoFee = 1_000_000_000;
}
if (PARAMETER.memoFee < 0) {
PARAMETER.memoFee = 0;
}
}

logConfig();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,14 @@ public static boolean process(Manager manager, ProposalCapsule proposalCapsule)
manager.getDynamicPropertiesStore().saveNewRewardAlgorithmEffectiveCycle();
break;
}
case MEMO_FEE: {
manager.getDynamicPropertiesStore().saveMemoFee(entry.getValue());
// update memo fee history
manager.getDynamicPropertiesStore().saveMemoFeeHistory(
manager.getDynamicPropertiesStore().getMemoFeeHistory()
+ "," + proposalCapsule.getExpirationTime() + ":" + entry.getValue());
break;
}
default:
find = false;
break;
Expand Down
37 changes: 37 additions & 0 deletions framework/src/main/java/org/tron/core/db/Manager.java
Original file line number Diff line number Diff line change
Expand Up @@ -855,6 +855,42 @@ public void consumeMultiSignFee(TransactionCapsule trx, TransactionTrace trace)
}
}

public void consumeMemoFee(TransactionCapsule trx, TransactionTrace trace)
throws AccountResourceInsufficientException {
if (trx.getInstance().getRawData().getData().isEmpty()) {
// no memo
return;
}

long fee = getDynamicPropertiesStore().getMemoFee();
if (fee == 0) {
return;
}

List<Contract> contracts = trx.getInstance().getRawData().getContractList();
for (Contract contract : contracts) {
byte[] address = TransactionCapsule.getOwner(contract);
AccountCapsule accountCapsule = getAccountStore().get(address);
try {
if (accountCapsule != null) {
adjustBalance(getAccountStore(), accountCapsule, -fee);

if (getDynamicPropertiesStore().supportBlackHoleOptimization()) {
getDynamicPropertiesStore().burnTrx(fee);
} else {
adjustBalance(getAccountStore(), this.getAccountStore().getBlackhole(), +fee);
}
}
} catch (BalanceInsufficientException e) {
throw new AccountResourceInsufficientException(
String.format("account %s insufficient balance[%d] to memo fee",
StringUtil.encode58Check(address), fee));
}
}

trace.getReceipt().setMemoFee(fee);
}

public void consumeBandwidth(TransactionCapsule trx, TransactionTrace trace)
throws ContractValidateException, AccountResourceInsufficientException,
TooBigTransactionResultException {
Expand Down Expand Up @@ -1338,6 +1374,7 @@ public TransactionInfo processTransaction(final TransactionCapsule trxCap, Block

consumeBandwidth(trxCap, trace);
consumeMultiSignFee(trxCap, trace);
consumeMemoFee(trxCap, trace);

trace.init(blockCap, eventPluginLoaded);
trace.checkIsConstant();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,8 @@ public class FullNodeHttpApiService implements Service {
private GetBandwidthPricesServlet getBandwidthPricesServlet;
@Autowired
private GetBlockServlet getBlockServlet;
@Autowired
private GetMemoFeePricesServlet getMemoFeePricesServlet;

private static String getParamsFile(String fileName) {
InputStream in = Thread.currentThread().getContextClassLoader()
Expand Down Expand Up @@ -542,6 +544,7 @@ public void start() {
context.addServlet(new ServletHolder(getBandwidthPricesServlet),
"/wallet/getbandwidthprices");
context.addServlet(new ServletHolder(getBlockServlet), "/wallet/getblock");
context.addServlet(new ServletHolder(getMemoFeePricesServlet), "/wallet/getmemofee");

int maxHttpConnectNumber = Args.getInstance().getMaxHttpConnectNumber();
if (maxHttpConnectNumber > 0) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package org.tron.core.services.http;

import com.alibaba.fastjson.JSONObject;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.tron.core.Wallet;


@Component
@Slf4j(topic = "API")
public class GetMemoFeePricesServlet extends RateLimiterServlet {

@Autowired
private Wallet wallet;

protected void doGet(HttpServletRequest request, HttpServletResponse response) {
try {
String reply = wallet.getMemoFeePrices();
if (reply != null) {
JSONObject jsonObject = new JSONObject();
jsonObject.put("prices", reply);
response.getWriter().println(jsonObject);
} else {
response.getWriter().println("{}");
}
} catch (Exception e) {
Util.processError(e, response);
}
}

protected void doPost(HttpServletRequest request, HttpServletResponse response) {
doGet(request, response);
}
}

0 comments on commit 1e952f3

Please sign in to comment.