Skip to content

Commit

Permalink
Merge pull request #5999 from fyyhtx/release_v4.7.6
Browse files Browse the repository at this point in the history
feat(net): add transaction expiration time check before execution
  • Loading branch information
lvs007 authored Sep 12, 2024
2 parents 1996f7b + 6c73ede commit cdbbb0a
Show file tree
Hide file tree
Showing 7 changed files with 150 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@
import org.tron.core.exception.P2pException;
import org.tron.core.exception.PermissionException;
import org.tron.core.exception.SignatureFormatException;
import org.tron.core.exception.TransactionExpirationException;
import org.tron.core.exception.ValidateSignatureException;
import org.tron.core.store.AccountStore;
import org.tron.core.store.DynamicPropertiesStore;
Expand Down Expand Up @@ -869,4 +870,12 @@ public void removeRedundantRet() {
this.transaction = transactionBuilder.build();
}
}

public void checkExpiration(long nextSlotTime) throws TransactionExpirationException {
if (getExpiration() < nextSlotTime) {
throw new TransactionExpirationException(String.format(
"Transaction expiration time is %d, but next slot time is %d",
getExpiration(), nextSlotTime));
}
}
}
1 change: 1 addition & 0 deletions framework/src/main/java/org/tron/core/Wallet.java
Original file line number Diff line number Diff line change
Expand Up @@ -549,6 +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());
dbManager.pushTransaction(trx);
int num = tronNetService.fastBroadcastTransaction(message);
if (num == 0 && minEffectiveConnection != 0) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -380,4 +380,12 @@ 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 @@ -13,6 +13,7 @@
import org.tron.core.config.args.Args;
import org.tron.core.exception.P2pException;
import org.tron.core.exception.P2pException.TypeEnum;
import org.tron.core.exception.TransactionExpirationException;
import org.tron.core.net.TronNetDelegate;
import org.tron.core.net.message.TronMessage;
import org.tron.core.net.message.adv.TransactionMessage;
Expand Down Expand Up @@ -128,6 +129,7 @@ private void handleTransaction(PeerConnection peer, TransactionMessage trx) {
}

