Skip to content

feat(validate): limit big transaction size #5838

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
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
16 changes: 15 additions & 1 deletion framework/src/main/java/org/tron/core/db/Manager.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package org.tron.core.db;

import static org.tron.common.utils.Commons.adjustBalance;
import static org.tron.core.Constant.TRANSACTION_MAX_BYTE_SIZE;
import static org.tron.core.exception.BadBlockException.TypeEnum.CALC_MERKLE_ROOT_FAILED;
import static org.tron.protos.Protocol.Transaction.Contract.ContractType.TransferContract;
import static org.tron.protos.Protocol.Transaction.Result.contractResult.SUCCESS;
Expand Down Expand Up @@ -793,9 +794,22 @@ void validateTapos(TransactionCapsule transactionCapsule) throws TaposException

void validateCommon(TransactionCapsule transactionCapsule)
throws TransactionExpirationException, TooBigTransactionException {
if (!transactionCapsule.isInBlock()) {
long generalBytesSize =
transactionCapsule.getInstance().toBuilder().clearRet().build().getSerializedSize()
+ Constant.MAX_RESULT_SIZE_IN_TX + Constant.MAX_RESULT_SIZE_IN_TX;
if (generalBytesSize > TRANSACTION_MAX_BYTE_SIZE) {
throw new TooBigTransactionException(String.format(
"Too big transaction with result, TxId %s, the size is %d bytes, maxTxSize %d",
transactionCapsule.getTransactionId(), generalBytesSize, TRANSACTION_MAX_BYTE_SIZE));
}
}

if (transactionCapsule.getData().length > Constant.TRANSACTION_MAX_BYTE_SIZE) {
throw new TooBigTransactionException(String.format(
"Too big transaction, the size is %d bytes", transactionCapsule.getData().length));
"Too big transaction, TxId %s, the size is %d bytes, maxTxSize %d",
transactionCapsule.getTransactionId(), transactionCapsule.getData().length,
TRANSACTION_MAX_BYTE_SIZE));
}
long transactionExpiration = transactionCapsule.getExpiration();
long headBlockTime = chainBaseManager.getHeadBlockTimeStamp();
Expand Down
37 changes: 37 additions & 0 deletions framework/src/test/java/org/tron/core/db/ManagerTest.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.tron.core.db;

import static org.junit.Assert.assertThrows;
import static org.tron.common.utils.Commons.adjustAssetBalanceV2;
import static org.tron.common.utils.Commons.adjustBalance;
import static org.tron.common.utils.Commons.adjustTotalShieldedPoolValue;
Expand All @@ -8,8 +9,10 @@

import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.google.protobuf.Any;
import com.google.protobuf.ByteString;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
Expand Down Expand Up @@ -85,6 +88,7 @@
import org.tron.protos.Protocol.Block;
import org.tron.protos.Protocol.Transaction;
import org.tron.protos.Protocol.Transaction.Contract.ContractType;
import org.tron.protos.Protocol.Transaction.raw;
import org.tron.protos.contract.AccountContract;
import org.tron.protos.contract.AssetIssueContractOuterClass;
import org.tron.protos.contract.BalanceContract.TransferContract;
Expand Down Expand Up @@ -1114,4 +1118,37 @@ public void testExpireTransaction() {
Assert.fail();
}
}

@Test
public void testTooBigTransaction() {
TransferContract transferContract =
TransferContract.newBuilder()
.setAmount(10)
.setOwnerAddress(ByteString.copyFromUtf8("aaa"))
.setToAddress(ByteString.copyFromUtf8("bbb"))
.build();
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 6666; i++) {
sb.append("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
}
Transaction transaction = Transaction.newBuilder().setRawData(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(false);
assertThrows(
"Too big transaction with result, "
+ "TxId 1c05e9fca6a2d0c366ed4430456527eb40198e70c8b20f5ceca4739c68a79af8, "
+ "the size is 533483 bytes, maxTxSize 512000",
TooBigTransactionException.class, ()-> dbManager.validateCommon(trx));

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

}
}