diff --git a/actuator/src/main/java/org/tron/core/utils/TransactionUtil.java b/actuator/src/main/java/org/tron/core/utils/TransactionUtil.java index 53d6caf5691..a2f3c07e1fa 100644 --- a/actuator/src/main/java/org/tron/core/utils/TransactionUtil.java +++ b/actuator/src/main/java/org/tron/core/utils/TransactionUtil.java @@ -223,9 +223,12 @@ public TransactionSignWeight getTransactionSignWeight(Transaction trx) { tswBuilder.setPermission(permission); if (trx.getSignatureCount() > 0) { List approveList = new ArrayList<>(); + // Read-only introspection: pass checkMaxSignatureSize=false so a historical tx + // committed with a sig above MAX_SIGNATURE_SIZE is still resolvable long currentWeight = TransactionCapsule.checkWeight(permission, trx.getSignatureList(), Sha256Hash.hash(CommonParameter.getInstance() - .isECKeyCryptoEngine(), trx.getRawData().toByteArray()), approveList); + .isECKeyCryptoEngine(), trx.getRawData().toByteArray()), approveList, + false); tswBuilder.addAllApprovedList(approveList); tswBuilder.setCurrentWeight(currentWeight); } diff --git a/chainbase/src/main/java/org/tron/core/capsule/BlockCapsule.java b/chainbase/src/main/java/org/tron/core/capsule/BlockCapsule.java index 34b7853d4d1..10f9eeee77a 100755 --- a/chainbase/src/main/java/org/tron/core/capsule/BlockCapsule.java +++ b/chainbase/src/main/java/org/tron/core/capsule/BlockCapsule.java @@ -185,9 +185,14 @@ private Sha256Hash getRawHash() { public boolean validateSignature(DynamicPropertiesStore dynamicPropertiesStore, AccountStore accountStore) throws ValidateSignatureException { try { + ByteString witnessSig = block.getBlockHeader().getWitnessSignature(); + if (!SignUtils.isValidLength(witnessSig.size(), + dynamicPropertiesStore.signatureMaxSizeChecked())) { + throw new ValidateSignatureException( + "Witness signature size is " + witnessSig.size()); + } byte[] sigAddress = SignUtils.signatureToAddress(getRawHash().getBytes(), - TransactionCapsule.getBase64FromByteString( - block.getBlockHeader().getWitnessSignature()), + TransactionCapsule.getBase64FromByteString(witnessSig), CommonParameter.getInstance().isECKeyCryptoEngine()); byte[] witnessAccountAddress = block.getBlockHeader().getRawData().getWitnessAddress() .toByteArray(); diff --git a/chainbase/src/main/java/org/tron/core/capsule/TransactionCapsule.java b/chainbase/src/main/java/org/tron/core/capsule/TransactionCapsule.java index bb4b70cde1b..54f0d25fb68 100755 --- a/chainbase/src/main/java/org/tron/core/capsule/TransactionCapsule.java +++ b/chainbase/src/main/java/org/tron/core/capsule/TransactionCapsule.java @@ -54,6 +54,7 @@ import org.tron.common.utils.Sha256Hash; import org.tron.core.actuator.TransactionFactory; import org.tron.core.config.Parameter; +import org.tron.core.config.Parameter.ChainConstant; import org.tron.core.db.TransactionContext; import org.tron.core.db.TransactionTrace; import org.tron.core.exception.BadItemException; @@ -230,7 +231,7 @@ public static long getWeight(Permission permission, byte[] address) { * @see ForkController#init(org.tron.core.ChainBaseManager) */ public static long checkWeight(Permission permission, List sigs, byte[] hash, - List approveList) + List approveList, boolean checkMaxSignatureSize) throws SignatureException, PermissionException, SignatureFormatException { long currentWeight = 0; if (sigs.size() > permission.getKeysCount()) { @@ -240,9 +241,8 @@ public static long checkWeight(Permission permission, List sigs, byt } HashMap addMap = new HashMap(); for (ByteString sig : sigs) { - if (sig.size() < 65) { - throw new SignatureFormatException( - "Signature size is " + sig.size()); + if (!SignUtils.isValidLength(sig.size(), checkMaxSignatureSize)) { + throw new SignatureFormatException("Signature size is " + sig.size()); } String base64 = TransactionCapsule.getBase64FromByteString(sig); byte[] address = SignUtils @@ -487,7 +487,8 @@ public static boolean validateSignature(Transaction transaction, throw new PermissionException("permission isn't exit"); } checkPermission(permissionId, permission, contract); - long weight = checkWeight(permission, transaction.getSignatureList(), hash, null); + long weight = checkWeight(permission, transaction.getSignatureList(), hash, null, + dynamicPropertiesStore.signatureMaxSizeChecked()); if (weight >= permission.getThreshold()) { return true; } @@ -583,7 +584,8 @@ public void sign(byte[] privateKey) { this.transaction = this.transaction.toBuilder().addSignature(sig).build(); } - public void addSign(byte[] privateKey, AccountStore accountStore) + public void addSign(byte[] privateKey, AccountStore accountStore, + DynamicPropertiesStore dynamicPropertiesStore) throws PermissionException, SignatureException, SignatureFormatException { Transaction.Contract contract = this.transaction.getRawData().getContract(0); int permissionId = contract.getPermissionId(); @@ -604,7 +606,7 @@ public void addSign(byte[] privateKey, AccountStore accountStore) if (this.transaction.getSignatureCount() > 0) { checkWeight(permission, this.transaction.getSignatureList(), this.getTransactionId().getBytes(), - approveList); + approveList, dynamicPropertiesStore.signatureMaxSizeChecked()); if (approveList.contains(ByteString.copyFrom(address))) { throw new PermissionException(encode58Check(address) + " had signed!"); } @@ -620,8 +622,9 @@ public void addSign(byte[] privateKey, AccountStore accountStore) .signHash(getTransactionId().getBytes()))); this.transaction = this.transaction.toBuilder().addSignature(sig).build(); } - - private static void checkPermission(int permissionId, Permission permission, Transaction.Contract contract) throws PermissionException { + + private static void checkPermission(int permissionId, Permission permission, + Transaction.Contract contract) throws PermissionException { if (permissionId != 0) { if (permission.getType() != PermissionType.Active) { throw new PermissionException("Permission type is error"); @@ -703,7 +706,7 @@ public boolean validateSignature(AccountStore accountStore, } } isVerified = true; - } + } return true; } diff --git a/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java b/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java index 0f74f20d379..23bed6adc83 100644 --- a/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java +++ b/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java @@ -3011,6 +3011,10 @@ public void saveAllowTvmOsaka(long value) { this.put(ALLOW_TVM_OSAKA, new BytesCapsule(ByteArray.fromLong(value))); } + public boolean signatureMaxSizeChecked() { + return getAllowTvmOsaka() == 1L; + } + public long getAllowTvmPrague() { return Optional.ofNullable(getUnchecked(ALLOW_TVM_PRAGUE)) .map(BytesCapsule::getData) diff --git a/common/src/main/java/org/tron/core/config/Parameter.java b/common/src/main/java/org/tron/core/config/Parameter.java index 5349ef8d875..53194c4596a 100644 --- a/common/src/main/java/org/tron/core/config/Parameter.java +++ b/common/src/main/java/org/tron/core/config/Parameter.java @@ -69,6 +69,11 @@ public class ChainConstant { public static final int MAX_VOTE_NUMBER = 30; public static final int SOLIDIFIED_THRESHOLD = 70; // 70% public static final int PRIVATE_KEY_LENGTH = 64; + public static final int MIN_SIGNATURE_SIZE = 65; + // Canonical ECDSA signature is 65 bytes (r||s||v). 68 = 65 + up to 3 trailing + // padding bytes; this window accommodates historical non-canonical encodings + // observed on chain. Long-term goal is to tighten this back to a strict 65. + public static final int MAX_SIGNATURE_SIZE = 68; public static final int BLOCK_SIZE = 2_000_000; public static final long CLOCK_MAX_DELAY = 3600000; // 3600 * 1000 ms public static final int BLOCK_PRODUCE_TIMEOUT_PERCENT = 50; // 50% diff --git a/consensus/src/main/java/org/tron/consensus/pbft/PbftMessageHandle.java b/consensus/src/main/java/org/tron/consensus/pbft/PbftMessageHandle.java index 523ffac4d61..f2b224bf5e2 100644 --- a/consensus/src/main/java/org/tron/consensus/pbft/PbftMessageHandle.java +++ b/consensus/src/main/java/org/tron/consensus/pbft/PbftMessageHandle.java @@ -129,7 +129,8 @@ public void onPrePrepare(PbftMessage message) { PbftMessage paMessage = message.buildPrePareMessage(miner); forwardMessage(paMessage); try { - paMessage.analyzeSignature(); + paMessage.analyzeSignature( + chainBaseManager.getDynamicPropertiesStore().signatureMaxSizeChecked()); } catch (SignatureException e) { logger.error("", e); } @@ -175,7 +176,8 @@ public synchronized void onPrepare(PbftMessage message) { doneMsg.put(message.getNo(), cmMessage); forwardMessage(cmMessage); try { - cmMessage.analyzeSignature(); + cmMessage.analyzeSignature( + chainBaseManager.getDynamicPropertiesStore().signatureMaxSizeChecked()); } catch (SignatureException e) { logger.error("", e); } @@ -316,4 +318,4 @@ public void run() { } }, 10, 1000); } -} \ No newline at end of file +} diff --git a/consensus/src/main/java/org/tron/consensus/pbft/message/PbftBaseMessage.java b/consensus/src/main/java/org/tron/consensus/pbft/message/PbftBaseMessage.java index 4eb61f3e22e..48796420c46 100644 --- a/consensus/src/main/java/org/tron/consensus/pbft/message/PbftBaseMessage.java +++ b/consensus/src/main/java/org/tron/consensus/pbft/message/PbftBaseMessage.java @@ -1,17 +1,20 @@ package org.tron.consensus.pbft.message; +import com.google.protobuf.ByteString; import com.google.protobuf.InvalidProtocolBufferException; import java.io.IOException; import java.security.SignatureException; import java.util.stream.Collectors; import org.bouncycastle.util.encoders.Hex; import org.tron.common.crypto.ECKey; +import org.tron.common.crypto.SignUtils; import org.tron.common.overlay.message.Message; import org.tron.common.utils.ByteUtil; import org.tron.common.utils.Sha256Hash; import org.tron.common.utils.StringUtil; import org.tron.core.capsule.TransactionCapsule; import org.tron.core.exception.P2pException; +import org.tron.core.store.DynamicPropertiesStore; import org.tron.protos.Protocol.PBFTMessage; import org.tron.protos.Protocol.PBFTMessage.DataType; import org.tron.protos.Protocol.SRL; @@ -94,10 +97,15 @@ public DataType getDataType() { public abstract String getNo(); - public void analyzeSignature() throws SignatureException { + public void analyzeSignature(boolean checkMaxSignatureSize) + throws SignatureException { + ByteString signature = getPbftMessage().getSignature(); + if (!SignUtils.isValidLength(signature.size(), checkMaxSignatureSize)) { + throw new SignatureException("PBFT signature size is " + signature.size()); + } byte[] hash = Sha256Hash.hash(true, getPbftMessage().getRawData().toByteArray()); publicKey = ECKey.signatureToAddress(hash, TransactionCapsule - .getBase64FromByteString(getPbftMessage().getSignature())); + .getBase64FromByteString(signature)); } @Override diff --git a/crypto/src/main/java/org/tron/common/crypto/SignUtils.java b/crypto/src/main/java/org/tron/common/crypto/SignUtils.java index b921d548e8b..f42839a425e 100644 --- a/crypto/src/main/java/org/tron/common/crypto/SignUtils.java +++ b/crypto/src/main/java/org/tron/common/crypto/SignUtils.java @@ -5,9 +5,15 @@ import org.tron.common.crypto.ECKey.ECDSASignature; import org.tron.common.crypto.sm2.SM2; import org.tron.common.crypto.sm2.SM2.SM2Signature; +import org.tron.core.config.Parameter.ChainConstant; public class SignUtils { + public static boolean isValidLength(int size, boolean checkMaxSignatureSize) { + return size >= ChainConstant.MIN_SIGNATURE_SIZE + && (!checkMaxSignatureSize || size <= ChainConstant.MAX_SIGNATURE_SIZE); + } + public static SignInterface getGeneratedRandomSign( SecureRandom secureRandom, boolean isECKeyCryptoEngine) { if (isECKeyCryptoEngine) { diff --git a/framework/src/main/java/org/tron/core/Wallet.java b/framework/src/main/java/org/tron/core/Wallet.java index 0482643d8d0..7e04dc354ab 100755 --- a/framework/src/main/java/org/tron/core/Wallet.java +++ b/framework/src/main/java/org/tron/core/Wallet.java @@ -644,7 +644,8 @@ public TransactionApprovedList getTransactionApprovedList(Transaction trx) { byte[] hash = Sha256Hash.hash(CommonParameter .getInstance().isECKeyCryptoEngine(), trx.getRawData().toByteArray()); for (ByteString sig : trx.getSignatureList()) { - if (sig.size() < 65) { + // Read-only path: skip the upper bound so historical txs stay resolvable. + if (!SignUtils.isValidLength(sig.size(), false)) { throw new SignatureFormatException( "Signature size is " + sig.size()); } diff --git a/framework/src/main/java/org/tron/core/net/messagehandler/PbftDataSyncHandler.java b/framework/src/main/java/org/tron/core/net/messagehandler/PbftDataSyncHandler.java index d66fa6d41f7..3be08c1bf28 100644 --- a/framework/src/main/java/org/tron/core/net/messagehandler/PbftDataSyncHandler.java +++ b/framework/src/main/java/org/tron/core/net/messagehandler/PbftDataSyncHandler.java @@ -19,6 +19,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.tron.common.crypto.ECKey; +import org.tron.common.crypto.SignUtils; import org.tron.common.es.ExecutorServiceManager; import org.tron.common.utils.ByteArray; import org.tron.common.utils.Sha256Hash; @@ -173,6 +174,11 @@ private class ValidPbftSignTask implements Callable { @Override public Boolean call() throws Exception { try { + if (!SignUtils.isValidLength(sign.size(), + chainBaseManager.getDynamicPropertiesStore().signatureMaxSizeChecked())) { + logger.error("viewN {} pbft signature size {} is invalid", viewN, sign.size()); + return false; + } byte[] srAddress = ECKey.signatureToAddress(dataHash, TransactionCapsule.getBase64FromByteString(sign)); if (!srSet.contains(ByteString.copyFrom(srAddress))) { diff --git a/framework/src/main/java/org/tron/core/net/messagehandler/PbftMsgHandler.java b/framework/src/main/java/org/tron/core/net/messagehandler/PbftMsgHandler.java index d086cc28b6c..e467ee91cc3 100644 --- a/framework/src/main/java/org/tron/core/net/messagehandler/PbftMsgHandler.java +++ b/framework/src/main/java/org/tron/core/net/messagehandler/PbftMsgHandler.java @@ -11,6 +11,7 @@ import org.tron.consensus.pbft.PbftManager; import org.tron.consensus.pbft.message.PbftBaseMessage; import org.tron.consensus.pbft.message.PbftMessage; +import org.tron.core.ChainBaseManager; import org.tron.core.config.args.Args; import org.tron.core.exception.P2pException; import org.tron.core.net.TronNetDelegate; @@ -32,6 +33,9 @@ public class PbftMsgHandler { @Autowired private TronNetDelegate tronNetDelegate; + @Autowired + private ChainBaseManager chainBaseManager; + public void processMessage(PeerConnection peer, PbftMessage msg) throws Exception { if (!tronNetDelegate.allowPBFT()) { return; @@ -50,7 +54,7 @@ public void processMessage(PeerConnection peer, PbftMessage msg) throws Exceptio && currentEpoch - msg.getEpoch() > expireEpoch) { return; } - msg.analyzeSignature(); + msg.analyzeSignature(chainBaseManager.getDynamicPropertiesStore().signatureMaxSizeChecked()); String key = buildKey(msg); Lock lock = striped.get(key); try { @@ -79,4 +83,4 @@ private String buildKey(PbftBaseMessage msg) { return msg.getKey() + msg.getPbftMessage().getRawData().getMsgType().toString(); } -} \ No newline at end of file +} diff --git a/framework/src/main/java/org/tron/core/net/service/relay/RelayService.java b/framework/src/main/java/org/tron/core/net/service/relay/RelayService.java index 61ae6326e9f..7053fe61cb6 100644 --- a/framework/src/main/java/org/tron/core/net/service/relay/RelayService.java +++ b/framework/src/main/java/org/tron/core/net/service/relay/RelayService.java @@ -152,10 +152,17 @@ public boolean checkHelloMessage(HelloMessage message, Channel channel) { boolean flag; try { + ByteString signature = msg.getSignature(); + if (!SignUtils.isValidLength(signature.size(), + chainBaseManager.getDynamicPropertiesStore().signatureMaxSizeChecked())) { + logger.warn("HelloMessage from {}, signature size {} is invalid.", + channel.getInetAddress(), signature.size()); + return false; + } Sha256Hash hash = Sha256Hash.of(CommonParameter .getInstance().isECKeyCryptoEngine(), ByteArray.fromLong(msg.getTimestamp())); String sig = - TransactionCapsule.getBase64FromByteString(msg.getSignature()); + TransactionCapsule.getBase64FromByteString(signature); byte[] sigAddress = SignUtils.signatureToAddress(hash.getBytes(), sig, Args.getInstance().isECKeyCryptoEngine()); if (manager.getDynamicPropertiesStore().getAllowMultiSign() != 1) { diff --git a/framework/src/test/java/org/tron/common/utils/client/utils/TransactionUtils.java b/framework/src/test/java/org/tron/common/utils/client/utils/TransactionUtils.java index 63ffe1b58ff..c2a9f701f32 100644 --- a/framework/src/test/java/org/tron/common/utils/client/utils/TransactionUtils.java +++ b/framework/src/test/java/org/tron/common/utils/client/utils/TransactionUtils.java @@ -32,6 +32,7 @@ import org.tron.core.exception.SignatureFormatException; import org.tron.core.services.http.JsonFormat; import org.tron.core.store.AccountStore; +import org.tron.core.store.DynamicPropertiesStore; import org.tron.protos.Protocol.Transaction; import org.tron.protos.Protocol.Transaction.Contract; import org.tron.protos.contract.AccountContract.AccountCreateContract; @@ -193,11 +194,12 @@ public static String getTransactionSign(String transaction, String priKey, } public static TransactionCapsule addTransactionSign(Transaction transaction, String priKey, - AccountStore accountStore) + AccountStore accountStore, + DynamicPropertiesStore dynamicPropertiesStore) throws PermissionException, SignatureException, SignatureFormatException { byte[] privateKey = ByteArray.fromHexString(priKey); TransactionCapsule trx = new TransactionCapsule(transaction); - trx.addSign(privateKey, accountStore); + trx.addSign(privateKey, accountStore, dynamicPropertiesStore); return trx; } diff --git a/framework/src/test/java/org/tron/core/actuator/ShieldedTransferActuatorTest.java b/framework/src/test/java/org/tron/core/actuator/ShieldedTransferActuatorTest.java index 578f9f5ebed..fdd49988d6e 100755 --- a/framework/src/test/java/org/tron/core/actuator/ShieldedTransferActuatorTest.java +++ b/framework/src/test/java/org/tron/core/actuator/ShieldedTransferActuatorTest.java @@ -207,7 +207,8 @@ public void publicAddressToShieldedAddressSuccess() { //Add public address sign transactionCap = TransactionUtils.addTransactionSign(transactionCap.getInstance(), - ADDRESS_ONE_PRIVATE_KEY, dbManager.getAccountStore()); + ADDRESS_ONE_PRIVATE_KEY, dbManager.getAccountStore(), + dbManager.getDynamicPropertiesStore()); Assert.assertTrue(dbManager.pushTransaction(transactionCap)); } catch (Exception e) { @@ -235,7 +236,8 @@ public void publicAddressToPublicAddressAndZereValueOutputSuccess() { //Add public address sign transactionCap = TransactionUtils.addTransactionSign(transactionCap.getInstance(), - ADDRESS_ONE_PRIVATE_KEY, dbManager.getAccountStore()); + ADDRESS_ONE_PRIVATE_KEY, dbManager.getAccountStore(), + dbManager.getDynamicPropertiesStore()); Assert.assertTrue(dbManager.pushTransaction(transactionCap)); } catch (Exception e) { @@ -255,7 +257,7 @@ public void publicAddressToShieldedAddressInvalidSign() { //Add public address sign TransactionUtils.addTransactionSign(transactionCap.getInstance(), ADDRESS_TWO_PRIVATE_KEY, - dbManager.getAccountStore()); + dbManager.getAccountStore(), dbManager.getDynamicPropertiesStore()); Assert.assertTrue(false); } catch (PermissionException e) { Assert.assertTrue(e instanceof PermissionException); @@ -395,7 +397,8 @@ public void publicAddressToShieldedAddressNotConsumeBandwidth() { TransactionCapsule transactionCap = getPublicToShieldedTransaction(); //Add public address sign transactionCap = TransactionUtils.addTransactionSign(transactionCap.getInstance(), - ADDRESS_ONE_PRIVATE_KEY, dbManager.getAccountStore()); + ADDRESS_ONE_PRIVATE_KEY, dbManager.getAccountStore(), + dbManager.getDynamicPropertiesStore()); AccountCapsule accountCapsule = dbManager.getAccountStore().get(ByteArray.fromHexString(PUBLIC_ADDRESS_ONE)); @@ -983,7 +986,8 @@ public void publicToShieldAddressAndShieldToPublicAddressWithZoreValueSuccess() //Add public address sign transactionCapOne = TransactionUtils.addTransactionSign(transactionCapOne.getInstance(), - ADDRESS_ONE_PRIVATE_KEY, dbManager.getAccountStore()); + ADDRESS_ONE_PRIVATE_KEY, dbManager.getAccountStore(), + dbManager.getDynamicPropertiesStore()); Assert.assertTrue(dbManager.pushTransaction(transactionCapOne)); AccountCapsule accountCapsuleOne = @@ -1403,4 +1407,3 @@ public void shieldedTransferValidationWorksWhenApiDisabled() { } } } - diff --git a/framework/src/test/java/org/tron/core/actuator/utils/TransactionUtilTest.java b/framework/src/test/java/org/tron/core/actuator/utils/TransactionUtilTest.java index 15842bfa2c8..277e0e2b0bb 100644 --- a/framework/src/test/java/org/tron/core/actuator/utils/TransactionUtilTest.java +++ b/framework/src/test/java/org/tron/core/actuator/utils/TransactionUtilTest.java @@ -17,11 +17,14 @@ import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.List; +import javax.annotation.Resource; import lombok.extern.slf4j.Slf4j; import org.junit.Assert; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; +import org.tron.api.GrpcAPI.TransactionSignWeight; +import org.tron.api.GrpcAPI.TransactionSignWeight.Result.response_code; import org.tron.common.BaseTest; import org.tron.common.TestConstants; import org.tron.common.utils.ByteArray; @@ -38,12 +41,16 @@ import org.tron.protos.Protocol.Transaction; import org.tron.protos.Protocol.Transaction.Contract.ContractType; import org.tron.protos.contract.BalanceContract.DelegateResourceContract; +import org.tron.protos.contract.BalanceContract.TransferContract; @Slf4j(topic = "capsule") public class TransactionUtilTest extends BaseTest { private static String OWNER_ADDRESS; + @Resource + private TransactionUtil transactionUtil; + /** * Init . */ @@ -452,4 +459,59 @@ public void testConcurrentToString() throws InterruptedException { } Assert.assertTrue(true); } + + @Test + public void getTransactionSignWeightShortSigRejected() { + // Lower bound is enforced on the read-only path; upper bound is not + // (so a tx committed pre-Osaka with a padded sig stays introspectable). + byte[] owner = ByteArray.fromHexString(OWNER_ADDRESS); + TransferContract transferContract = TransferContract.newBuilder() + .setAmount(1L) + .setOwnerAddress(ByteString.copyFrom(owner)) + .setToAddress(ByteString.copyFrom(new byte[21])) + .build(); + Transaction transaction = new TransactionCapsule( + transferContract, ContractType.TransferContract) + .getInstance().toBuilder() + .addSignature(ByteString.copyFrom(new byte[64])) + .build(); + + dbManager.getDynamicPropertiesStore().saveAllowTvmOsaka(1); + try { + TransactionSignWeight signWeight = transactionUtil.getTransactionSignWeight(transaction); + Assert.assertEquals(response_code.SIGNATURE_FORMAT_ERROR, + signWeight.getResult().getCode()); + } finally { + dbManager.getDynamicPropertiesStore().saveAllowTvmOsaka(0); + } + } + + @Test + public void getTransactionSignWeightPaddedSigPostOsakaAccepted() { + // Read-only path must not reject a 69-byte signature post-Osaka — the + // upper bound is meant to gate new submissions, not block introspection + // of historical transactions. + byte[] owner = ByteArray.fromHexString(OWNER_ADDRESS); + TransferContract transferContract = TransferContract.newBuilder() + .setAmount(1L) + .setOwnerAddress(ByteString.copyFrom(owner)) + .setToAddress(ByteString.copyFrom(new byte[21])) + .build(); + byte[] paddedSig = new byte[69]; + paddedSig[64] = 27; + Transaction transaction = new TransactionCapsule( + transferContract, ContractType.TransferContract) + .getInstance().toBuilder() + .addSignature(ByteString.copyFrom(paddedSig)) + .build(); + + dbManager.getDynamicPropertiesStore().saveAllowTvmOsaka(1); + try { + TransactionSignWeight signWeight = transactionUtil.getTransactionSignWeight(transaction); + Assert.assertNotEquals(response_code.SIGNATURE_FORMAT_ERROR, + signWeight.getResult().getCode()); + } finally { + dbManager.getDynamicPropertiesStore().saveAllowTvmOsaka(0); + } + } } diff --git a/framework/src/test/java/org/tron/core/capsule/BlockCapsuleTest.java b/framework/src/test/java/org/tron/core/capsule/BlockCapsuleTest.java index ca0844c2c16..9ffd573a6e4 100644 --- a/framework/src/test/java/org/tron/core/capsule/BlockCapsuleTest.java +++ b/framework/src/test/java/org/tron/core/capsule/BlockCapsuleTest.java @@ -1,5 +1,8 @@ package org.tron.core.capsule; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + import com.google.protobuf.ByteString; import java.io.IOException; import java.util.ArrayList; @@ -21,6 +24,10 @@ import org.tron.core.config.args.Args; import org.tron.core.exception.BadBlockException; import org.tron.core.exception.BadItemException; +import org.tron.core.exception.ValidateSignatureException; +import org.tron.core.store.AccountStore; +import org.tron.core.store.DynamicPropertiesStore; +import org.tron.protos.Protocol.Block; import org.tron.protos.Protocol.Transaction.Contract.ContractType; import org.tron.protos.contract.BalanceContract.TransferContract; @@ -196,4 +203,84 @@ public void testConcurrentToString() throws InterruptedException { Assert.assertTrue(true); } + // ---- witness signature size enforcement tests ---- + + private BlockCapsule signedBlock() { + String key = PublicMethod.getRandomPrivateKey(); + LocalWitnesses lw = new LocalWitnesses(); + lw.setPrivateKeys(Arrays.asList(key)); + lw.initWitnessAccountAddress(null, true); + Args.setLocalWitnesses(lw); + + BlockCapsule block = new BlockCapsule(2, + Sha256Hash.wrap(ByteString.copyFrom(ByteArray.fromHexString( + "9938a342238077182498b464ac0292229938a342238077182498b464ac029222"))), + 9999L, + ByteString.copyFrom(lw.getWitnessAccountAddress())); + block.sign(ByteArray.fromHexString(key)); + return block; + } + + private BlockCapsule withPaddedWitnessSig(BlockCapsule src, int extraBytes) { + byte[] original = src.getInstance().getBlockHeader() + .getWitnessSignature().toByteArray(); + byte[] padded = Arrays.copyOf(original, original.length + extraBytes); + Block modified = src.getInstance().toBuilder() + .setBlockHeader(src.getInstance().getBlockHeader().toBuilder() + .setWitnessSignature(ByteString.copyFrom(padded))) + .build(); + return new BlockCapsule(modified); + } + + @Test + public void witnessSignaturePaddedOsakaRejected() throws Exception { + // Pad past MAX_SIGNATURE_SIZE (68) so the post-Osaka upper-bound check fires. + BlockCapsule paddedBlock = withPaddedWitnessSig(signedBlock(), 4); + Assert.assertEquals(69, + paddedBlock.getInstance().getBlockHeader().getWitnessSignature().size()); + + DynamicPropertiesStore dps = mock(DynamicPropertiesStore.class); + when(dps.signatureMaxSizeChecked()).thenReturn(true); + AccountStore accountStore = mock(AccountStore.class); + + ValidateSignatureException e = Assert.assertThrows( + ValidateSignatureException.class, + () -> paddedBlock.validateSignature(dps, accountStore)); + Assert.assertTrue("Error must mention the sig size", + e.getMessage().contains("69")); + } + + @Test + public void witnessSignaturePaddedPreOsaka() throws Exception { + BlockCapsule paddedBlock = withPaddedWitnessSig(signedBlock(), 4); + + DynamicPropertiesStore dps = mock(DynamicPropertiesStore.class); + when(dps.signatureMaxSizeChecked()).thenReturn(false); + when(dps.getAllowMultiSign()).thenReturn(0L); + AccountStore accountStore = mock(AccountStore.class); + + try { + paddedBlock.validateSignature(dps, accountStore); + // valid result is fine + } catch (ValidateSignatureException e) { + Assert.assertFalse("Size check must not fire before Osaka", + e.getMessage().contains("Witness signature size")); + } + } + + @Test(expected = ValidateSignatureException.class) + public void witnessSignatureShortRejected() throws Exception { + Block modified = blockCapsule0.getInstance().toBuilder() + .setBlockHeader(blockCapsule0.getInstance().getBlockHeader().toBuilder() + .setWitnessSignature(ByteString.copyFrom(new byte[64]))) + .build(); + BlockCapsule shortBlock = new BlockCapsule(modified); + + DynamicPropertiesStore dps = mock(DynamicPropertiesStore.class); + when(dps.getAllowTvmOsaka()).thenReturn(0L); + AccountStore accountStore = mock(AccountStore.class); + + shortBlock.validateSignature(dps, accountStore); + } + } diff --git a/framework/src/test/java/org/tron/core/capsule/TransactionCapsuleTest.java b/framework/src/test/java/org/tron/core/capsule/TransactionCapsuleTest.java index 9c2e004931e..2f553c13dc4 100644 --- a/framework/src/test/java/org/tron/core/capsule/TransactionCapsuleTest.java +++ b/framework/src/test/java/org/tron/core/capsule/TransactionCapsuleTest.java @@ -9,6 +9,7 @@ import ch.qos.logback.classic.spi.ILoggingEvent; import ch.qos.logback.core.read.ListAppender; import com.google.protobuf.ByteString; +import java.util.Collections; import java.util.List; import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; @@ -23,7 +24,11 @@ import org.tron.common.utils.StringUtil; import org.tron.core.Wallet; import org.tron.core.config.args.Args; +import org.tron.core.exception.SignatureFormatException; import org.tron.protos.Protocol.AccountType; +import org.tron.protos.Protocol.Key; +import org.tron.protos.Protocol.Permission; +import org.tron.protos.Protocol.Permission.PermissionType; import org.tron.protos.Protocol.Transaction; import org.tron.protos.Protocol.Transaction.Contract.ContractType; import org.tron.protos.Protocol.Transaction.Result; @@ -134,4 +139,69 @@ public void fastVerify() { capsuleLogger.setLevel(originalLevel); } } + + // ---- checkWeight signature-size enforcement tests ---- + + private static final byte[] DUMMY_HASH = new byte[32]; + + private static Permission singleKeyPermission() { + return Permission.newBuilder() + .setType(PermissionType.Owner) + .setThreshold(1) + .addKeys(Key.newBuilder() + .setAddress(ByteString.copyFrom(new byte[21])) + .setWeight(1)) + .build(); + } + + @Test(expected = SignatureFormatException.class) + public void checkWeightShortSigRejected() throws Exception { + List sigs = Collections.singletonList(ByteString.copyFrom(new byte[64])); + TransactionCapsule.checkWeight(singleKeyPermission(), sigs, DUMMY_HASH, null, + dbManager.getDynamicPropertiesStore().signatureMaxSizeChecked()); + } + + @Test(expected = SignatureFormatException.class) + public void checkWeightPaddedSigOsakaRejected() throws Exception { + dbManager.getDynamicPropertiesStore().saveAllowTvmOsaka(1); + try { + List sigs = Collections.singletonList(ByteString.copyFrom(new byte[69])); + TransactionCapsule.checkWeight(singleKeyPermission(), sigs, DUMMY_HASH, null, + dbManager.getDynamicPropertiesStore().signatureMaxSizeChecked()); + } finally { + dbManager.getDynamicPropertiesStore().saveAllowTvmOsaka(0); + } + } + + @Test + public void checkWeightPaddedSigPreOsaka() { + dbManager.getDynamicPropertiesStore().saveAllowTvmOsaka(0); + List sigs = Collections.singletonList(ByteString.copyFrom(new byte[69])); + try { + TransactionCapsule.checkWeight(singleKeyPermission(), sigs, DUMMY_HASH, null, + dbManager.getDynamicPropertiesStore().signatureMaxSizeChecked()); + } catch (SignatureFormatException e) { + Assert.fail("Padded sig must not be rejected by size check before Osaka: " + e.getMessage()); + } catch (Exception e) { + // SignatureException / PermissionException after the size check — expected + } + } + + @Test + public void checkWeightNormalSigOsaka() { + dbManager.getDynamicPropertiesStore().saveAllowTvmOsaka(1); + try { + byte[] validSizeSig = new byte[65]; + validSizeSig[64] = 27; // v = 27 (valid range) + List sigs = Collections.singletonList(ByteString.copyFrom(validSizeSig)); + TransactionCapsule.checkWeight(singleKeyPermission(), sigs, DUMMY_HASH, null, + dbManager.getDynamicPropertiesStore().signatureMaxSizeChecked()); + } catch (SignatureFormatException e) { + Assert.fail("65-byte sig must not be rejected by size check post-Osaka: " + e.getMessage()); + } catch (Exception e) { + // crypto / permission error after size check — expected + } finally { + dbManager.getDynamicPropertiesStore().saveAllowTvmOsaka(0); + } + } } diff --git a/framework/src/test/java/org/tron/core/db/TransactionExpireTest.java b/framework/src/test/java/org/tron/core/db/TransactionExpireTest.java index e107979107a..b4cb1025f12 100644 --- a/framework/src/test/java/org/tron/core/db/TransactionExpireTest.java +++ b/framework/src/test/java/org/tron/core/db/TransactionExpireTest.java @@ -184,4 +184,107 @@ public void testTransactionApprovedList() { Assert.assertEquals(TransactionApprovedList.Result.response_code.COMPUTE_ADDRESS_ERROR, transactionApprovedList.getResult().getCode()); } + + @Test + public void testApprovedListPaddedSigPostOsakaAccepted() { + // Read-only introspection must not reject a 69-byte sig post-Osaka — the + // upper bound is meant to gate new submissions, not block lookups of + // historical transactions committed before the size cap existed. + initLocalWitness(); + byte[] address = Args.getLocalWitnesses().getWitnessAccountAddress(); + 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 capsule = + new TransactionCapsule(transferContract, ContractType.TransferContract); + capsule.sign(ByteArray.fromHexString(Args.getLocalWitnesses().getPrivateKey())); + + byte[] sig65 = capsule.getInstance().getSignature(0).toByteArray(); + byte[] sig69 = Arrays.copyOf(sig65, 69); + Transaction tx = capsule.getInstance().toBuilder() + .clearSignature().addSignature(ByteString.copyFrom(sig69)).build(); + + dbManager.getDynamicPropertiesStore().saveAllowTvmOsaka(1); + try { + TransactionApprovedList result = wallet.getTransactionApprovedList(tx); + Assert.assertNotEquals("Padded sig must not be size-rejected on read-only path post-Osaka", + TransactionApprovedList.Result.response_code.SIGNATURE_FORMAT_ERROR, + result.getResult().getCode()); + } finally { + dbManager.getDynamicPropertiesStore().saveAllowTvmOsaka(0); + } + } + + @Test + public void testApprovedListShortSigRejected() { + // Lower bound is still enforced on the read-only path. + initLocalWitness(); + byte[] address = Args.getLocalWitnesses().getWitnessAccountAddress(); + 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(); + Transaction tx = new TransactionCapsule(transferContract, ContractType.TransferContract) + .getInstance().toBuilder() + .addSignature(ByteString.copyFrom(new byte[64])) + .build(); + + TransactionApprovedList result = wallet.getTransactionApprovedList(tx); + Assert.assertEquals("Sig below MIN_SIGNATURE_SIZE must be rejected", + TransactionApprovedList.Result.response_code.SIGNATURE_FORMAT_ERROR, + result.getResult().getCode()); + } + + @Test + public void testApprovedListPaddedSigPreOsaka() { + initLocalWitness(); + byte[] address = Args.getLocalWitnesses().getWitnessAccountAddress(); + 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 capsule = + new TransactionCapsule(transferContract, ContractType.TransferContract); + capsule.sign(ByteArray.fromHexString(Args.getLocalWitnesses().getPrivateKey())); + + byte[] sig65 = capsule.getInstance().getSignature(0).toByteArray(); + byte[] sig66 = Arrays.copyOf(sig65, 66); + Transaction tx = capsule.getInstance().toBuilder() + .clearSignature().addSignature(ByteString.copyFrom(sig66)).build(); + + dbManager.getDynamicPropertiesStore().saveAllowTvmOsaka(0); + TransactionApprovedList result = wallet.getTransactionApprovedList(tx); + Assert.assertNotEquals("Padded sig must not be rejected by size check before Osaka", + TransactionApprovedList.Result.response_code.SIGNATURE_FORMAT_ERROR, + result.getResult().getCode()); + } } diff --git a/framework/src/test/java/org/tron/core/net/messagehandler/PbftDataSyncHandlerTest.java b/framework/src/test/java/org/tron/core/net/messagehandler/PbftDataSyncHandlerTest.java index 7f3ad8a71e2..a6a4b1ae1d0 100644 --- a/framework/src/test/java/org/tron/core/net/messagehandler/PbftDataSyncHandlerTest.java +++ b/framework/src/test/java/org/tron/core/net/messagehandler/PbftDataSyncHandlerTest.java @@ -3,12 +3,15 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.google.protobuf.ByteString; import java.lang.reflect.Field; +import java.lang.reflect.Method; import java.util.ArrayList; +import java.util.Collections; import java.util.Map; import org.junit.Assert; import org.junit.Test; import org.mockito.Mockito; import org.tron.common.utils.Sha256Hash; +import org.tron.consensus.base.Param; import org.tron.core.ChainBaseManager; import org.tron.core.capsule.BlockCapsule; import org.tron.core.capsule.PbftSignCapsule; @@ -55,4 +58,35 @@ public void testProcessMessage() throws Exception { Map map = new ObjectMapper().convertValue(field1.get(pbftDataSyncHandler), Map.class); Assert.assertFalse(map.containsKey(0)); } + + @Test + public void testValidPbftSignPaddedSigOsakaRejected() throws Exception { + PbftDataSyncHandler pbftDataSyncHandler = new PbftDataSyncHandler(); + DynamicPropertiesStore dynamicPropertiesStore = Mockito.mock(DynamicPropertiesStore.class); + ChainBaseManager chainBaseManager = Mockito.mock(ChainBaseManager.class); + Mockito.when(chainBaseManager.getDynamicPropertiesStore()).thenReturn(dynamicPropertiesStore); + Mockito.when(dynamicPropertiesStore.signatureMaxSizeChecked()).thenReturn(true); + + Field field = PbftDataSyncHandler.class.getDeclaredField("chainBaseManager"); + field.setAccessible(true); + field.set(pbftDataSyncHandler, chainBaseManager); + + Param.getInstance().setAgreeNodeCount(1); + Method method = PbftDataSyncHandler.class.getDeclaredMethod("validPbftSign", + Protocol.PBFTMessage.Raw.class, java.util.List.class, java.util.List.class); + method.setAccessible(true); + + Protocol.PBFTMessage.Raw raw = Protocol.PBFTMessage.Raw.newBuilder() + .setViewN(1) + .setEpoch(0) + .setDataType(Protocol.PBFTMessage.DataType.BLOCK) + .setMsgType(Protocol.PBFTMessage.MsgType.COMMIT) + .setData(ByteString.copyFromUtf8("block")) + .build(); + + boolean valid = (boolean) method.invoke(pbftDataSyncHandler, raw, + Collections.singletonList(ByteString.copyFrom(new byte[69])), + Collections.singletonList(ByteString.copyFrom(new byte[21]))); + Assert.assertFalse(valid); + } } diff --git a/framework/src/test/java/org/tron/core/net/messagehandler/PbftMsgHandlerTest.java b/framework/src/test/java/org/tron/core/net/messagehandler/PbftMsgHandlerTest.java index 65a8f615bfe..85eace10ee1 100644 --- a/framework/src/test/java/org/tron/core/net/messagehandler/PbftMsgHandlerTest.java +++ b/framework/src/test/java/org/tron/core/net/messagehandler/PbftMsgHandlerTest.java @@ -5,6 +5,8 @@ import com.google.protobuf.ByteString; import java.io.File; import java.net.InetSocketAddress; +import java.security.SignatureException; +import java.util.Arrays; import org.bouncycastle.util.encoders.Hex; import org.junit.After; import org.junit.AfterClass; @@ -120,4 +122,53 @@ public void testPbft() throws Exception { Assert.assertEquals(1, PeerManager.getPeers().size()); } + + @Test + public void testPbftPaddedSigOsakaRejected() throws Exception { + InetSocketAddress a1 = new InetSocketAddress("127.0.0.1", 10001); + Channel c1 = mock(Channel.class); + Mockito.when(c1.getInetSocketAddress()).thenReturn(a1); + Mockito.when(c1.getInetAddress()).thenReturn(a1.getAddress()); + PeerManager.add(context, c1); + + peer = PeerManager.getPeers().get(0); + BlockCapsule blockCapsule = new BlockCapsule(1, Sha256Hash.ZERO_HASH, + System.currentTimeMillis(), ByteString.EMPTY); + Protocol.PBFTMessage.Raw raw = Protocol.PBFTMessage.Raw.newBuilder() + .setViewN(blockCapsule.getNum()) + .setEpoch(0) + .setDataType(Protocol.PBFTMessage.DataType.BLOCK) + .setMsgType(Protocol.PBFTMessage.MsgType.PREPREPARE) + .setData(blockCapsule.getBlockId().getByteString()) + .build(); + SignInterface sign = SignUtils.fromPrivate(Hex.decode(PublicMethod.getRandomPrivateKey()), + true); + byte[] sig = sign.Base64toBytes(sign.signHash(Sha256Hash.hash(true, raw.toByteArray()))); + byte[] paddedSig = Arrays.copyOf(sig, 69); + Protocol.PBFTMessage message = Protocol.PBFTMessage.newBuilder() + .setRawData(raw) + .setSignature(ByteString.copyFrom(paddedSig)) + .build(); + + PbftMessage pbftMessage = new PbftMessage(); + pbftMessage.setType(MessageTypes.PBFT_MSG.asByte()); + pbftMessage.setPbftMessage(message); + pbftMessage.setData(message.toByteArray()); + pbftMessage.setSwitch(blockCapsule.isSwitch()); + Param.getInstance().setPbftInterface(context.getBean(PbftBaseImpl.class)); + peer.setNeedSyncFromPeer(false); + + DynamicPropertiesStore dynamicPropertiesStore = context.getBean(DynamicPropertiesStore.class); + dynamicPropertiesStore.saveAllowPBFT(1); + dynamicPropertiesStore.saveAllowTvmOsaka(1); + try { + SignatureException e = Assert.assertThrows( + SignatureException.class, + () -> context.getBean(PbftMsgHandler.class).processMessage(peer, pbftMessage)); + Assert.assertTrue("Padded PBFT signature must be rejected post-Osaka", + e.getMessage().contains("PBFT signature size is 69")); + } finally { + dynamicPropertiesStore.saveAllowTvmOsaka(0); + } + } } diff --git a/framework/src/test/java/org/tron/core/net/services/RelayServiceTest.java b/framework/src/test/java/org/tron/core/net/services/RelayServiceTest.java index 8585244b941..3d33bfb7e0e 100644 --- a/framework/src/test/java/org/tron/core/net/services/RelayServiceTest.java +++ b/framework/src/test/java/org/tron/core/net/services/RelayServiceTest.java @@ -10,6 +10,7 @@ import java.lang.reflect.Method; import java.net.InetSocketAddress; import java.util.ArrayList; +import java.util.Arrays; import java.util.Comparator; import java.util.List; import java.util.Set; @@ -226,6 +227,66 @@ private void testCheckHelloMessage() { } } + @Test + public void testCheckHelloMessagePaddedSigOsakaRejected() { + initWitness(); + String key = "0154435f065a57fec6af1e12eaa2fa600030639448d7809f4c65bdcf8baed7e5"; + ByteString address = getFromHexString("418A8D690BF36806C36A7DAE3AF796643C1AA9CC01"); + InetSocketAddress a1 = new InetSocketAddress("127.0.0.1", 10001); + Node node = new Node(NetUtil.getNodeId(), a1.getAddress().getHostAddress(), + null, a1.getPort()); + + SignInterface cryptoEngine = SignUtils.fromPrivate(ByteArray.fromHexString(key), + Args.getInstance().isECKeyCryptoEngine()); + HelloMessage helloMessage = new HelloMessage(node, System.currentTimeMillis(), + ChainBaseManager.getChainBaseManager()); + byte[] sig = cryptoEngine.Base64toBytes(cryptoEngine.signHash(Sha256Hash.of(CommonParameter + .getInstance().isECKeyCryptoEngine(), ByteArray.fromLong(helloMessage + .getTimestamp())).getBytes())); + byte[] paddedSig = Arrays.copyOf(sig, 69); + helloMessage.setHelloMessage(helloMessage.getHelloMessage().toBuilder() + .setAddress(address) + .setSignature(ByteString.copyFrom(paddedSig)) + .build()); + + Channel c1 = mock(Channel.class); + Mockito.when(c1.getInetSocketAddress()).thenReturn(a1); + Mockito.when(c1.getInetAddress()).thenReturn(a1.getAddress()); + Channel c2 = mock(Channel.class); + Mockito.when(c2.getInetSocketAddress()).thenReturn(a1); + Mockito.when(c2.getInetAddress()).thenReturn(a1.getAddress()); + + Args.getInstance().fastForward = true; + ApplicationContext ctx = (ApplicationContext) ReflectUtils.getFieldObject(p2pEventHandler, + "ctx"); + PeerConnection peer1 = PeerManager.add(ctx, c1); + assert peer1 != null; + peer1.setAddress(address); + PeerConnection peer2 = PeerManager.add(ctx, c2); + assert peer2 != null; + peer2.setAddress(address); + + ReflectUtils.setFieldValue(tronNetService, "p2pConfig", new P2pConfig()); + + try { + Field field = service.getClass().getDeclaredField("witnessScheduleStore"); + field.setAccessible(true); + field.set(service, chainBaseManager.getWitnessScheduleStore()); + + Field field2 = service.getClass().getDeclaredField("manager"); + field2.setAccessible(true); + field2.set(service, dbManager); + + chainBaseManager.getDynamicPropertiesStore().saveAllowTvmOsaka(1); + Assert.assertFalse(service.checkHelloMessage(helloMessage, c1)); + } catch (Exception e) { + logger.info("", e); + assert false; + } finally { + chainBaseManager.getDynamicPropertiesStore().saveAllowTvmOsaka(0); + } + } + @Test public void testNullWitnessAddress() { try { diff --git a/framework/src/test/java/org/tron/core/zksnark/ShieldedReceiveTest.java b/framework/src/test/java/org/tron/core/zksnark/ShieldedReceiveTest.java index 7143cef43e2..ba10ed77fda 100755 --- a/framework/src/test/java/org/tron/core/zksnark/ShieldedReceiveTest.java +++ b/framework/src/test/java/org/tron/core/zksnark/ShieldedReceiveTest.java @@ -333,7 +333,8 @@ public void testBroadcastBeforeAllowZksnark() //Add public address sign transactionCap = TransactionUtils.addTransactionSign(transactionCap.getInstance(), - ADDRESS_ONE_PRIVATE_KEY, chainBaseManager.getAccountStore()); + ADDRESS_ONE_PRIVATE_KEY, chainBaseManager.getAccountStore(), + chainBaseManager.getDynamicPropertiesStore()); try { dbManager.pushTransaction(transactionCap); } catch (Exception e) {