try {
trx.getTransactionCapsule().checkExpiration(tronNetDelegate.getNextBlockSlotTime());
tronNetDelegate.pushTransaction(trx.getTransactionCapsule());
advService.broadcast(trx);
} catch (P2pException e) {
Expand All @@ -137,6 +139,9 @@ private void handleTransaction(PeerConnection peer, TransactionMessage trx) {
peer.setBadPeer(true);
peer.disconnect(ReasonCode.BAD_TX);
}
} catch (TransactionExpirationException e) {
logger.warn("{}. trx: {}, peer: {}",
e.getMessage(), trx.getMessageId(), peer.getInetAddress());
} catch (Exception e) {
logger.error("Trx {} from peer {} process failed", trx.getMessageId(), peer.getInetAddress(),
e);
Expand Down
79 changes: 66 additions & 13 deletions framework/src/test/java/org/tron/core/db/TransactionExpireTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -50,19 +50,6 @@ public void init() throws IOException {
context = new TronApplicationContext(DefaultConfig.class);
wallet = context.getBean(Wallet.class);
dbManager = context.getBean(Manager.class);

blockCapsule = new BlockCapsule(
1,
Sha256Hash.wrap(ByteString.copyFrom(
ByteArray.fromHexString(
"0304f784e4e7bae517bcab94c3e0c9214fb4ac7ff9d7d5a937d1f40031f87b81"))),
1,
ByteString.copyFromUtf8("testAddress"));
dbManager.getDynamicPropertiesStore().saveLatestBlockHeaderNumber(blockCapsule.getNum());
dbManager.getDynamicPropertiesStore()
.saveLatestBlockHeaderTimestamp(blockCapsule.getTimeStamp());
dbManager.updateRecentBlock(blockCapsule);
initLocalWitness();
}

private void initLocalWitness() {
Expand All @@ -81,6 +68,19 @@ public void removeDb() {

@Test
public void testExpireTransaction() {
blockCapsule = new BlockCapsule(
1,
Sha256Hash.wrap(ByteString.copyFrom(
ByteArray.fromHexString(
"0304f784e4e7bae517bcab94c3e0c9214fb4ac7ff9d7d5a937d1f40031f87b81"))),
1,
ByteString.copyFromUtf8("testAddress"));
dbManager.getDynamicPropertiesStore().saveLatestBlockHeaderNumber(blockCapsule.getNum());
dbManager.getDynamicPropertiesStore()
.saveLatestBlockHeaderTimestamp(blockCapsule.getTimeStamp());
dbManager.updateRecentBlock(blockCapsule);
initLocalWitness();

TransferContract transferContract = TransferContract.newBuilder()
.setAmount(1L)
.setOwnerAddress(ByteString.copyFrom(Args.getLocalWitnesses()
Expand All @@ -101,8 +101,61 @@ public void testExpireTransaction() {
Assert.assertEquals(response_code.TRANSACTION_EXPIRATION_ERROR, result.getCode());
}

@Test
public void testExpireTransactionNew() {
blockCapsule = new BlockCapsule(
1,
Sha256Hash.wrap(ByteString.copyFrom(
ByteArray.fromHexString(
"0304f784e4e7bae517bcab94c3e0c9214fb4ac7ff9d7d5a937d1f40031f87b81"))),
System.currentTimeMillis(),
ByteString.copyFromUtf8("testAddress"));
dbManager.getDynamicPropertiesStore().saveLatestBlockHeaderNumber(blockCapsule.getNum());
dbManager.getDynamicPropertiesStore()
.saveLatestBlockHeaderTimestamp(blockCapsule.getTimeStamp());
dbManager.updateRecentBlock(blockCapsule);
initLocalWitness();
byte[] address = Args.getLocalWitnesses()
.getWitnessAccountAddress(CommonParameter.getInstance().isECKeyCryptoEngine());
ByteString addressByte = ByteString.copyFrom(address);
AccountCapsule accountCapsule =
new AccountCapsule(Protocol.Account.newBuilder().setAddress(addressByte).build());
accountCapsule.setBalance(1000_000_000L);
dbManager.getChainBaseManager().getAccountStore()
.put(accountCapsule.createDbKey(), accountCapsule);

TransferContract transferContract = TransferContract.newBuilder()
.setAmount(1L)
.setOwnerAddress(addressByte)
.setToAddress(ByteString.copyFrom(ByteArray.fromHexString(
(Wallet.getAddressPreFixString() + "A389132D6639FBDA4FBC8B659264E6B7C90DB086"))))
.build();
TransactionCapsule transactionCapsule =
new TransactionCapsule(transferContract, ContractType.TransferContract);
transactionCapsule.setReference(blockCapsule.getNum(), blockCapsule.getBlockId().getBytes());

transactionCapsule.setExpiration(System.currentTimeMillis());
transactionCapsule.sign(ByteArray.fromHexString(Args.getLocalWitnesses().getPrivateKey()));

GrpcAPI.Return result = wallet.broadcastTransaction(transactionCapsule.getInstance());
Assert.assertEquals(response_code.TRANSACTION_EXPIRATION_ERROR, result.getCode());
}

@Test
public void testTransactionApprovedList() {
blockCapsule = new BlockCapsule(
1,
Sha256Hash.wrap(ByteString.copyFrom(
ByteArray.fromHexString(
"0304f784e4e7bae517bcab94c3e0c9214fb4ac7ff9d7d5a937d1f40031f87b81"))),
1,
ByteString.copyFromUtf8("testAddress"));
dbManager.getDynamicPropertiesStore().saveLatestBlockHeaderNumber(blockCapsule.getNum());
dbManager.getDynamicPropertiesStore()
.saveLatestBlockHeaderTimestamp(blockCapsule.getTimeStamp());
dbManager.updateRecentBlock(blockCapsule);
initLocalWitness();

byte[] address = Args.getLocalWitnesses()
.getWitnessAccountAddress(CommonParameter.getInstance().isECKeyCryptoEngine());
TransferContract transferContract = TransferContract.newBuilder()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,18 @@
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.LinkedBlockingQueue;

import lombok.Getter;
import org.joda.time.DateTime;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;
import org.mockito.Mockito;
import org.tron.common.BaseTest;
import org.tron.common.runtime.TvmTestUtils;
import org.tron.common.utils.ByteArray;
import org.tron.core.Constant;
import org.tron.core.config.args.Args;
Expand Down Expand Up @@ -75,10 +80,48 @@ public void testProcessMessage() {
transactionsMsgHandler.processMessage(peer, new TransactionsMessage(transactionList));
Assert.assertNull(advInvRequest.get(item));
//Thread.sleep(10);
transactionsMsgHandler.close();
BlockingQueue<TrxEvent> smartContractQueue =
new LinkedBlockingQueue(2);
smartContractQueue.offer(new TrxEvent(null, null));
smartContractQueue.offer(new TrxEvent(null, null));
Field field1 = TransactionsMsgHandler.class.getDeclaredField("smartContractQueue");
field1.setAccessible(true);
field1.set(transactionsMsgHandler, smartContractQueue);
Protocol.Transaction trx1 = TvmTestUtils.generateTriggerSmartContractAndGetTransaction(
ByteArray.fromHexString("121212a9cf"),
ByteArray.fromHexString("121212a9cf"),
ByteArray.fromHexString("123456"),
100, 100000000, 0, 0);
Map<Item, Long> advInvRequest1 = new ConcurrentHashMap<>();
Item item1 = new Item(new TransactionMessage(trx1).getMessageId(),
Protocol.Inventory.InventoryType.TRX);
advInvRequest1.put(item1, 0L);
Mockito.when(peer.getAdvInvRequest()).thenReturn(advInvRequest1);
List<Protocol.Transaction> transactionList1 = new ArrayList<>();
transactionList1.add(trx1);
transactionsMsgHandler.processMessage(peer, new TransactionsMessage(transactionList1));
Assert.assertNull(advInvRequest.get(item1));
} catch (Exception e) {
Assert.fail();
} finally {
transactionsMsgHandler.close();
}
}

class TrxEvent {

@Getter
private PeerConnection peer;
@Getter
private TransactionMessage msg;
@Getter
private long time;

public TrxEvent(PeerConnection peer, TransactionMessage msg) {
this.peer = peer;
this.msg = msg;
this.time = System.currentTimeMillis();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

import java.io.IOException;
import java.net.InetSocketAddress;

import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.BeforeClass;
Expand Down Expand Up @@ -105,12 +106,28 @@ private void testBroadcast() {
}

private void testTrxBroadcast() {
Protocol.Transaction trx = Protocol.Transaction.newBuilder().build();
Protocol.Transaction trx = Protocol.Transaction.newBuilder()
.setRawData(
Protocol.Transaction.raw.newBuilder()
.setRefBlockNum(1)
.setExpiration(System.currentTimeMillis() + 3000).build()).build();
CommonParameter.getInstance().setValidContractProtoThreadNum(1);
TransactionMessage msg = new TransactionMessage(trx);
service.broadcast(msg);
Item item = new Item(msg.getMessageId(), InventoryType.TRX);
Assert.assertNotNull(service.getMessage(item));

Protocol.Transaction expiredTrx = Protocol.Transaction.newBuilder()
.setRawData(
Protocol.Transaction.raw.newBuilder()
.setRefBlockNum(1)
.setExpiration(System.currentTimeMillis() - 1).build())
.build();
CommonParameter.getInstance().setValidContractProtoThreadNum(1);
TransactionMessage msg1 = new TransactionMessage(expiredTrx);
service.broadcast(msg);
Item item1 = new Item(msg1.getMessageId(), InventoryType.TRX);
Assert.assertNull(service.getMessage(item1));
}

}

0 comments on commit cdbbb0a

Please sign in to comment.