diff --git a/actuator/src/main/java/org/tron/core/actuator/UnfreezeBalanceV2Actuator.java b/actuator/src/main/java/org/tron/core/actuator/UnfreezeBalanceV2Actuator.java index 53bcadc8bf9..45b05ec8bec 100755 --- a/actuator/src/main/java/org/tron/core/actuator/UnfreezeBalanceV2Actuator.java +++ b/actuator/src/main/java/org/tron/core/actuator/UnfreezeBalanceV2Actuator.java @@ -93,7 +93,6 @@ public boolean execute(Object result) throws ContractExeException { accountStore.put(ownerAddress, accountCapsule); - ret.setUnfreezeAmount(unfreezeBalance); ret.setWithdrawExpireAmount(unfreezeAmount); ret.setStatus(fee, code.SUCESS); return true; diff --git a/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java b/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java index f8e28296782..a0154470bc5 100644 --- a/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java +++ b/actuator/src/main/java/org/tron/core/utils/ProposalUtil.java @@ -608,6 +608,17 @@ public static void validator(DynamicPropertiesStore dynamicPropertiesStore, } break; } + case ALLOW_OPTIMIZED_RETURN_VALUE_OF_CHAIN_ID: { + if (!forkController.pass(ForkBlockVersionEnum.VERSION_4_7)) { + throw new ContractValidateException( + "Bad chain parameter id [ALLOW_OPTIMIZED_RETURN_VALUE_OF_CHAIN_ID]"); + } + if (value != 1) { + throw new ContractValidateException( + "This value[ALLOW_OPTIMIZED_RETURN_VALUE_OF_CHAIN_ID] is only allowed to be 1"); + } + break; + } default: break; @@ -676,7 +687,8 @@ public enum ProposalType { // current value, value range ALLOW_NEW_REWARD(67), // 0, 1 MEMO_FEE(68), // 0, [0, 1000_000_000] ALLOW_DELEGATE_OPTIMIZATION(69), - UNFREEZE_DELAY_DAYS(70); // 0, [1, 365] + UNFREEZE_DELAY_DAYS(70), // 0, [1, 365] + ALLOW_OPTIMIZED_RETURN_VALUE_OF_CHAIN_ID(71); // 0, 1 private long code; 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 d03ca513822..496af641cde 100644 --- a/actuator/src/main/java/org/tron/core/utils/TransactionUtil.java +++ b/actuator/src/main/java/org/tron/core/utils/TransactionUtil.java @@ -299,6 +299,7 @@ public static long estimateConsumeBandWidthSize( final AccountCapsule ownerCapsule, ChainBaseManager chainBaseManager) { DelegateResourceContract.Builder builder = DelegateResourceContract.newBuilder() + .setLock(true) .setBalance(ownerCapsule.getFrozenV2BalanceForBandwidth()); TransactionCapsule fakeTransactionCapsule = new TransactionCapsule(builder.build() , ContractType.DelegateResourceContract); diff --git a/actuator/src/main/java/org/tron/core/vm/config/ConfigLoader.java b/actuator/src/main/java/org/tron/core/vm/config/ConfigLoader.java index 7d06e5c9490..8dbb4457d4d 100644 --- a/actuator/src/main/java/org/tron/core/vm/config/ConfigLoader.java +++ b/actuator/src/main/java/org/tron/core/vm/config/ConfigLoader.java @@ -32,6 +32,8 @@ public static void load(StoreFactory storeFactory) { VMConfig.initAllowHigherLimitForMaxCpuTimeOfOneTx( ds.getAllowHigherLimitForMaxCpuTimeOfOneTx()); VMConfig.initAllowTvmFreezeV2(ds.supportUnfreezeDelay() ? 1 : 0); + VMConfig.initAllowOptimizedReturnValueOfChainId( + ds.getAllowOptimizedReturnValueOfChainId()); } } } diff --git a/actuator/src/main/java/org/tron/core/vm/config/VMConfig.java b/actuator/src/main/java/org/tron/core/vm/config/VMConfig.java index cd94409878d..38fa1ca17f6 100644 --- a/actuator/src/main/java/org/tron/core/vm/config/VMConfig.java +++ b/actuator/src/main/java/org/tron/core/vm/config/VMConfig.java @@ -37,6 +37,8 @@ public class VMConfig { private static boolean ALLOW_TVM_FREEZE_V2 = false; + private static boolean ALLOW_OPTIMIZED_RETURN_VALUE_OF_CHAIN_ID = false; + private VMConfig() { } @@ -100,6 +102,10 @@ public static void initAllowTvmFreezeV2(long allow) { ALLOW_TVM_FREEZE_V2 = allow == 1; } + public static void initAllowOptimizedReturnValueOfChainId(long allow) { + ALLOW_OPTIMIZED_RETURN_VALUE_OF_CHAIN_ID = allow == 1; + } + public static boolean getEnergyLimitHardFork() { return CommonParameter.ENERGY_LIMIT_HARD_FORK; } @@ -151,4 +157,8 @@ public static boolean allowHigherLimitForMaxCpuTimeOfOneTx() { public static boolean allowTvmFreezeV2() { return ALLOW_TVM_FREEZE_V2; } + + public static boolean allowOptimizedReturnValueOfChainId() { + return ALLOW_OPTIMIZED_RETURN_VALUE_OF_CHAIN_ID; + } } diff --git a/actuator/src/main/java/org/tron/core/vm/program/Program.java b/actuator/src/main/java/org/tron/core/vm/program/Program.java index 0f141dce840..fac78690263 100644 --- a/actuator/src/main/java/org/tron/core/vm/program/Program.java +++ b/actuator/src/main/java/org/tron/core/vm/program/Program.java @@ -1256,7 +1256,7 @@ public DataWord getCallerAddress() { public DataWord getChainId() { byte[] chainId = getContractState().getBlockByNum(0).getBlockId().getBytes(); - if (VMConfig.allowTvmCompatibleEvm()) { + if (VMConfig.allowTvmCompatibleEvm() || VMConfig.allowOptimizedReturnValueOfChainId()) { chainId = Arrays.copyOfRange(chainId, chainId.length - 4, chainId.length); } return new DataWord(chainId).clone(); diff --git a/chainbase/src/main/java/org/tron/core/db2/core/SnapshotManager.java b/chainbase/src/main/java/org/tron/core/db2/core/SnapshotManager.java index ab953fae932..fe59a2737dd 100644 --- a/chainbase/src/main/java/org/tron/core/db2/core/SnapshotManager.java +++ b/chainbase/src/main/java/org/tron/core/db2/core/SnapshotManager.java @@ -49,7 +49,6 @@ @Slf4j(topic = "DB") public class SnapshotManager implements RevokingDatabase { - public static final int DEFAULT_MAX_FLUSH_COUNT = 500; public static final int DEFAULT_MIN_FLUSH_COUNT = 1; private static final int DEFAULT_STACK_MAX_SIZE = 256; private static final long ONE_MINUTE_MILLS = 60*1000L; 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 b417a3b283f..3770d0ab22e 100644 --- a/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java +++ b/chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java @@ -193,9 +193,11 @@ public class DynamicPropertiesStore extends TronStoreWithRevoking private static final byte[] ALLOW_DELEGATE_OPTIMIZATION = "ALLOW_DELEGATE_OPTIMIZATION".getBytes(); - private static final byte[] UNFREEZE_DELAY_DAYS = "UNFREEZE_DELAY_DAYS".getBytes(); + private static final byte[] ALLOW_OPTIMIZED_RETURN_VALUE_OF_CHAIN_ID = + "ALLOW_OPTIMIZED_RETURN_VALUE_OF_CHAIN_ID".getBytes(); + @Autowired private DynamicPropertiesStore(@Value("properties") String dbName) { super(dbName); @@ -899,6 +901,14 @@ private DynamicPropertiesStore(@Value("properties") String dbName) { CommonParameter.getInstance().getUnfreezeDelayDays() ); } + + try { + this.getAllowOptimizedReturnValueOfChainId(); + } catch (IllegalArgumentException e) { + this.saveAllowOptimizedReturnValueOfChainId( + CommonParameter.getInstance().getAllowOptimizedReturnValueOfChainId() + ); + } } public String intArrayToString(int[] a) { @@ -2647,6 +2657,20 @@ public void saveUnfreezeDelayDays(long value) { this.put(UNFREEZE_DELAY_DAYS, new BytesCapsule(ByteArray.fromLong(value))); } + public void saveAllowOptimizedReturnValueOfChainId(long value) { + this.put(ALLOW_OPTIMIZED_RETURN_VALUE_OF_CHAIN_ID, + new BytesCapsule(ByteArray.fromLong(value))); + } + + public long getAllowOptimizedReturnValueOfChainId() { + String msg = "not found ALLOW_OPTIMIZED_RETURN_VALUE_OF_CHAIN_ID"; + return Optional.ofNullable(getUnchecked(ALLOW_OPTIMIZED_RETURN_VALUE_OF_CHAIN_ID)) + .map(BytesCapsule::getData) + .map(ByteArray::toLong) + .orElseThrow( + () -> new IllegalArgumentException(msg)); + } + private static class DynamicResourceProperties { private static final byte[] ONE_DAY_NET_LIMIT = "ONE_DAY_NET_LIMIT".getBytes(); diff --git a/common/src/main/java/org/tron/common/parameter/CommonParameter.java b/common/src/main/java/org/tron/common/parameter/CommonParameter.java index cd7ea7965e6..bb4c70d388c 100644 --- a/common/src/main/java/org/tron/common/parameter/CommonParameter.java +++ b/common/src/main/java/org/tron/common/parameter/CommonParameter.java @@ -582,6 +582,10 @@ public class CommonParameter { @Setter public long unfreezeDelayDays = 0L; + @Getter + @Setter + public long allowOptimizedReturnValueOfChainId = 0L; + private static double calcMaxTimeRatio() { //return max(2.0, min(5.0, 5 * 4.0 / max(Runtime.getRuntime().availableProcessors(), 1))); return 5.0; diff --git a/common/src/main/java/org/tron/core/Constant.java b/common/src/main/java/org/tron/core/Constant.java index e4725f413e5..c621f05838a 100644 --- a/common/src/main/java/org/tron/core/Constant.java +++ b/common/src/main/java/org/tron/core/Constant.java @@ -294,6 +294,8 @@ public class Constant { public static final String COMMITTEE_ALLOW_HIGHER_LIMIT_FOR_MAX_CPU_TIME_OF_ONE_TX = "committee.allowHigherLimitForMaxCpuTimeOfOneTx"; public static final String COMMITTEE_ALLOW_NEW_REWARD_ALGORITHM = "committee.allowNewRewardAlgorithm"; + public static final String COMMITTEE_ALLOW_OPTIMIZED_RETURN_VALUE_OF_CHAIN_ID = + "committee.allowOptimizedReturnValueOfChainId"; public static final String METRICS_STORAGE_ENABLE = "node.metrics.storageEnable"; diff --git a/common/src/main/java/org/tron/core/config/args/Storage.java b/common/src/main/java/org/tron/core/config/args/Storage.java index ce4cc6865d3..778d4d0141c 100644 --- a/common/src/main/java/org/tron/core/config/args/Storage.java +++ b/common/src/main/java/org/tron/core/config/args/Storage.java @@ -90,7 +90,7 @@ public class Storage { private static final int DEFAULT_CHECKPOINT_VERSION = 1; private static final boolean DEFAULT_CHECKPOINT_SYNC = true; private static final int DEFAULT_ESTIMATED_TRANSACTIONS = 1000; - private static final int DEFAULT_SNAPSHOT_MAX_FLUSH_COUNT = 500; + private static final int DEFAULT_SNAPSHOT_MAX_FLUSH_COUNT = 1; private Config storage; /** diff --git a/docker/Dockerfile b/docker/Dockerfile index f19208f1816..2732f5a55ed 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -1,4 +1,4 @@ -FROM tronprotocol/centos7 +FROM tronprotocol/centos7:0.2 ENV TMP_DIR="/tron-build" ENV JDK_TAR="jdk-8u202-linux-x64.tar.gz" @@ -24,7 +24,7 @@ RUN set -o errexit -o nounset \ && git checkout master \ && ./gradlew build -x test \ && cd build/distributions \ - && unzip -o java-tron-1.0.0.zip \ + && 7za x -y java-tron-1.0.0.zip \ && mv java-tron-1.0.0 $BASE_DIR \ && rm -rf $TMP_DIR \ && rm -rf ~/.gradle \ diff --git a/framework/src/main/java/org/tron/core/Wallet.java b/framework/src/main/java/org/tron/core/Wallet.java index b79bd3510e7..21c7bfa4441 100755 --- a/framework/src/main/java/org/tron/core/Wallet.java +++ b/framework/src/main/java/org/tron/core/Wallet.java @@ -821,6 +821,9 @@ public GrpcAPI.CanDelegatedMaxSizeResponseMessage getCanDelegatedMaxSize( canDelegatedMaxSize = this.calcCanDelegatedEnergyMaxSize(ownerAddress); } + if (canDelegatedMaxSize < TRX_PRECISION) { + canDelegatedMaxSize = 0L; + } builder.setMaxSize(canDelegatedMaxSize); return builder.build(); } @@ -1284,6 +1287,11 @@ public Protocol.ChainParameters getChainParameters() { .setValue(dbManager.getDynamicPropertiesStore().getUnfreezeDelayDays()) .build()); + builder.addChainParameter(Protocol.ChainParameters.ChainParameter.newBuilder() + .setKey("getAllowOptimizedReturnValueOfChainId") + .setValue(dbManager.getDynamicPropertiesStore().getAllowOptimizedReturnValueOfChainId()) + .build()); + return builder.build(); } diff --git a/framework/src/main/java/org/tron/core/config/args/Args.java b/framework/src/main/java/org/tron/core/config/args/Args.java index 72b526ad57b..b47e9c4d7b1 100644 --- a/framework/src/main/java/org/tron/core/config/args/Args.java +++ b/framework/src/main/java/org/tron/core/config/args/Args.java @@ -956,6 +956,10 @@ public static void setParam(final String[] args, final String confFileName) { config.hasPath(Constant.COMMITTEE_ALLOW_NEW_REWARD_ALGORITHM) ? config .getInt(Constant.COMMITTEE_ALLOW_NEW_REWARD_ALGORITHM) : 0; + PARAMETER.allowOptimizedReturnValueOfChainId = + config.hasPath(Constant.COMMITTEE_ALLOW_OPTIMIZED_RETURN_VALUE_OF_CHAIN_ID) ? config + .getInt(Constant.COMMITTEE_ALLOW_OPTIMIZED_RETURN_VALUE_OF_CHAIN_ID) : 0; + initBackupProperty(config); if (Constant.ROCKSDB.equalsIgnoreCase(CommonParameter .getInstance().getStorage().getDbEngine())) { diff --git a/framework/src/main/java/org/tron/core/consensus/ProposalService.java b/framework/src/main/java/org/tron/core/consensus/ProposalService.java index 9b5c6dfb975..c35549e8749 100644 --- a/framework/src/main/java/org/tron/core/consensus/ProposalService.java +++ b/framework/src/main/java/org/tron/core/consensus/ProposalService.java @@ -318,6 +318,11 @@ public static boolean process(Manager manager, ProposalCapsule proposalCapsule) manager.getDynamicPropertiesStore().saveAllowDelegateOptimization(entry.getValue()); break; } + case ALLOW_OPTIMIZED_RETURN_VALUE_OF_CHAIN_ID: { + manager.getDynamicPropertiesStore() + .saveAllowOptimizedReturnValueOfChainId(entry.getValue()); + break; + } default: find = false; break; diff --git a/framework/src/main/java/org/tron/core/db/Manager.java b/framework/src/main/java/org/tron/core/db/Manager.java index 060a2db5de2..41f948836b9 100644 --- a/framework/src/main/java/org/tron/core/db/Manager.java +++ b/framework/src/main/java/org/tron/core/db/Manager.java @@ -42,6 +42,7 @@ import lombok.extern.slf4j.Slf4j; import org.apache.commons.collections4.CollectionUtils; import org.bouncycastle.util.encoders.Hex; +import org.quartz.CronExpression; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.tron.api.GrpcAPI.TransactionInfoList; @@ -537,21 +538,14 @@ public void init() { //initActuatorCreator ActuatorCreator.init(); TransactionRegister.registerActuator(); - - long exitHeight = CommonParameter.getInstance().getShutdownBlockHeight(); - long exitCount = CommonParameter.getInstance().getShutdownBlockCount(); - - if (exitCount > 0 && (exitHeight < 0 || exitHeight > headNum + exitCount)) { - CommonParameter.getInstance().setShutdownBlockHeight(headNum + exitCount); + // init auto-stop + try { + initAutoStop(); + } catch (IllegalArgumentException e) { + logger.error("Auto-stop params error: {}", e.getMessage()); + System.exit(1); } - if (CommonParameter.getInstance().getShutdownBlockHeight() < headNum) { - logger.info("ShutDownBlockHeight {} is less than headNum {}, ignored.", - CommonParameter.getInstance().getShutdownBlockHeight(), headNum); - CommonParameter.getInstance().setShutdownBlockHeight(-1); - } - // init - latestSolidityNumShutDown = CommonParameter.getInstance().getShutdownBlockHeight(); maxFlushCount = CommonParameter.getInstance().getStorage().getMaxFlushCount(); } @@ -677,6 +671,62 @@ private void initWitness() { }); } + /** + * init auto-stop, check params + */ + private void initAutoStop() { + final long headNum = chainBaseManager.getHeadBlockNum(); + final long headTime = chainBaseManager.getHeadBlockTimeStamp(); + final long exitHeight = CommonParameter.getInstance().getShutdownBlockHeight(); + final long exitCount = CommonParameter.getInstance().getShutdownBlockCount(); + final CronExpression blockTime = Args.getInstance().getShutdownBlockTime(); + + if (exitHeight > 0 && exitHeight < headNum) { + throw new IllegalArgumentException( + String.format("shutDownBlockHeight %d is less than headNum %d", exitHeight, headNum)); + } + + if (exitCount == 0) { + throw new IllegalArgumentException( + String.format("shutDownBlockCount %d is less than 1", exitCount)); + } + + if (blockTime != null && blockTime.getNextValidTimeAfter(new Date(headTime)) == null) { + throw new IllegalArgumentException( + String.format("shutDownBlockTime %s is illegal", blockTime)); + } + + if (exitHeight > 0 && exitCount > 0) { + throw new IllegalArgumentException( + String.format("shutDownBlockHeight %d and shutDownBlockCount %d set both", + exitHeight, exitCount)); + } + + if (exitHeight > 0 && blockTime != null) { + throw new IllegalArgumentException( + String.format("shutDownBlockHeight %d and shutDownBlockTime %s set both", + exitHeight, blockTime)); + } + + if (exitCount > 0 && blockTime != null) { + throw new IllegalArgumentException( + String.format("shutDownBlockCount %d and shutDownBlockTime %s set both", + exitCount, blockTime)); + } + + if (exitHeight == headNum) { + logger.info("Auto-stop hit: shutDownBlockHeight: {}, currentHeaderNum: {}, exit now", + exitHeight, headNum); + System.exit(0); + } + + if (exitCount > 0) { + CommonParameter.getInstance().setShutdownBlockHeight(headNum + exitCount); + } + // init + latestSolidityNumShutDown = CommonParameter.getInstance().getShutdownBlockHeight(); + } + public AccountStore getAccountStore() { return chainBaseManager.getAccountStore(); } @@ -964,12 +1014,12 @@ private void applyBlock(BlockCapsule block, List txs) revokingStore.setMaxFlushCount(maxFlushCount); if (Args.getInstance().getShutdownBlockTime() != null && Args.getInstance().getShutdownBlockTime().getNextValidTimeAfter( - new Date(block.getTimeStamp() - SnapshotManager.DEFAULT_MAX_FLUSH_COUNT * 1000 * 3)) + new Date(block.getTimeStamp() - maxFlushCount * 1000 * 3L)) .compareTo(new Date(block.getTimeStamp())) <= 0) { revokingStore.setMaxFlushCount(SnapshotManager.DEFAULT_MIN_FLUSH_COUNT); } if (latestSolidityNumShutDown > 0 && latestSolidityNumShutDown - block.getNum() - <= SnapshotManager.DEFAULT_MAX_FLUSH_COUNT) { + <= maxFlushCount) { revokingStore.setMaxFlushCount(SnapshotManager.DEFAULT_MIN_FLUSH_COUNT); } } else { diff --git a/framework/src/main/java/org/tron/core/net/TronNetDelegate.java b/framework/src/main/java/org/tron/core/net/TronNetDelegate.java index a531a0d50af..05dde7a9701 100644 --- a/framework/src/main/java/org/tron/core/net/TronNetDelegate.java +++ b/framework/src/main/java/org/tron/core/net/TronNetDelegate.java @@ -94,9 +94,8 @@ public class TronNetDelegate { private Thread hitThread; - // for Test @Setter - private volatile boolean test = false; + private volatile boolean exit = true; private Cache freshBlockId = CacheBuilder.newBuilder() .maximumSize(blockIdCacheSize).expireAfterWrite(1, TimeUnit.HOURS) @@ -107,7 +106,7 @@ public void init() { hitThread = new Thread(() -> { LockSupport.park(); // to Guarantee Some other thread invokes unpark with the current thread as the target - if (hitDown && !test) { + if (hitDown && exit) { System.exit(0); } }); diff --git a/framework/src/main/java/org/tron/core/net/peer/PeerConnection.java b/framework/src/main/java/org/tron/core/net/peer/PeerConnection.java index a433ad43bd8..ae9f3169d6e 100644 --- a/framework/src/main/java/org/tron/core/net/peer/PeerConnection.java +++ b/framework/src/main/java/org/tron/core/net/peer/PeerConnection.java @@ -206,7 +206,7 @@ public String log() { + "remainNum:%d\n" + "syncChainRequested:%d\n" + "blockInProcess:%d\n", - channel.getInetAddress(), + channel.getInetSocketAddress(), (now - channel.getStartTime()) / Constant.ONE_THOUSAND, channel.getLatency(), fastForwardBlock != null ? fastForwardBlock.getNum() : blockBothHave.getNum(), diff --git a/framework/src/main/java/org/tron/core/net/peer/PeerManager.java b/framework/src/main/java/org/tron/core/net/peer/PeerManager.java index dfcb0c0e599..8a402438c86 100644 --- a/framework/src/main/java/org/tron/core/net/peer/PeerManager.java +++ b/framework/src/main/java/org/tron/core/net/peer/PeerManager.java @@ -43,11 +43,11 @@ public static void init() { public static void close() { try { - peers.forEach(p -> { + for (PeerConnection p : new ArrayList<>(peers)) { if (!p.isDisconnect()) { p.getChannel().close(); } - }); + } executor.shutdownNow(); } catch (Exception e) { logger.error("Peer manager shutdown failed", e); diff --git a/framework/src/main/java/org/tron/core/services/interfaceOnPBFT/RpcApiServiceOnPBFT.java b/framework/src/main/java/org/tron/core/services/interfaceOnPBFT/RpcApiServiceOnPBFT.java index 286613b14b9..281714bc083 100755 --- a/framework/src/main/java/org/tron/core/services/interfaceOnPBFT/RpcApiServiceOnPBFT.java +++ b/framework/src/main/java/org/tron/core/services/interfaceOnPBFT/RpcApiServiceOnPBFT.java @@ -16,11 +16,17 @@ import org.tron.api.GrpcAPI.BlockExtention; import org.tron.api.GrpcAPI.BlockReference; import org.tron.api.GrpcAPI.BytesMessage; +import org.tron.api.GrpcAPI.CanDelegatedMaxSizeRequestMessage; +import org.tron.api.GrpcAPI.CanDelegatedMaxSizeResponseMessage; +import org.tron.api.GrpcAPI.CanWithdrawUnfreezeAmountRequestMessage; +import org.tron.api.GrpcAPI.CanWithdrawUnfreezeAmountResponseMessage; import org.tron.api.GrpcAPI.DecryptNotesTRC20; import org.tron.api.GrpcAPI.DelegatedResourceList; import org.tron.api.GrpcAPI.DelegatedResourceMessage; import org.tron.api.GrpcAPI.EmptyMessage; import org.tron.api.GrpcAPI.ExchangeList; +import org.tron.api.GrpcAPI.GetAvailableUnfreezeCountRequestMessage; +import org.tron.api.GrpcAPI.GetAvailableUnfreezeCountResponseMessage; import org.tron.api.GrpcAPI.IvkDecryptTRC20Parameters; import org.tron.api.GrpcAPI.NfTRC20Parameters; import org.tron.api.GrpcAPI.NoteParameters; @@ -44,6 +50,7 @@ import org.tron.core.services.ratelimiter.RpcApiAccessInterceptor; import org.tron.protos.Protocol.Account; import org.tron.protos.Protocol.Block; +import org.tron.protos.Protocol.DelegatedResourceAccountIndex; import org.tron.protos.Protocol.DynamicProperties; import org.tron.protos.Protocol.Exchange; import org.tron.protos.Protocol.MarketOrder; @@ -58,6 +65,7 @@ import org.tron.protos.contract.ShieldContract.OutputPointInfo; import org.tron.protos.contract.SmartContractOuterClass.TriggerSmartContract; + @Slf4j(topic = "API") public class RpcApiServiceOnPBFT implements Service { @@ -298,15 +306,60 @@ public void getDelegatedResource(DelegatedResourceMessage request, ); } + @Override + public void getDelegatedResourceV2(DelegatedResourceMessage request, + StreamObserver responseObserver) { + walletOnPBFT.futureGet( + () -> rpcApiService.getWalletSolidityApi() + .getDelegatedResourceV2(request, responseObserver) + ); + } + @Override public void getDelegatedResourceAccountIndex(BytesMessage request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { walletOnPBFT.futureGet( () -> rpcApiService.getWalletSolidityApi() .getDelegatedResourceAccountIndex(request, responseObserver) ); } + @Override + public void getDelegatedResourceAccountIndexV2(BytesMessage request, + StreamObserver responseObserver) { + walletOnPBFT.futureGet( + () -> rpcApiService.getWalletSolidityApi() + .getDelegatedResourceAccountIndexV2(request, responseObserver) + ); + } + + @Override + public void getCanDelegatedMaxSize(CanDelegatedMaxSizeRequestMessage request, + StreamObserver responseObserver) { + walletOnPBFT.futureGet( + () -> rpcApiService.getWalletSolidityApi() + .getCanDelegatedMaxSize(request, responseObserver) + ); + } + + @Override + public void getAvailableUnfreezeCount(GetAvailableUnfreezeCountRequestMessage request, + StreamObserver responseObserver) { + walletOnPBFT.futureGet( + () -> rpcApiService.getWalletSolidityApi() + .getAvailableUnfreezeCount(request, responseObserver) + ); + } + + @Override + public void getCanWithdrawUnfreezeAmount(CanWithdrawUnfreezeAmountRequestMessage request, + StreamObserver responseObserver) { + walletOnPBFT.futureGet( + () -> rpcApiService.getWalletSolidityApi() + .getCanWithdrawUnfreezeAmount(request, responseObserver) + ); + } + @Override public void getTransactionCountByBlockNum(NumberMessage request, StreamObserver responseObserver) { diff --git a/framework/src/main/java/org/tron/core/services/interfaceOnPBFT/http/GetAvailableUnfreezeCountOnPBFTServlet.java b/framework/src/main/java/org/tron/core/services/interfaceOnPBFT/http/GetAvailableUnfreezeCountOnPBFTServlet.java new file mode 100644 index 00000000000..bb393f92efc --- /dev/null +++ b/framework/src/main/java/org/tron/core/services/interfaceOnPBFT/http/GetAvailableUnfreezeCountOnPBFTServlet.java @@ -0,0 +1,25 @@ +package org.tron.core.services.interfaceOnPBFT.http; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.tron.core.services.http.GetAvailableUnfreezeCountServlet; +import org.tron.core.services.interfaceOnPBFT.WalletOnPBFT; + +@Component +@Slf4j(topic = "API") +public class GetAvailableUnfreezeCountOnPBFTServlet extends GetAvailableUnfreezeCountServlet { + + @Autowired + private WalletOnPBFT walletOnPBFT; + + protected void doGet(HttpServletRequest request, HttpServletResponse response) { + walletOnPBFT.futureGet(() -> super.doGet(request, response)); + } + + protected void doPost(HttpServletRequest request, HttpServletResponse response) { + walletOnPBFT.futureGet(() -> super.doPost(request, response)); + } +} diff --git a/framework/src/main/java/org/tron/core/services/interfaceOnPBFT/http/GetCanDelegatedMaxSizeOnPBFTServlet.java b/framework/src/main/java/org/tron/core/services/interfaceOnPBFT/http/GetCanDelegatedMaxSizeOnPBFTServlet.java new file mode 100644 index 00000000000..8b3b47462e8 --- /dev/null +++ b/framework/src/main/java/org/tron/core/services/interfaceOnPBFT/http/GetCanDelegatedMaxSizeOnPBFTServlet.java @@ -0,0 +1,25 @@ +package org.tron.core.services.interfaceOnPBFT.http; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.tron.core.services.http.GetCanDelegatedMaxSizeServlet; +import org.tron.core.services.interfaceOnPBFT.WalletOnPBFT; + +@Component +@Slf4j(topic = "API") +public class GetCanDelegatedMaxSizeOnPBFTServlet extends GetCanDelegatedMaxSizeServlet { + + @Autowired + private WalletOnPBFT walletOnPBFT; + + protected void doGet(HttpServletRequest request, HttpServletResponse response) { + walletOnPBFT.futureGet(() -> super.doGet(request, response)); + } + + protected void doPost(HttpServletRequest request, HttpServletResponse response) { + walletOnPBFT.futureGet(() -> super.doPost(request, response)); + } +} diff --git a/framework/src/main/java/org/tron/core/services/interfaceOnPBFT/http/GetCanWithdrawUnfreezeAmountOnPBFTServlet.java b/framework/src/main/java/org/tron/core/services/interfaceOnPBFT/http/GetCanWithdrawUnfreezeAmountOnPBFTServlet.java new file mode 100644 index 00000000000..c8b20c4eef7 --- /dev/null +++ b/framework/src/main/java/org/tron/core/services/interfaceOnPBFT/http/GetCanWithdrawUnfreezeAmountOnPBFTServlet.java @@ -0,0 +1,26 @@ +package org.tron.core.services.interfaceOnPBFT.http; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.tron.core.services.http.GetCanWithdrawUnfreezeAmountServlet; +import org.tron.core.services.interfaceOnPBFT.WalletOnPBFT; + +@Component +@Slf4j(topic = "API") +public class GetCanWithdrawUnfreezeAmountOnPBFTServlet + extends GetCanWithdrawUnfreezeAmountServlet { + + @Autowired + private WalletOnPBFT walletOnPBFT; + + protected void doGet(HttpServletRequest request, HttpServletResponse response) { + walletOnPBFT.futureGet(() -> super.doGet(request, response)); + } + + protected void doPost(HttpServletRequest request, HttpServletResponse response) { + walletOnPBFT.futureGet(() -> super.doPost(request, response)); + } +} diff --git a/framework/src/main/java/org/tron/core/services/interfaceOnPBFT/http/GetDelegatedResourceAccountIndexV2OnPBFTServlet.java b/framework/src/main/java/org/tron/core/services/interfaceOnPBFT/http/GetDelegatedResourceAccountIndexV2OnPBFTServlet.java new file mode 100644 index 00000000000..07541905300 --- /dev/null +++ b/framework/src/main/java/org/tron/core/services/interfaceOnPBFT/http/GetDelegatedResourceAccountIndexV2OnPBFTServlet.java @@ -0,0 +1,26 @@ +package org.tron.core.services.interfaceOnPBFT.http; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.tron.core.services.http.GetDelegatedResourceAccountIndexV2Servlet; +import org.tron.core.services.interfaceOnPBFT.WalletOnPBFT; + +@Component +@Slf4j(topic = "API") +public class GetDelegatedResourceAccountIndexV2OnPBFTServlet extends + GetDelegatedResourceAccountIndexV2Servlet { + + @Autowired + private WalletOnPBFT walletOnPBFT; + + protected void doGet(HttpServletRequest request, HttpServletResponse response) { + walletOnPBFT.futureGet(() -> super.doGet(request, response)); + } + + protected void doPost(HttpServletRequest request, HttpServletResponse response) { + walletOnPBFT.futureGet(() -> super.doPost(request, response)); + } +} diff --git a/framework/src/main/java/org/tron/core/services/interfaceOnPBFT/http/GetDelegatedResourceV2OnPBFTServlet.java b/framework/src/main/java/org/tron/core/services/interfaceOnPBFT/http/GetDelegatedResourceV2OnPBFTServlet.java new file mode 100644 index 00000000000..6429c90eec5 --- /dev/null +++ b/framework/src/main/java/org/tron/core/services/interfaceOnPBFT/http/GetDelegatedResourceV2OnPBFTServlet.java @@ -0,0 +1,25 @@ +package org.tron.core.services.interfaceOnPBFT.http; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.tron.core.services.http.GetDelegatedResourceV2Servlet; +import org.tron.core.services.interfaceOnPBFT.WalletOnPBFT; + +@Component +@Slf4j(topic = "API") +public class GetDelegatedResourceV2OnPBFTServlet extends GetDelegatedResourceV2Servlet { + + @Autowired + private WalletOnPBFT walletOnPBFT; + + protected void doGet(HttpServletRequest request, HttpServletResponse response) { + walletOnPBFT.futureGet(() -> super.doGet(request, response)); + } + + protected void doPost(HttpServletRequest request, HttpServletResponse response) { + walletOnPBFT.futureGet(() -> super.doPost(request, response)); + } +} diff --git a/framework/src/main/java/org/tron/core/services/interfaceOnPBFT/http/PBFT/HttpApiOnPBFTService.java b/framework/src/main/java/org/tron/core/services/interfaceOnPBFT/http/PBFT/HttpApiOnPBFTService.java index 13b356deba1..a6e560e78be 100644 --- a/framework/src/main/java/org/tron/core/services/interfaceOnPBFT/http/PBFT/HttpApiOnPBFTService.java +++ b/framework/src/main/java/org/tron/core/services/interfaceOnPBFT/http/PBFT/HttpApiOnPBFTService.java @@ -20,14 +20,19 @@ import org.tron.core.services.interfaceOnPBFT.http.GetAssetIssueByNameOnPBFTServlet; import org.tron.core.services.interfaceOnPBFT.http.GetAssetIssueListByNameOnPBFTServlet; import org.tron.core.services.interfaceOnPBFT.http.GetAssetIssueListOnPBFTServlet; +import org.tron.core.services.interfaceOnPBFT.http.GetAvailableUnfreezeCountOnPBFTServlet; import org.tron.core.services.interfaceOnPBFT.http.GetBlockByIdOnPBFTServlet; import org.tron.core.services.interfaceOnPBFT.http.GetBlockByLatestNumOnPBFTServlet; import org.tron.core.services.interfaceOnPBFT.http.GetBlockByLimitNextOnPBFTServlet; import org.tron.core.services.interfaceOnPBFT.http.GetBlockByNumOnPBFTServlet; import org.tron.core.services.interfaceOnPBFT.http.GetBrokerageOnPBFTServlet; import org.tron.core.services.interfaceOnPBFT.http.GetBurnTrxOnPBFTServlet; +import org.tron.core.services.interfaceOnPBFT.http.GetCanDelegatedMaxSizeOnPBFTServlet; +import org.tron.core.services.interfaceOnPBFT.http.GetCanWithdrawUnfreezeAmountOnPBFTServlet; import org.tron.core.services.interfaceOnPBFT.http.GetDelegatedResourceAccountIndexOnPBFTServlet; +import org.tron.core.services.interfaceOnPBFT.http.GetDelegatedResourceAccountIndexV2OnPBFTServlet; import org.tron.core.services.interfaceOnPBFT.http.GetDelegatedResourceOnPBFTServlet; +import org.tron.core.services.interfaceOnPBFT.http.GetDelegatedResourceV2OnPBFTServlet; import org.tron.core.services.interfaceOnPBFT.http.GetEnergyPricesOnPBFTServlet; import org.tron.core.services.interfaceOnPBFT.http.GetExchangeByIdOnPBFTServlet; import org.tron.core.services.interfaceOnPBFT.http.GetMarketOrderByAccountOnPBFTServlet; @@ -154,6 +159,18 @@ public class HttpApiOnPBFTService implements Service { @Autowired private GetBlockOnPBFTServlet getBlockOnPBFTServlet; + @Autowired + private GetAvailableUnfreezeCountOnPBFTServlet getAvailableUnfreezeCountOnPBFTServlet; + @Autowired + private GetCanDelegatedMaxSizeOnPBFTServlet getCanDelegatedMaxSizeOnPBFTServlet; + @Autowired + private GetCanWithdrawUnfreezeAmountOnPBFTServlet getCanWithdrawUnfreezeAmountOnPBFTServlet; + @Autowired + private GetDelegatedResourceAccountIndexV2OnPBFTServlet + getDelegatedResourceAccountIndexV2OnPBFTServlet; + @Autowired + private GetDelegatedResourceV2OnPBFTServlet getDelegatedResourceV2OnPBFTServlet; + @Override public void init() { @@ -243,6 +260,17 @@ public void start() { context.addServlet(new ServletHolder(getBlockOnPBFTServlet), "/getblock"); + context.addServlet(new ServletHolder(getAvailableUnfreezeCountOnPBFTServlet), + "/getavailableunfreezecount"); + context.addServlet(new ServletHolder(getCanDelegatedMaxSizeOnPBFTServlet), + "/getcandelegatedmaxsize"); + context.addServlet(new ServletHolder(getCanWithdrawUnfreezeAmountOnPBFTServlet), + "/getcanwithdrawunfreezeamount"); + context.addServlet(new ServletHolder(getDelegatedResourceAccountIndexV2OnPBFTServlet), + "/getdelegatedresourceaccountindexv2"); + context.addServlet(new ServletHolder(getDelegatedResourceV2OnPBFTServlet), + "/getdelegatedresourcev2"); + int maxHttpConnectNumber = Args.getInstance().getMaxHttpConnectNumber(); if (maxHttpConnectNumber > 0) { server.addBean(new ConnectionLimit(maxHttpConnectNumber, server)); diff --git a/framework/src/main/java/org/tron/core/services/interfaceOnSolidity/RpcApiServiceOnSolidity.java b/framework/src/main/java/org/tron/core/services/interfaceOnSolidity/RpcApiServiceOnSolidity.java index 4d9d0361d23..2fc4b88de9b 100755 --- a/framework/src/main/java/org/tron/core/services/interfaceOnSolidity/RpcApiServiceOnSolidity.java +++ b/framework/src/main/java/org/tron/core/services/interfaceOnSolidity/RpcApiServiceOnSolidity.java @@ -17,10 +17,16 @@ import org.tron.api.GrpcAPI.BlockExtention; import org.tron.api.GrpcAPI.BlockReference; import org.tron.api.GrpcAPI.BytesMessage; +import org.tron.api.GrpcAPI.CanDelegatedMaxSizeRequestMessage; +import org.tron.api.GrpcAPI.CanDelegatedMaxSizeResponseMessage; +import org.tron.api.GrpcAPI.CanWithdrawUnfreezeAmountRequestMessage; +import org.tron.api.GrpcAPI.CanWithdrawUnfreezeAmountResponseMessage; import org.tron.api.GrpcAPI.DelegatedResourceList; import org.tron.api.GrpcAPI.DelegatedResourceMessage; import org.tron.api.GrpcAPI.EmptyMessage; import org.tron.api.GrpcAPI.ExchangeList; +import org.tron.api.GrpcAPI.GetAvailableUnfreezeCountRequestMessage; +import org.tron.api.GrpcAPI.GetAvailableUnfreezeCountResponseMessage; import org.tron.api.GrpcAPI.NoteParameters; import org.tron.api.GrpcAPI.NumberMessage; import org.tron.api.GrpcAPI.PaginatedMessage; @@ -46,6 +52,7 @@ import org.tron.core.services.ratelimiter.RpcApiAccessInterceptor; import org.tron.protos.Protocol.Account; import org.tron.protos.Protocol.Block; +import org.tron.protos.Protocol.DelegatedResourceAccountIndex; import org.tron.protos.Protocol.DynamicProperties; import org.tron.protos.Protocol.Exchange; import org.tron.protos.Protocol.MarketOrder; @@ -60,6 +67,7 @@ import org.tron.protos.contract.ShieldContract.OutputPointInfo; import org.tron.protos.contract.SmartContractOuterClass.TriggerSmartContract; + @Slf4j(topic = "API") public class RpcApiServiceOnSolidity implements Service { @@ -305,13 +313,48 @@ public void getDelegatedResource(DelegatedResourceMessage request, .getDelegatedResource(request, responseObserver)); } + @Override + public void getDelegatedResourceV2(DelegatedResourceMessage request, + StreamObserver responseObserver) { + walletOnSolidity.futureGet(() -> rpcApiService.getWalletSolidityApi() + .getDelegatedResourceV2(request, responseObserver)); + } + @Override public void getDelegatedResourceAccountIndex(BytesMessage request, - StreamObserver responseObserver) { + StreamObserver responseObserver) { walletOnSolidity.futureGet(() -> rpcApiService.getWalletSolidityApi() .getDelegatedResourceAccountIndex(request, responseObserver)); } + @Override + public void getDelegatedResourceAccountIndexV2(BytesMessage request, + StreamObserver responseObserver) { + walletOnSolidity.futureGet(() -> rpcApiService.getWalletSolidityApi() + .getDelegatedResourceAccountIndexV2(request, responseObserver)); + } + + @Override + public void getCanDelegatedMaxSize(CanDelegatedMaxSizeRequestMessage request, + StreamObserver responseObserver) { + walletOnSolidity.futureGet(() -> rpcApiService.getWalletSolidityApi() + .getCanDelegatedMaxSize(request, responseObserver)); + } + + @Override + public void getAvailableUnfreezeCount(GetAvailableUnfreezeCountRequestMessage request, + StreamObserver responseObserver) { + walletOnSolidity.futureGet(() -> rpcApiService.getWalletSolidityApi() + .getAvailableUnfreezeCount(request, responseObserver)); + } + + @Override + public void getCanWithdrawUnfreezeAmount(CanWithdrawUnfreezeAmountRequestMessage request, + StreamObserver responseObserver) { + walletOnSolidity.futureGet(() -> rpcApiService.getWalletSolidityApi() + .getCanWithdrawUnfreezeAmount(request, responseObserver)); + } + @Override public void getTransactionCountByBlockNum(NumberMessage request, StreamObserver responseObserver) { diff --git a/framework/src/test/java/org/tron/core/services/stop/BlockHeightStopTest.java b/framework/src/test/java/org/tron/core/services/stop/BlockHeightStopTest.java index 43eb4f5ba4e..a05cc64aad4 100644 --- a/framework/src/test/java/org/tron/core/services/stop/BlockHeightStopTest.java +++ b/framework/src/test/java/org/tron/core/services/stop/BlockHeightStopTest.java @@ -11,8 +11,6 @@ public class BlockHeightStopTest extends ConditionallyStopTest { protected void initParameter(CommonParameter parameter) { parameter.setShutdownBlockHeight(height); - // will ignore - parameter.setShutdownBlockCount(128); } @Override diff --git a/framework/src/test/java/org/tron/core/services/stop/BlockSyncCountStopTest.java b/framework/src/test/java/org/tron/core/services/stop/BlockSyncCountStopTest.java index cd5010fabc9..f974a8a4272 100644 --- a/framework/src/test/java/org/tron/core/services/stop/BlockSyncCountStopTest.java +++ b/framework/src/test/java/org/tron/core/services/stop/BlockSyncCountStopTest.java @@ -11,8 +11,6 @@ public class BlockSyncCountStopTest extends ConditionallyStopTest { protected void initParameter(CommonParameter parameter) { parameter.setShutdownBlockCount(sync); - // will ignore - parameter.setShutdownBlockHeight(1024); } @Override diff --git a/framework/src/test/java/org/tron/core/services/stop/BlockTimeStopTest.java b/framework/src/test/java/org/tron/core/services/stop/BlockTimeStopTest.java index 9dd34a577d6..2d3fde1afdb 100644 --- a/framework/src/test/java/org/tron/core/services/stop/BlockTimeStopTest.java +++ b/framework/src/test/java/org/tron/core/services/stop/BlockTimeStopTest.java @@ -28,10 +28,6 @@ public class BlockTimeStopTest extends ConditionallyStopTest { protected void initParameter(CommonParameter parameter) { parameter.setShutdownBlockTime(cronExpression); - // will ignore - parameter.setShutdownBlockHeight(48); - // will ignore - parameter.setShutdownBlockCount(32); } @Override diff --git a/framework/src/test/java/org/tron/core/services/stop/ConditionallyStopTest.java b/framework/src/test/java/org/tron/core/services/stop/ConditionallyStopTest.java index 88f2d1c04e0..d012587849b 100644 --- a/framework/src/test/java/org/tron/core/services/stop/ConditionallyStopTest.java +++ b/framework/src/test/java/org/tron/core/services/stop/ConditionallyStopTest.java @@ -81,7 +81,7 @@ public void init() throws Exception { consensusService.start(); chainManager = dbManager.getChainBaseManager(); tronNetDelegate = context.getBean(TronNetDelegate.class); - tronNetDelegate.setTest(true); + tronNetDelegate.setExit(false); currentHeader = dbManager.getDynamicPropertiesStore() .getLatestBlockHeaderNumberFromDB(); } diff --git a/plugins/README.md b/plugins/README.md index 584619af395..e2458b7e9a6 100644 --- a/plugins/README.md +++ b/plugins/README.md @@ -47,6 +47,25 @@ DB convert provides a helper which can convert LevelDB data to RocksDB data, par java -jar Toolkit.jar db convert output-directory/database /tmp/database ``` +## DB Copy + +DB copy provides a helper which can copy LevelDB or RocksDB data quickly on the same file systems by creating hard links. + +### Available parameters: + +- ``: Source path for database. Default: output-directory/database +- ``: Output path for database. Default: output-directory-cp/database +- `-h | --help`: provide the help info + +### Examples: + +```shell script +# full command + java -jar Toolkit.jar db cp [-h] +# examples + java -jar Toolkit.jar db cp output-directory/database /tmp/databse +``` + ## DB Lite diff --git a/plugins/src/main/java/org/tron/plugins/Db.java b/plugins/src/main/java/org/tron/plugins/Db.java index e7296a2cbc5..c67c838a3d6 100644 --- a/plugins/src/main/java/org/tron/plugins/Db.java +++ b/plugins/src/main/java/org/tron/plugins/Db.java @@ -10,7 +10,8 @@ DbMove.class, DbArchive.class, DbConvert.class, - DbLite.class + DbLite.class, + DbCopy.class }, commandListHeading = "%nCommands:%n%nThe most commonly used db commands are:%n" ) diff --git a/plugins/src/main/java/org/tron/plugins/DbCopy.java b/plugins/src/main/java/org/tron/plugins/DbCopy.java new file mode 100644 index 00000000000..7558d764cd4 --- /dev/null +++ b/plugins/src/main/java/org/tron/plugins/DbCopy.java @@ -0,0 +1,160 @@ +package org.tron.plugins; + +import java.io.File; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Objects; +import java.util.concurrent.Callable; +import java.util.stream.Collectors; +import lombok.extern.slf4j.Slf4j; +import me.tongfei.progressbar.ProgressBar; +import org.tron.plugins.utils.DBUtils; +import org.tron.plugins.utils.FileUtils; +import picocli.CommandLine; + + +@Slf4j(topic = "copy") +@CommandLine.Command(name = "cp", aliases = "copy", + description = "Quick copy leveldb or rocksdb data.", + exitCodeListHeading = "Exit Codes:%n", + exitCodeList = { + "0:Successful", + "n:Internal error: exception occurred,please check toolkit.log"}) +public class DbCopy implements Callable { + + + @CommandLine.Spec + CommandLine.Model.CommandSpec spec; + @CommandLine.Parameters(index = "0", defaultValue = "output-directory/database", + description = "Input path. Default: ${DEFAULT-VALUE}") + private File src; + @CommandLine.Parameters(index = "1", defaultValue = "output-directory-cp/database", + description = "Output path. Default: ${DEFAULT-VALUE}") + private File dest; + + @CommandLine.Option(names = {"-h", "--help"}) + private boolean help; + + + @Override + public Integer call() throws Exception { + if (help) { + spec.commandLine().usage(System.out); + return 0; + } + if (dest.exists()) { + logger.info(" {} exist, please delete it first.", dest); + spec.commandLine().getErr().println(spec.commandLine().getColorScheme() + .errorText(String.format("%s exist, please delete it first.", dest))); + return 402; + } + if (!src.exists()) { + logger.info(" {} does not exist.", src); + spec.commandLine().getErr().println(spec.commandLine().getColorScheme() + .errorText(String.format("%s does not exist.", src))); + return 404; + } + + if (!src.isDirectory()) { + logger.info(" {} is not a directory.", src); + spec.commandLine().getErr().println(spec.commandLine().getColorScheme() + .errorText(String.format("%s is not a directory.", src))); + return 403; + } + + List files = Arrays.stream(Objects.requireNonNull(src.listFiles())) + .filter(File::isDirectory) + .filter(e -> !DBUtils.CHECKPOINT_DB_V2.equals(e.getName())) + .collect(Collectors.toList()); + + // add checkpoint v2 convert + File cpV2Dir = new File(Paths.get(src.toString(), DBUtils.CHECKPOINT_DB_V2).toString()); + List cpList = new ArrayList<>(); + if (cpV2Dir.exists()) { + cpList = Arrays.stream(Objects.requireNonNull(cpV2Dir.listFiles())) + .filter(File::isDirectory) + .collect(Collectors.toList()); + } + + if (files.isEmpty()) { + logger.info("{} does not contain any database.", src); + spec.commandLine().getOut().format("%s does not contain any database.", src).println(); + return 0; + } + final long time = System.currentTimeMillis(); + List services = new ArrayList<>(); + files.forEach(f -> services.add( + new DbCopier(src.getPath(), dest.getPath(), f.getName()))); + cpList.forEach(f -> services.add( + new DbCopier( + Paths.get(src.getPath(), DBUtils.CHECKPOINT_DB_V2).toString(), + Paths.get(dest.getPath(), DBUtils.CHECKPOINT_DB_V2).toString(), + f.getName()))); + List fails = ProgressBar.wrap(services.stream(), "copy task").parallel().map( + dbCopier -> { + try { + return dbCopier.doCopy() ? null : dbCopier.name(); + } catch (Exception e) { + logger.error("{}", e); + spec.commandLine().getErr().println(spec.commandLine().getColorScheme() + .errorText(e.getMessage())); + return dbCopier.name(); + } + }).filter(Objects::nonNull).collect(Collectors.toList()); + // copy info.properties if lite need + Arrays.stream(Objects.requireNonNull(src.listFiles())) + .filter(File::isFile).forEach(f -> FileUtils.copy(Paths.get(src.toString(), f.getName()), + Paths.get(dest.toString(), f.getName()))); + long during = (System.currentTimeMillis() - time) / 1000; + spec.commandLine().getOut().format("copy db done, fails: %s, take %d s.", + fails, during).println(); + logger.info("database copy use {} seconds total, fails: {}.", during, fails); + return fails.size(); + } + + interface Copier { + + boolean doCopy(); + + String name(); + } + + static class DbCopier implements Copier { + private final String srcDir; + private final String dstDir; + private final String dbName; + private final Path srcDbPath; + private final Path dstDbPath; + + public DbCopier(String srcDir, String dstDir, String name) { + this.srcDir = srcDir; + this.dstDir = dstDir; + this.dbName = name; + this.srcDbPath = Paths.get(this.srcDir, name); + this.dstDbPath = Paths.get(this.dstDir, name); + } + + @Override + public boolean doCopy() { + File srcDb = srcDbPath.toFile(); + if (!srcDb.exists()) { + logger.info(" {} does not exist.", srcDb); + return true; + } + FileUtils.createDirIfNotExists(dstDir); + logger.info("Copy database {} start", this.dbName); + FileUtils.copyDir(Paths.get(srcDir), Paths.get(dstDir), dbName); + logger.info("Copy database {} end", this.dbName); + return true; + } + + @Override + public String name() { + return dbName; + } + } + +} diff --git a/plugins/src/main/java/org/tron/plugins/DbLite.java b/plugins/src/main/java/org/tron/plugins/DbLite.java index 51b588bf9b5..c4ea5872a51 100644 --- a/plugins/src/main/java/org/tron/plugins/DbLite.java +++ b/plugins/src/main/java/org/tron/plugins/DbLite.java @@ -591,8 +591,7 @@ private void mergeBak2Database(String liteDir, BlockNumInfo blockNumInfo) throws } else { iterator.seek(head); } - ProgressBar.wrap(iterator, dbName) - .forEachRemaining(e -> destDb.put(e.getKey(), e.getValue())); + iterator.forEachRemaining(e -> destDb.put(e.getKey(), e.getValue())); } } catch (IOException | RocksDBException e) { throw new RuntimeException(e);