Skip to content
Open
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
11 changes: 11 additions & 0 deletions framework/src/main/java/org/tron/core/Wallet.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import static org.tron.common.utils.Commons.getAssetIssueStoreFinal;
import static org.tron.common.utils.Commons.getExchangeStoreFinal;
import static org.tron.common.utils.WalletUtil.isConstant;
import static org.tron.core.Constant.PER_SIGN_LENGTH;
import static org.tron.core.capsule.utils.TransactionUtil.buildInternalTransaction;
import static org.tron.core.config.Parameter.ChainConstant.BLOCK_PRODUCED_INTERVAL;
import static org.tron.core.config.Parameter.ChainConstant.TRX_PRECISION;
Expand Down Expand Up @@ -505,6 +506,16 @@ public GrpcAPI.Return broadcastTransaction(Transaction signedTransaction) {
trx.setTime(System.currentTimeMillis());
Sha256Hash txID = trx.getTransactionId();
try {
for (ByteString sig : signedTransaction.getSignatureList()) {
if (sig.size() != PER_SIGN_LENGTH) {
String info = "Signature size is " + sig.size();
logger.warn("Broadcast transaction {} has failed, {}.", txID, info);
return builder.setResult(false).setCode(response_code.SIGERROR)
.setMessage(ByteString.copyFromUtf8("Validate signature error: " + info))
.build();
}
}

if (tronNetDelegate.isBlockUnsolidified()) {
logger.warn("Broadcast transaction {} has failed, block unsolidified.", txID);
return builder.setResult(false).setCode(response_code.BLOCK_UNSOLIDIFIED)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
package org.tron.core.net.messagehandler;

import static org.tron.core.Constant.PER_SIGN_LENGTH;

import com.google.protobuf.ByteString;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
Expand Down Expand Up @@ -142,6 +145,12 @@ private void check(PeerConnection peer, TransactionsMessage msg) throws P2pExcep
throw new P2pException(TypeEnum.BAD_TRX,
"tx " + item.getHash() + " contract size should be greater than 0");
}
for (ByteString sig : trx.getSignatureList()) {
if (sig.size() != PER_SIGN_LENGTH) {
throw new P2pException(TypeEnum.BAD_TRX,
"tx " + item.getHash() + " signature size is " + sig.size());
}
}
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package org.tron.core.net.service.relay;

import static org.tron.core.Constant.PER_SIGN_LENGTH;

import com.google.protobuf.ByteString;
import java.net.InetSocketAddress;
import java.util.Arrays;
Expand Down Expand Up @@ -150,6 +152,12 @@ public boolean checkHelloMessage(HelloMessage message, Channel channel) {
return false;
}

if (msg.getSignature().size() != PER_SIGN_LENGTH) {
logger.warn("HelloMessage from {}, signature size is {}.",
channel.getInetAddress(), msg.getSignature().size());
return false;
}

boolean flag;
try {
Sha256Hash hash = Sha256Hash.of(CommonParameter
Expand Down
41 changes: 41 additions & 0 deletions framework/src/test/java/org/tron/core/WalletMockTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,47 @@ public void testCreateTransactionCapsuleWithoutValidateWithTimeout()
}


@Test
public void testBroadcastTxInvalidSigLength() throws Exception {
Wallet wallet = new Wallet();
TronNetDelegate tronNetDelegateMock = mock(TronNetDelegate.class);
Field field = wallet.getClass().getDeclaredField("tronNetDelegate");
field.setAccessible(true);
field.set(wallet, tronNetDelegateMock);

// signature shorter than 65 bytes → SIGERROR
Protocol.Transaction shortSig = Protocol.Transaction.newBuilder()
.addSignature(ByteString.copyFrom(new byte[64]))
.build();
GrpcAPI.Return ret = wallet.broadcastTransaction(shortSig);
assertEquals(GrpcAPI.Return.response_code.SIGERROR, ret.getCode());

// signature longer than 65 bytes → SIGERROR
Protocol.Transaction longSig = Protocol.Transaction.newBuilder()
.addSignature(ByteString.copyFrom(new byte[66]))
.build();
ret = wallet.broadcastTransaction(longSig);
assertEquals(GrpcAPI.Return.response_code.SIGERROR, ret.getCode());

// empty signature → SIGERROR
Protocol.Transaction emptySig = Protocol.Transaction.newBuilder()
.addSignature(ByteString.EMPTY)
.build();
ret = wallet.broadcastTransaction(emptySig);
assertEquals(GrpcAPI.Return.response_code.SIGERROR, ret.getCode());

// tronNetDelegate must not be consulted because the request is rejected up front
Mockito.verify(tronNetDelegateMock, Mockito.never()).isBlockUnsolidified();

// 65-byte signature passes the length check and proceeds to downstream logic
when(tronNetDelegateMock.isBlockUnsolidified()).thenReturn(true);
Protocol.Transaction validSig = Protocol.Transaction.newBuilder()
.addSignature(ByteString.copyFrom(new byte[65]))
.build();
ret = wallet.broadcastTransaction(validSig);
assertEquals(GrpcAPI.Return.response_code.BLOCK_UNSOLIDIFIED, ret.getCode());
}

@Test
public void testBroadcastTransactionBlockUnsolidified() throws Exception {
Wallet wallet = new Wallet();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -337,6 +337,75 @@ public void testDuplicateTransactionRejected() throws Exception {
}
}

@Test
public void testInvalidSigLength() throws Exception {
TransactionsMsgHandler handler = new TransactionsMsgHandler();
handler.init();
try {
PeerConnection peer = Mockito.mock(PeerConnection.class);

BalanceContract.TransferContract transferContract = BalanceContract.TransferContract
.newBuilder()
.setAmount(10)
.setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString("121212a9cf")))
.setToAddress(ByteString.copyFrom(ByteArray.fromHexString("232323a9cf")))
.build();

// signature shorter than 65 bytes → BAD_TRX
Protocol.Transaction shortSigTrx = Protocol.Transaction.newBuilder()
.setRawData(Protocol.Transaction.raw.newBuilder()
.addContract(Protocol.Transaction.Contract.newBuilder()
.setType(Protocol.Transaction.Contract.ContractType.TransferContract)
.setParameter(Any.pack(transferContract)).build())
.build())
.addSignature(ByteString.copyFrom(new byte[64]))
.build();

List<Protocol.Transaction> shortList = new ArrayList<>();
shortList.add(shortSigTrx);
stubAdvInvRequest(peer, new TransactionsMessage(shortList));
P2pException shortEx = Assert.assertThrows(P2pException.class,
() -> handler.processMessage(peer, new TransactionsMessage(shortList)));
Assert.assertEquals(TypeEnum.BAD_TRX, shortEx.getType());

// signature longer than 65 bytes → BAD_TRX
Protocol.Transaction longSigTrx = Protocol.Transaction.newBuilder()
.setRawData(Protocol.Transaction.raw.newBuilder()
.setRefBlockNum(1)
.addContract(Protocol.Transaction.Contract.newBuilder()
.setType(Protocol.Transaction.Contract.ContractType.TransferContract)
.setParameter(Any.pack(transferContract)).build())
.build())
.addSignature(ByteString.copyFrom(new byte[66]))
.build();

List<Protocol.Transaction> longList = new ArrayList<>();
longList.add(longSigTrx);
stubAdvInvRequest(peer, new TransactionsMessage(longList));
P2pException longEx = Assert.assertThrows(P2pException.class,
() -> handler.processMessage(peer, new TransactionsMessage(longList)));
Assert.assertEquals(TypeEnum.BAD_TRX, longEx.getType());

// exactly 65 bytes → passes the length check (no P2pException from check)
Protocol.Transaction validSigTrx = Protocol.Transaction.newBuilder()
.setRawData(Protocol.Transaction.raw.newBuilder()
.setRefBlockNum(2)
.addContract(Protocol.Transaction.Contract.newBuilder()
.setType(Protocol.Transaction.Contract.ContractType.TransferContract)
.setParameter(Any.pack(transferContract)).build())
.build())
.addSignature(ByteString.copyFrom(new byte[65]))
.build();

List<Protocol.Transaction> validList = new ArrayList<>();
validList.add(validSigTrx);
stubAdvInvRequest(peer, new TransactionsMessage(validList));
handler.processMessage(peer, new TransactionsMessage(validList));
} finally {
handler.close();
}
}

@Test
public void testIsBusyWithCachedTransactions() throws Exception {
TransactionsMsgHandler handler = new TransactionsMsgHandler();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,30 @@ private void testCheckHelloMessage() {

boolean res = service.checkHelloMessage(helloMessage, c1);
Assert.assertTrue(res);

HelloMessage shortSigMsg = new HelloMessage(node, System.currentTimeMillis(),
ChainBaseManager.getChainBaseManager());
shortSigMsg.setHelloMessage(shortSigMsg.getHelloMessage().toBuilder()
.setAddress(address)
.setSignature(ByteString.copyFrom(new byte[64]))
.build());
Assert.assertFalse(service.checkHelloMessage(shortSigMsg, c1));

HelloMessage longSigMsg = new HelloMessage(node, System.currentTimeMillis(),
ChainBaseManager.getChainBaseManager());
longSigMsg.setHelloMessage(longSigMsg.getHelloMessage().toBuilder()
.setAddress(address)
.setSignature(ByteString.copyFrom(new byte[66]))
.build());
Assert.assertFalse(service.checkHelloMessage(longSigMsg, c1));

HelloMessage emptySigMsg = new HelloMessage(node, System.currentTimeMillis(),
ChainBaseManager.getChainBaseManager());
emptySigMsg.setHelloMessage(emptySigMsg.getHelloMessage().toBuilder()
.setAddress(address)
.setSignature(ByteString.EMPTY)
.build());
Assert.assertFalse(service.checkHelloMessage(emptySigMsg, c1));
} catch (Exception e) {
logger.info("", e);
assert false;
Expand Down
Loading