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
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package org.tron.core.services.stop;

import java.text.ParseException;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.TimeZone;
import lombok.extern.slf4j.Slf4j;
import org.junit.Assert;
import org.tron.common.cron.CronExpression;
Expand All @@ -12,14 +14,14 @@
public class BlockTimeStopTest extends ConditionallyStopTest {
private static final DateTimeFormatter pattern = DateTimeFormatter
.ofPattern("ss mm HH dd MM ? yyyy");
private static final String time = localDateTime.plusSeconds(12 * 3).format(pattern);

private static CronExpression cronExpression;


static {
try {
cronExpression = new CronExpression(time);
cronExpression = new CronExpression(localDateTime.plusSeconds(12 * 3).format(pattern));
cronExpression.setTimeZone(TimeZone.getTimeZone(ZoneOffset.UTC));
} catch (ParseException e) {
logger.error("{}", e.getMessage());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,18 @@

import com.google.common.collect.Maps;
import com.google.protobuf.ByteString;
import java.io.File;
import java.io.IOException;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.ZoneOffset;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import lombok.extern.slf4j.Slf4j;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.ClassRule;
import org.junit.Test;
Expand All @@ -25,11 +22,10 @@
import org.tron.common.crypto.ECKey;
import org.tron.common.parameter.CommonParameter;
import org.tron.common.utils.ByteArray;
import org.tron.common.utils.FileUtil;
import org.tron.common.utils.LocalWitnesses;
import org.tron.common.utils.PublicMethod;
import org.tron.common.utils.Sha256Hash;
import org.tron.common.utils.Utils;
import org.tron.consensus.ConsensusDelegate;
import org.tron.consensus.dpos.DposService;
import org.tron.consensus.dpos.DposSlot;
import org.tron.core.ChainBaseManager;
import org.tron.core.Constant;
Expand All @@ -39,34 +35,31 @@
import org.tron.core.config.DefaultConfig;
import org.tron.core.config.args.Args;
import org.tron.core.consensus.ConsensusService;
import org.tron.core.db.BlockGenerate;
import org.tron.core.db.Manager;
import org.tron.core.net.TronNetDelegate;
import org.tron.protos.Protocol;

@Slf4j
public abstract class ConditionallyStopTest extends BlockGenerate {
@Slf4j(topic = "test")
public abstract class ConditionallyStopTest {

@ClassRule
public static final TemporaryFolder temporaryFolder = new TemporaryFolder();

static ChainBaseManager chainManager;
private static DposSlot dposSlot;

private final String key = PublicMethod.getRandomPrivateKey();
private final byte[] privateKey = ByteArray.fromHexString(key);

private final AtomicInteger port = new AtomicInteger(0);
protected String dbPath;
protected Manager dbManager;
long currentHeader = -1;
private TronNetDelegate tronNetDelegate;
private TronApplicationContext context;

private DposService dposService;
private ConsensusDelegate consensusDelegate;

static LocalDateTime localDateTime = LocalDateTime.now();
private long time = ZonedDateTime.of(localDateTime,
ZoneId.systemDefault()).toInstant().toEpochMilli();
private static final Instant instant = Instant.parse("2025-10-01T00:00:00Z");
private final long time = instant.toEpochMilli();
static LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, ZoneOffset.UTC);

protected abstract void initParameter(CommonParameter parameter);

Expand All @@ -76,6 +69,8 @@ protected void initDbPath() throws IOException {
dbPath = temporaryFolder.newFolder().toString();
}

private Map<String, String> witnesses;


@Before
public void init() throws Exception {
Expand All @@ -84,30 +79,37 @@ public void init() throws Exception {
logger.info("Full node running.");
Args.setParam(new String[] {"-d", dbPath}, Constant.TEST_CONF);
Args.getInstance().setNodeListenPort(10000 + port.incrementAndGet());

Args.getInstance().genesisBlock.setTimestamp(Long.toString(time));
initParameter(Args.getInstance());
context = new TronApplicationContext(DefaultConfig.class);

dbManager = context.getBean(Manager.class);
setManager(dbManager);
dposSlot = context.getBean(DposSlot.class);
ConsensusService consensusService = context.getBean(ConsensusService.class);
consensusService.start();
chainManager = dbManager.getChainBaseManager();
tronNetDelegate = context.getBean(TronNetDelegate.class);
dposService = context.getBean(DposService.class);
consensusDelegate = context.getBean(ConsensusDelegate.class);
tronNetDelegate.setExit(false);
currentHeader = dbManager.getDynamicPropertiesStore()
.getLatestBlockHeaderNumberFromDB();

byte[] address = PublicMethod.getAddressByteByPrivateKey(key);
ByteString addressByte = ByteString.copyFrom(address);
WitnessCapsule witnessCapsule = new WitnessCapsule(addressByte);
chainManager.getWitnessStore().put(addressByte.toByteArray(), witnessCapsule);
chainManager.addWitness(addressByte);

AccountCapsule accountCapsule =
new AccountCapsule(Protocol.Account.newBuilder().setAddress(addressByte).build());
chainManager.getAccountStore().put(addressByte.toByteArray(), accountCapsule);
chainManager.getWitnessScheduleStore().reset();
chainManager.getWitnessStore().reset();
witnesses = addTestWitnessAndAccount();

List<ByteString> allWitnesses = new ArrayList<>();
consensusDelegate.getAllWitnesses().forEach(witnessCapsule ->
allWitnesses.add(witnessCapsule.getAddress()));
dposService.updateWitness(allWitnesses);
List<ByteString> activeWitnesses = consensusDelegate.getActiveWitnesses();
activeWitnesses.forEach(address -> {
WitnessCapsule witnessCapsule = consensusDelegate.getWitness(address.toByteArray());
witnessCapsule.setIsJobs(true);
consensusDelegate.saveWitness(witnessCapsule);
});
chainManager.getDynamicPropertiesStore().saveNextMaintenanceTime(time);
}

@After
Expand All @@ -116,72 +118,57 @@ public void destroy() {
context.destroy();
}

private void generateBlock(Map<ByteString, String> witnessAndAccount) throws Exception {
private void generateBlock() throws Exception {

BlockCapsule block =
createTestBlockCapsule(
chainManager.getDynamicPropertiesStore().getLatestBlockHeaderTimestamp() + 3000,
chainManager.getNextBlockSlotTime(),
chainManager.getDynamicPropertiesStore().getLatestBlockHeaderNumber() + 1,
chainManager.getDynamicPropertiesStore().getLatestBlockHeaderHash().getByteString(),
witnessAndAccount);
chainManager.getDynamicPropertiesStore().getLatestBlockHeaderHash().getByteString());

tronNetDelegate.processBlock(block, false);

logger.info("headerNum: {} solidityNum: {}, dbNum: {}",
block.getNum(), chainManager.getDynamicPropertiesStore().getLatestSolidifiedBlockNum(),
chainManager.getDynamicPropertiesStore().getLatestBlockHeaderNumberFromDB());
}

@Test
@Test(timeout = 30_000) // milliseconds
public void testStop() throws Exception {
final ECKey ecKey = ECKey.fromPrivate(privateKey);
Assert.assertNotNull(ecKey);
byte[] address = ecKey.getAddress();
WitnessCapsule witnessCapsule = new WitnessCapsule(ByteString.copyFrom(address));
chainManager.getWitnessScheduleStore().saveActiveWitnesses(new ArrayList<>());
chainManager.addWitness(ByteString.copyFrom(address));

Protocol.Block block = getSignedBlock(witnessCapsule.getAddress(), time, privateKey);

tronNetDelegate.processBlock(new BlockCapsule(block), false);

Map<ByteString, String> witnessAndAccount = addTestWitnessAndAccount();
witnessAndAccount.put(ByteString.copyFrom(address), key);
while (!tronNetDelegate.isHitDown()) {
generateBlock(witnessAndAccount);
generateBlock();
}
Assert.assertTrue(tronNetDelegate.isHitDown());
check();
}

private Map<ByteString, String> addTestWitnessAndAccount() {
chainManager.getWitnesses().clear();
return IntStream.range(0, 2)
private Map<String, String> addTestWitnessAndAccount() {
return IntStream.range(0, 27)
.mapToObj(
i -> {
ECKey ecKey = new ECKey(Utils.getRandom());
String privateKey = ByteArray.toHexString(ecKey.getPrivKey().toByteArray());
ByteString address = ByteString.copyFrom(ecKey.getAddress());

WitnessCapsule witnessCapsule = new WitnessCapsule(address);
WitnessCapsule witnessCapsule = new WitnessCapsule(address, 27 - i, "SR" + i);
chainManager.getWitnessStore().put(address.toByteArray(), witnessCapsule);
chainManager.addWitness(address);

AccountCapsule accountCapsule =
new AccountCapsule(Protocol.Account.newBuilder().setAddress(address).build());
chainManager.getAccountStore().put(address.toByteArray(), accountCapsule);

return Maps.immutableEntry(address, privateKey);
return Maps.immutableEntry(ByteArray.toHexString(ecKey.getAddress()), privateKey);
})
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
}

private BlockCapsule createTestBlockCapsule(long time,
long number, ByteString hash,
Map<ByteString, String> witnessAddressMap) {
ByteString witnessAddress = dposSlot.getScheduledWitness(dposSlot.getSlot(time));
BlockCapsule blockCapsule = new BlockCapsule(number, Sha256Hash.wrap(hash), time,
witnessAddress);
long number, ByteString hash) {
long slot = dposSlot.getSlot(time);
ByteString witness = dposSlot.getScheduledWitness(slot);
BlockCapsule blockCapsule = new BlockCapsule(number, Sha256Hash.wrap(hash), time, witness);
blockCapsule.generatedByMyself = true;
blockCapsule.setMerkleRoot();
blockCapsule.sign(ByteArray.fromHexString(witnessAddressMap.get(witnessAddress)));
String pri = witnesses.get(ByteArray.toHexString(witness.toByteArray()));
blockCapsule.sign(ByteArray.fromHexString(pri));
return blockCapsule;
}

}