Skip to content

Commit fcae37a

Browse files
authored
Merge pull request tronprotocol#5839 from zeusoo001/feature/remove_redundant_ret
feat(*): remove redundant ret for transaction
2 parents 83a2950 + 68a3728 commit fcae37a

File tree

10 files changed

+117
-18
lines changed

10 files changed

+117
-18
lines changed

chainbase/src/main/java/org/tron/core/capsule/TransactionCapsule.java

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
import static org.tron.common.utils.StringUtil.encode58Check;
1919
import static org.tron.common.utils.WalletUtil.checkPermissionOperations;
20+
import static org.tron.core.Constant.MAX_CONTRACT_RESULT_SIZE;
2021
import static org.tron.core.exception.P2pException.TypeEnum.PROTOBUF_ERROR;
2122

2223
import com.google.common.primitives.Bytes;
@@ -733,6 +734,15 @@ public long getResultSerializedSize() {
733734
return size;
734735
}
735736

737+
public long getResultSizeWithMaxContractRet() {
738+
long size = 0;
739+
for (Result result : this.transaction.getRetList()) {
740+
size += result.toBuilder().clearContractRet().build().getSerializedSize()
741+
+ MAX_CONTRACT_RESULT_SIZE;
742+
}
743+
return size;
744+
}
745+
736746
@Override
737747
public Transaction getInstance() {
738748
return this.transaction;
@@ -845,4 +855,18 @@ public BalanceContract.TransferContract getTransferContract() {
845855
return null;
846856
}
847857
}
858+
859+
public void removeRedundantRet() {
860+
Transaction tx = this.getInstance();
861+
List<Result> tmpList = new ArrayList<>(tx.getRetList());
862+
int contractCount = tx.getRawData().getContractCount();
863+
if (tx.getRetCount() > contractCount && contractCount > 0) {
864+
Transaction.Builder transactionBuilder = tx.toBuilder().clearRet();
865+
for (int i = 0; i < contractCount; i++) {
866+
Result result = tmpList.get(i);
867+
transactionBuilder.addRet(result);
868+
}
869+
this.transaction = transactionBuilder.build();
870+
}
871+
}
848872
}

