Skip to content

feat(transaction): optimize transactions during the consensus phase #6172

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions chainbase/src/main/java/org/tron/core/ChainBaseManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -380,6 +380,15 @@ public static synchronized void init(ChainBaseManager manager) {
AssetUtil.setDynamicPropertiesStore(manager.getDynamicPropertiesStore());
}

public long getNextBlockSlotTime() {
long slotCount = 1;
if (dynamicPropertiesStore.getStateFlag() == 1) {
slotCount += dynamicPropertiesStore.getMaintenanceSkipSlots();
}
return dynamicPropertiesStore.getLatestBlockHeaderTimestamp()
+ slotCount * BLOCK_PRODUCED_INTERVAL;
}

@PostConstruct
private void init() {
this.lowestBlockNum = this.blockIndexStore.getLimitNumber(1, 1).stream()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,9 @@ public void consume(TransactionCapsule trx, TransactionTrace trace)
TooBigTransactionResultException, TooBigTransactionException {
List<Contract> contracts = trx.getInstance().getRawData().getContractList();
long resultSizeWithMaxContractRet = trx.getResultSizeWithMaxContractRet();
if (!trx.isInBlock() && resultSizeWithMaxContractRet >
boolean optimizeTxs = !trx.isInBlock() || chainBaseManager
.getDynamicPropertiesStore().allowConsensusLogicOptimization();
if (optimizeTxs && resultSizeWithMaxContractRet >
Constant.MAX_RESULT_SIZE_IN_TX * contracts.size()) {
throw new TooBigTransactionResultException(String.format(
"Too big transaction result, TxId %s, the result size is %d bytes, maxResultSize %d",
Expand Down Expand Up @@ -135,7 +137,7 @@ public void consume(TransactionCapsule trx, TransactionTrace trace)
}
long now = chainBaseManager.getHeadSlot();
if (contractCreateNewAccount(contract)) {
if (!trx.isInBlock()) {
if (optimizeTxs) {
long maxCreateAccountTxSize = dynamicPropertiesStore.getMaxCreateAccountTxSize();
int signatureCount = trx.getInstance().getSignatureCount();
long createAccountBytesSize = trx.getInstance().toBuilder().clearRet()
Expand Down
2 changes: 1 addition & 1 deletion framework/src/main/java/org/tron/core/Wallet.java
Original file line number Diff line number Diff line change
Expand Up @@ -549,7 +549,7 @@ public GrpcAPI.Return broadcastTransaction(Transaction signedTransaction) {
throw new ContractValidateException(ActuatorConstant.CONTRACT_NOT_EXIST);
}
TransactionMessage message = new TransactionMessage(trx.getInstance().toByteArray());
trx.checkExpiration(tronNetDelegate.getNextBlockSlotTime());
trx.checkExpiration(chainBaseManager.getNextBlockSlotTime());
dbManager.pushTransaction(trx);
int num = tronNetService.fastBroadcastTransaction(message);
if (num == 0 && minEffectiveConnection != 0) {
Expand Down
8 changes: 7 additions & 1 deletion framework/src/main/java/org/tron/core/db/Manager.java
Original file line number Diff line number Diff line change
Expand Up @@ -794,7 +794,9 @@ void validateTapos(TransactionCapsule transactionCapsule) throws TaposException

void validateCommon(TransactionCapsule transactionCapsule)
throws TransactionExpirationException, TooBigTransactionException {
if (!transactionCapsule.isInBlock()) {
boolean optimizeTxs = !transactionCapsule.isInBlock() || chainBaseManager
.getDynamicPropertiesStore().allowConsensusLogicOptimization();
if (optimizeTxs) {
transactionCapsule.removeRedundantRet();
long generalBytesSize =
transactionCapsule.getInstance().toBuilder().clearRet().build().getSerializedSize()
Expand All @@ -813,6 +815,10 @@ void validateCommon(TransactionCapsule transactionCapsule)
}
long transactionExpiration = transactionCapsule.getExpiration();
long headBlockTime = chainBaseManager.getHeadBlockTimeStamp();
if (transactionCapsule.isInBlock()
&& chainBaseManager.getDynamicPropertiesStore().allowConsensusLogicOptimization()) {
transactionCapsule.checkExpiration(chainBaseManager.getNextBlockSlotTime());
}
if (transactionExpiration <= headBlockTime
|| transactionExpiration > headBlockTime + Constant.MAXIMUM_TIME_UNTIL_EXPIRATION) {
throw new TransactionExpirationException(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -380,12 +380,4 @@ public boolean isBlockUnsolidified() {
return headNum - solidNum >= maxUnsolidifiedBlocks;
}

public long getNextBlockSlotTime() {
long slotCount = 1;
if (chainBaseManager.getDynamicPropertiesStore().getStateFlag() == 1) {
slotCount += chainBaseManager.getDynamicPropertiesStore().getMaintenanceSkipSlots();
}
return chainBaseManager.getDynamicPropertiesStore().getLatestBlockHeaderTimestamp()
+ slotCount * BLOCK_PRODUCED_INTERVAL;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.tron.common.es.ExecutorServiceManager;
import org.tron.core.ChainBaseManager;
import org.tron.core.config.args.Args;
import org.tron.core.exception.P2pException;
import org.tron.core.exception.P2pException.TypeEnum;
Expand All @@ -36,6 +37,8 @@ public class TransactionsMsgHandler implements TronMsgHandler {
private TronNetDelegate tronNetDelegate;
@Autowired
private AdvService advService;
@Autowired
private ChainBaseManager chainBaseManager;

private BlockingQueue<TrxEvent> smartContractQueue = new LinkedBlockingQueue(MAX_TRX_SIZE);

Expand Down Expand Up @@ -129,7 +132,7 @@ private void handleTransaction(PeerConnection peer, TransactionMessage trx) {
}

try {
trx.getTransactionCapsule().checkExpiration(tronNetDelegate.getNextBlockSlotTime());
trx.getTransactionCapsule().checkExpiration(chainBaseManager.getNextBlockSlotTime());
tronNetDelegate.pushTransaction(trx.getTransactionCapsule());
advService.broadcast(trx);
} catch (P2pException e) {
Expand Down
24 changes: 24 additions & 0 deletions framework/src/test/java/org/tron/core/db/ManagerTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -1160,6 +1160,30 @@ public void testTooBigTransaction() {

}

@Test
public void testExpiration() {
dbManager.getDynamicPropertiesStore().saveConsensusLogicOptimization(1);
TransferContract transferContract =
TransferContract.newBuilder()
.setAmount(10)
.setOwnerAddress(ByteString.copyFromUtf8("aaa"))
.setToAddress(ByteString.copyFromUtf8("bbb"))
.build();
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 100; i++) {
sb.append("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
}
Transaction transaction = Transaction.newBuilder().setRawData(Transaction.raw.newBuilder()
.setData(ByteString.copyFrom(sb.toString().getBytes(StandardCharsets.UTF_8)))
.addContract(Transaction.Contract.newBuilder().setParameter(Any.pack(transferContract))
.setType(ContractType.TransferContract))).build();
TransactionCapsule trx = new TransactionCapsule(transaction);
trx.setInBlock(true);

assertThrows(TransactionExpirationException.class, () -> dbManager.validateCommon(trx));

}

@Test
public void blockTrigger() {
exit.expectSystemExitWithStatus(1);
Expand Down