Skip to content
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
2 changes: 1 addition & 1 deletion framework/src/main/java/org/tron/core/db/Manager.java
Original file line number Diff line number Diff line change
Expand Up @@ -1235,7 +1235,7 @@ public List<TransactionCapsule> getVerifyTxs(BlockCapsule block) {

List<TransactionCapsule> txs = new ArrayList<>();
Map<String, TransactionCapsule> txMap = new HashMap<>();
Set<String> multiAddresses = new HashSet<>();
Set<String> multiAddresses = new HashSet<>(ownerAddressSet);

pendingTransactions.forEach(capsule -> {
String txId = Hex.toHexString(capsule.getTransactionId().getBytes());
Expand Down
42 changes: 42 additions & 0 deletions framework/src/test/java/org/tron/core/db/ManagerTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
Expand Down Expand Up @@ -876,6 +877,47 @@ public void getVerifyTxsTest() {
Assert.assertEquals(txs.size(), 1);
}

@Test
public void getVerifyTxsSkipsBlockWhenPermissionTxAlreadyConsumed() throws Exception {
// Scenario: a permission-change tx (A) for owner X has been processed and consumed,
// so it is no longer in pendingTransactions but ownerAddressSet still contains X.
// A later transfer tx (B) from X with the old signature enters pending with
// isVerified=true. A malicious SR produces a block containing only B (no A).
// getVerifyTxs must place B into the re-verify list rather than calling
// setVerified(true) just because B matches the pending entry.
TransferContract bContract = TransferContract.newBuilder()
.setOwnerAddress(ByteString.copyFrom("f1".getBytes()))
.setAmount(7).build();
TransactionCapsule bTx = new TransactionCapsule(bContract, ContractType.TransferContract);
String hexOwner = ByteArray.toHexString("f1".getBytes());

dbManager.getPendingTransactions().clear();
dbManager.getPendingTransactions().add(bTx);

Field field = Manager.class.getDeclaredField("ownerAddressSet");
field.setAccessible(true);
@SuppressWarnings("unchecked")
Set<String> ownerAddressSet = (Set<String>) field.get(dbManager);
Set<String> backup = new HashSet<>(ownerAddressSet);
ownerAddressSet.clear();
ownerAddressSet.add(hexOwner);

try {
List<Transaction> blockTxs = new ArrayList<>();
blockTxs.add(bTx.getInstance());
BlockCapsule capsule = new BlockCapsule(0, ByteString.EMPTY, 0, blockTxs);

List<TransactionCapsule> txs = dbManager.getVerifyTxs(capsule);

Assert.assertEquals(1, txs.size());
Assert.assertEquals(bTx.getTransactionId(), txs.get(0).getTransactionId());
} finally {
ownerAddressSet.clear();
ownerAddressSet.addAll(backup);
dbManager.getPendingTransactions().clear();
}
}

@Test
public void doNotSwitch()
throws ValidateSignatureException, ContractValidateException, ContractExeException,
Expand Down
Loading