chainbase/src/main/java/org/tron/core/db/BandwidthProcessor.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,13 @@ public void consume(TransactionCapsule trx, TransactionTrace trace)
9898
throws ContractValidateException, AccountResourceInsufficientException,
9999
TooBigTransactionResultException, TooBigTransactionException {
100100
List<Contract> contracts = trx.getInstance().getRawData().getContractList();
101+
long resultSizeWithMaxContractRet = trx.getResultSizeWithMaxContractRet();
102+
if (!trx.isInBlock() && resultSizeWithMaxContractRet >
103+
Constant.MAX_RESULT_SIZE_IN_TX * contracts.size()) {
104+
throw new TooBigTransactionResultException(String.format(
105+
"Too big transaction result, TxId %s, the result size is %d bytes, maxResultSize %d",
106+
trx.getTransactionId(), resultSizeWithMaxContractRet, Constant.MAX_RESULT_SIZE_IN_TX));
107+
}
101108
if (trx.getResultSerializedSize() > Constant.MAX_RESULT_SIZE_IN_TX * contracts.size()) {
102109
throw new TooBigTransactionResultException();
103110
}

common/src/main/java/org/tron/core/Constant.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ public class Constant {
3636
public static final long ENERGY_LIMIT_IN_CONSTANT_TX = 3_000_000L; // ref: 1 us = 1 energy
3737
public static final long MAX_RESULT_SIZE_IN_TX = 64; // max 8 * 8 items in result
3838
public static final long PER_SIGN_LENGTH = 65L;
39+
public static final long MAX_CONTRACT_RESULT_SIZE = 2L;
3940
public static final long PB_DEFAULT_ENERGY_LIMIT = 0L;
4041
public static final long CREATOR_DEFAULT_ENERGY_LIMIT = 1000 * 10_000L;
4142

framework/src/main/java/org/tron/core/Wallet.java

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -497,8 +497,6 @@ public GrpcAPI.Return broadcastTransaction(Transaction signedTransaction) {
497497
trx.setTime(System.currentTimeMillis());
498498
Sha256Hash txID = trx.getTransactionId();
499499
try {
500-
TransactionMessage message = new TransactionMessage(signedTransaction.toByteArray());
501-
502500
if (tronNetDelegate.isBlockUnsolidified()) {
503501
logger.warn("Broadcast transaction {} has failed, block unsolidified.", txID);
504502
return builder.setResult(false).setCode(response_code.BLOCK_UNSOLIDIFIED)
@@ -550,6 +548,7 @@ public GrpcAPI.Return broadcastTransaction(Transaction signedTransaction) {
550548
if (trx.getInstance().getRawData().getContractCount() == 0) {
551549
throw new ContractValidateException(ActuatorConstant.CONTRACT_NOT_EXIST);
552550
}
551+
TransactionMessage message = new TransactionMessage(trx.getInstance().toByteArray());
553552
dbManager.pushTransaction(trx);
554553
int num = tronNetService.fastBroadcastTransaction(message);
555554
if (num == 0 && minEffectiveConnection != 0) {
@@ -592,8 +591,7 @@ public GrpcAPI.Return broadcastTransaction(Transaction signedTransaction) {
592591
} catch (TooBigTransactionException e) {
593592
logger.warn(BROADCAST_TRANS_FAILED, txID, e.getMessage());
594593
return builder.setResult(false).setCode(response_code.TOO_BIG_TRANSACTION_ERROR)
595-
.setMessage(ByteString.copyFromUtf8("Transaction size is too big."))
596-
.build();
594+
.setMessage(ByteString.copyFromUtf8(e.getMessage())).build();
597595
} catch (TransactionExpirationException e) {
598596
logger.warn(BROADCAST_TRANS_FAILED, txID, e.getMessage());
599597
return builder.setResult(false).setCode(response_code.TRANSACTION_EXPIRATION_ERROR)

framework/src/main/java/org/tron/core/db/Manager.java

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -795,6 +795,7 @@ void validateTapos(TransactionCapsule transactionCapsule) throws TaposException
795795
void validateCommon(TransactionCapsule transactionCapsule)
796796
throws TransactionExpirationException, TooBigTransactionException {
797797
if (!transactionCapsule.isInBlock()) {
798+
transactionCapsule.removeRedundantRet();
798799
long generalBytesSize =
799800
transactionCapsule.getInstance().toBuilder().clearRet().build().getSerializedSize()
800801
+ Constant.MAX_RESULT_SIZE_IN_TX + Constant.MAX_RESULT_SIZE_IN_TX;
@@ -804,7 +805,6 @@ void validateCommon(TransactionCapsule transactionCapsule)
804805
transactionCapsule.getTransactionId(), generalBytesSize, TRANSACTION_MAX_BYTE_SIZE));
805806
}
806807
}
807-
808808
if (transactionCapsule.getData().length > Constant.TRANSACTION_MAX_BYTE_SIZE) {
809809
throw new TooBigTransactionException(String.format(
810810
"Too big transaction, TxId %s, the size is %d bytes, maxTxSize %d",
@@ -1425,8 +1425,14 @@ public TransactionInfo processTransaction(final TransactionCapsule trxCap, Block
14251425
if (trxCap == null) {
14261426
return null;
14271427
}
1428-
Contract contract = trxCap.getInstance().getRawData().getContract(0);
14291428
Sha256Hash txId = trxCap.getTransactionId();
1429+
if (trxCap.getInstance().getRawData().getContractList().size() != 1) {
1430+
throw new ContractSizeNotEqualToOneException(
1431+
String.format(
1432+
"tx %s contract size should be exactly 1, this is extend feature ,actual :%d",
1433+
txId, trxCap.getInstance().getRawData().getContractList().size()));
1434+
}
1435+
Contract contract = trxCap.getInstance().getRawData().getContract(0);
14301436
final Histogram.Timer requestTimer = Metrics.histogramStartTimer(
14311437
MetricKeys.Histogram.PROCESS_TRANSACTION_LATENCY,
14321438
Objects.nonNull(blockCap) ? MetricLabels.BLOCK : MetricLabels.TRX,
@@ -1442,13 +1448,6 @@ public TransactionInfo processTransaction(final TransactionCapsule trxCap, Block
14421448
validateTapos(trxCap);
14431449
validateCommon(trxCap);
14441450

1445-
if (trxCap.getInstance().getRawData().getContractList().size() != 1) {
1446-
throw new ContractSizeNotEqualToOneException(
1447-
String.format(
1448-
"tx %s contract size should be exactly 1, this is extend feature ,actual :%d",
1449-
txId, trxCap.getInstance().getRawData().getContractList().size()));
1450-
}
1451-
14521451
validateDup(trxCap);
14531452

14541453
if (!trxCap.validateSignature(chainBaseManager.getAccountStore(),

framework/src/test/java/org/tron/common/runtime/vm/BandWidthRuntimeTest.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@
4444
import org.tron.protos.Protocol.Transaction;
4545
import org.tron.protos.Protocol.Transaction.Contract;
4646
import org.tron.protos.Protocol.Transaction.Contract.ContractType;
47+
import org.tron.protos.Protocol.Transaction.Result;
48+
import org.tron.protos.Protocol.Transaction.Result.contractResult;
4749
import org.tron.protos.Protocol.Transaction.raw;
4850
import org.tron.protos.contract.SmartContractOuterClass.CreateSmartContract;
4951
import org.tron.protos.contract.SmartContractOuterClass.TriggerSmartContract;
@@ -237,4 +239,17 @@ private byte[] createContract()
237239
Assert.assertNull(trace.getRuntimeError());
238240
return trace.getRuntimeResult().getContractAddress();
239241
}
242+
243+
@Test
244+
public void testMaxContractResultSize() {
245+
int maxSize = 0;
246+
for (contractResult cr : contractResult.values()) {
247+
if (cr.name().equals("UNRECOGNIZED")) {
248+
continue;
249+
}
250+
Result result = Result.newBuilder().setContractRet(cr).build();
251+
maxSize = Math.max(maxSize, result.getSerializedSize());
252+
}
253+
Assert.assertEquals(2, maxSize);
254+
}
240255
}

framework/src/test/java/org/tron/core/BandwidthProcessorTest.java

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
package org.tron.core;
22

3+
import static org.junit.Assert.assertThrows;
4+
35
import com.google.protobuf.Any;
46
import com.google.protobuf.ByteString;
7+
import java.nio.charset.StandardCharsets;
58
import lombok.extern.slf4j.Slf4j;
69
import org.joda.time.DateTime;
710
import org.junit.Assert;
@@ -24,6 +27,11 @@
2427
import org.tron.core.store.StoreFactory;
2528
import org.tron.protos.Protocol;
2629
import org.tron.protos.Protocol.AccountType;
30+
import org.tron.protos.Protocol.Transaction;
31+
import org.tron.protos.Protocol.Transaction.Contract;
32+
import org.tron.protos.Protocol.Transaction.Contract.ContractType;
33+
import org.tron.protos.Protocol.Transaction.Result;
34+
import org.tron.protos.Protocol.Transaction.raw;
2735
import org.tron.protos.contract.AssetIssueContractOuterClass.AssetIssueContract;
2836
import org.tron.protos.contract.AssetIssueContractOuterClass.TransferAssetContract;
2937
import org.tron.protos.contract.BalanceContract.TransferContract;
@@ -540,6 +548,32 @@ public void testUsingFee() throws Exception {
540548
dbManager.consumeBandwidth(trx, trace);
541549
}
542550

551+
@Test
552+
public void testConsumeBandwidthTooBigTransactionResultException() {
553+
TransferContract transferContract =
554+
TransferContract.newBuilder()
555+
.setAmount(10)
556+
.setOwnerAddress(ByteString.copyFromUtf8("aaa"))
557+
.setToAddress(ByteString.copyFromUtf8("bbb"))
558+
.build();
559+
StringBuilder sb = new StringBuilder();
560+
for (int i = 0; i < 6666; i++) {
561+
sb.append("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
562+
}
563+
Transaction transaction = Transaction.newBuilder().setRawData(raw.newBuilder()
564+
.setData(ByteString.copyFrom(sb.toString().getBytes(StandardCharsets.UTF_8)))
565+
.addContract(Contract.newBuilder().setParameter(Any.pack(transferContract))
566+
.setType(ContractType.TransferContract)))
567+
.addRet(Result.newBuilder().setAssetIssueID(sb.toString()).build()).build();
568+
TransactionCapsule trx = new TransactionCapsule(transaction);
569+
trx.setInBlock(false);
570+
TransactionTrace trace = new TransactionTrace(trx, StoreFactory
571+
.getInstance(), new RuntimeImpl());
572+
assertThrows(
573+
"Too big transaction result, TxId %s, the result size is %d bytes, maxResultSize %d",
574+
TooBigTransactionResultException.class, () -> dbManager.consumeBandwidth(trx, trace));
575+
}
576+
543577
/**
544578
* sameTokenName close, consume success assetIssueCapsule.getOwnerAddress() !=
545579
* fromAccount.getAddress()) contract.getType() = TransferAssetContract

framework/src/test/java/org/tron/core/capsule/TransactionCapsuleTest.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
package org.tron.core.capsule;
22

3+
import static org.tron.protos.Protocol.Transaction.Result.contractResult.BAD_JUMP_DESTINATION;
4+
import static org.tron.protos.Protocol.Transaction.Result.contractResult.PRECOMPILED_CONTRACT;
5+
import static org.tron.protos.Protocol.Transaction.Result.contractResult.SUCCESS;
6+
37
import com.google.protobuf.ByteString;
48
import lombok.extern.slf4j.Slf4j;
59
import org.junit.Assert;
@@ -13,8 +17,10 @@
1317
import org.tron.core.config.args.Args;
1418
import org.tron.protos.Protocol.AccountType;
1519
import org.tron.protos.Protocol.Transaction;
20+
import org.tron.protos.Protocol.Transaction.Contract.ContractType;
1621
import org.tron.protos.Protocol.Transaction.Result;
1722
import org.tron.protos.Protocol.Transaction.Result.contractResult;
23+
import org.tron.protos.Protocol.Transaction.raw;
1824

1925
@Slf4j
2026
public class TransactionCapsuleTest extends BaseTest {
@@ -1064,4 +1070,18 @@ public void trxCapsuleClearTest() {
10641070
Assert.assertEquals(trxCap.getInstance()
10651071
.getRet(0).getContractRet(), Result.contractResult.OUT_OF_TIME);
10661072
}
1073+
1074+
@Test
1075+
public void testRemoveRedundantRet() {
1076+
Transaction.Builder transaction = Transaction.newBuilder().setRawData(raw.newBuilder()
1077+
.addContract(Transaction.Contract.newBuilder().setType(ContractType.TriggerSmartContract))
1078+
.setFeeLimit(1000000000)).build().toBuilder();
1079+
transaction.addRet(Result.newBuilder().setContractRet(SUCCESS).build());
1080+
transaction.addRet(Result.newBuilder().setContractRet(PRECOMPILED_CONTRACT).build());
1081+
transaction.addRet(Result.newBuilder().setContractRet(BAD_JUMP_DESTINATION).build());
1082+
TransactionCapsule transactionCapsule = new TransactionCapsule(transaction.build());
1083+
transactionCapsule.removeRedundantRet();
1084+
Assert.assertEquals(1, transactionCapsule.getInstance().getRetCount());
1085+
Assert.assertEquals(SUCCESS, transactionCapsule.getInstance().getRet(0).getContractRet());
1086+
}
10671087
}

framework/src/test/java/org/tron/core/db/ManagerTest.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1131,24 +1131,24 @@ public void testTooBigTransaction() {
11311131
for (int i = 0; i < 6666; i++) {
11321132
sb.append("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
11331133
}
1134-
Transaction transaction = Transaction.newBuilder().setRawData(raw.newBuilder()
1135-
.setData(ByteString.copyFrom(sb.toString().getBytes(StandardCharsets.UTF_8)))
1136-
.addContract(Transaction.Contract.newBuilder().setParameter(Any.pack(transferContract))
1134+
Transaction transaction = Transaction.newBuilder().setRawData(Transaction.raw.newBuilder()
1135+
.setData(ByteString.copyFrom(sb.toString().getBytes(StandardCharsets.UTF_8)))
1136+
.addContract(Transaction.Contract.newBuilder().setParameter(Any.pack(transferContract))
11371137
.setType(ContractType.TransferContract))).build();
11381138
TransactionCapsule trx = new TransactionCapsule(transaction);
11391139
trx.setInBlock(false);
11401140
assertThrows(
11411141
"Too big transaction with result, "
11421142
+ "TxId 1c05e9fca6a2d0c366ed4430456527eb40198e70c8b20f5ceca4739c68a79af8, "
11431143
+ "the size is 533483 bytes, maxTxSize 512000",
1144-
TooBigTransactionException.class, ()-> dbManager.validateCommon(trx));
1144+
TooBigTransactionException.class, () -> dbManager.validateCommon(trx));
11451145

11461146
trx.setInBlock(true);
11471147
assertThrows(
11481148
"Too big transaction, "
11491149
+ "TxId 1c05e9fca6a2d0c366ed4430456527eb40198e70c8b20f5ceca4739c68a79af8, "
11501150
+ "the size is 1066643 bytes, maxTxSize 512000",
1151-
TooBigTransactionException.class, ()-> dbManager.validateCommon(trx));
1151+
TooBigTransactionException.class, () -> dbManager.validateCommon(trx));
11521152

11531153
}
11541154
}

protocol/src/main/protos/core/Tron.proto

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -407,6 +407,7 @@ message Transaction {
407407
UNKNOWN = 13;
408408
TRANSFER_FAILED = 14;
409409
INVALID_CODE = 15;
410+
// please fill in the order according to the serial number
410411
}
411412
int64 fee = 1;
412413
code ret = 2;

0 commit comments

Comments
 (0)