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
37 changes: 37 additions & 0 deletions src/main/java/org/tron/common/utils/PathUtil.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package org.tron.common.utils;

import java.io.IOException;
import java.nio.file.InvalidPathException;
import java.nio.file.Path;
import java.nio.file.Paths;

public class PathUtil {
public static String toAbsolutePath(String inputPath) throws IOException {
if (inputPath == null || inputPath.trim().isEmpty()) {
throw new IllegalArgumentException("Input path cannot be null or empty");
}
try {
Path path = Paths.get(inputPath);
if (inputPath.startsWith("~/") || inputPath.startsWith("~\\")) {
String userHome = System.getProperty("user.home");
path = Paths.get(userHome, inputPath.substring(2));
}
Path absolutePath = path.toAbsolutePath().normalize();
return absolutePath.toString();
} catch (InvalidPathException e) {
throw new IOException("Invalid path: " + inputPath, e);
}
}

public static String getTempDirectoryPath() {
String osName = System.getProperty("os.name").toLowerCase();

if (osName.contains("win")) {
return System.getenv("TEMP");
} else if (osName.contains("mac") || osName.contains("nix") || osName.contains("nux")) {
return "/tmp";
} else {
throw new UnsupportedOperationException("Unsupported operating system: " + osName);
}
}
}
24 changes: 24 additions & 0 deletions src/main/java/org/tron/keystore/WalletUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,26 @@ public static String generateWalletFile(WalletFile walletFile, File destinationD
return fileName;
}

public static String exportWalletFile(WalletFile walletFile, String walletAddress, File destinationDirectory)
throws IOException {
String fileName = getExportWalletFileName(walletAddress);
File destination = new File(destinationDirectory, fileName);

objectMapper.writeValue(destination, walletFile);
return fileName;
}

public static String importWalletFile(WalletFile walletFile, File destinationDirectory)
throws IOException {
/*
String fileName = getWalletFileName(walletFile);
File destination = new File(destinationDirectory, fileName);

objectMapper.writeValue(destination, walletFile);
return fileName;
*/
return "";
}
// /**
// * Generates a BIP-39 compatible Ethereum wallet. The private key for the wallet can
// * be calculated using following algorithm:
Expand Down Expand Up @@ -164,6 +184,10 @@ private static String getWalletFileName(WalletFile walletFile) {
return walletFile.getAddress() + ".json";
}

private static String getExportWalletFileName(String walletAddress) {
return walletAddress + ".txt";
}

public static String getDefaultKeyDirectory() {
return getDefaultKeyDirectory(System.getProperty("os.name"));
}
Expand Down
90 changes: 90 additions & 0 deletions src/main/java/org/tron/walletcli/Client.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
import java.io.File;
import java.io.IOException;
import java.math.BigInteger;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.Base64.Decoder;
Expand Down Expand Up @@ -32,6 +34,7 @@
import org.tron.common.utils.Base58;
import org.tron.common.utils.ByteArray;
import org.tron.common.utils.ByteUtil;
import org.tron.common.utils.PathUtil;
import org.tron.common.utils.Utils;
import org.tron.common.zksnark.JLibrustzcash;
import org.tron.common.zksnark.LibrustzcashParam;
Expand All @@ -51,6 +54,9 @@
import org.tron.core.zen.address.PaymentAddress;
import org.tron.core.zen.address.SpendingKey;
import org.tron.keystore.StringUtils;
import org.tron.keystore.Wallet;
import org.tron.keystore.WalletFile;
import org.tron.keystore.WalletUtils;
import org.tron.mnemonic.MnemonicUtils;
import org.tron.protos.Protocol.MarketOrder;
import org.tron.protos.Protocol.MarketOrderList;
Expand Down Expand Up @@ -87,6 +93,8 @@ public class Client {
"BackupWallet",
"BackupWallet2Base64",
"ExportWalletMnemonic",
"ExportWalletKeystore",
"ImportWalletByKeystore",
"BroadcastTransaction",
"CancelAllUnfreezeV2",
"ChangePassword",
Expand Down Expand Up @@ -235,6 +243,8 @@ public class Client {
"BackupWallet",
"BackupWallet2Base64",
"ExportWalletMnemonic",
"ExportWalletKeystore",
"ImportWalletByKeystore",
"BroadcastTransaction",
"CancelAllUnfreezeV2",
"ChangePassword",
Expand Down Expand Up @@ -681,6 +691,78 @@ private void exportWalletMnemonic() throws IOException, CipherException {
clearChars(mnemonicChars);
}

private void exportWalletKeystore(String[] parameters) throws CipherException, IOException {
if (parameters.length < 2) {
String tempPath = PathUtil.getTempDirectoryPath();
System.out.println("Example usage: ExportWalletKeystore tronlink " + tempPath);
System.out.println("exportWalletKeystore failed, parameters error !!");
return;
}

String channel = parameters[0];
if (!channel.equalsIgnoreCase("tronlink")) {
System.out.println("exportWalletKeystore failed, channel error !!");
System.out.println("currrently only tronlink is supported!!");
}
String exportDirPath = parameters[1];
String exportFullDirPath = PathUtil.toAbsolutePath(exportDirPath);
File exportFullDir = new File(exportFullDirPath);
if (!exportFullDir.exists()) {
throw new IOException("Directory does not exist: " + exportFullDir.getAbsolutePath());
}
if (!exportFullDir.canWrite()) {
throw new IOException("Directory is not writable: " + exportFullDir.getAbsolutePath());
}

String exportFilePath = walletApiWrapper.exportKeystore(channel, exportFullDir);
if (exportFilePath != null) {
System.out.println("exported keystore file : " + Paths.get(exportFullDirPath, exportFilePath));
System.out.println("exportWalletKeystore successful !!");
} else {
System.out.println("exportWalletKeystore failed !!");
}
}

private void importWalletByKeystore(String[] parameters) throws CipherException, IOException {
if (parameters.length < 2) {
System.out.println("Example usage: ImportWalletByKeystore tronlink tronlink-export-keystore.txt");
System.out.println("importWalletByKeystore failed, parameters error !!");
return;
}

String channel = parameters[0];
if (!channel.equalsIgnoreCase("tronlink")) {
System.out.println("importWalletByKeystore failed, channel error !!");
return ;
}
String importPath = parameters[1];
String importFilePath = PathUtil.toAbsolutePath(importPath);
File importFile = new File(importFilePath);
if (!importFile.exists()) {
System.out.println("importWalletByKeystore failed, keystore file to import not exists !!");
return ;
}

char[] password = Utils.inputPassword2Twice();
byte[] passwdByte = StringUtils.char2Byte(password);

try {
String fileName = walletApiWrapper.importWalletByKeystore(passwdByte, password, importFile);
if (fileName != null) {
System.out.println("fileName = " + fileName);
System.out.println("importWalletByKeystore successful !!");
} else {
System.out.println("importWalletByKeystore failed !!");
}
} catch (Exception e) {
System.out.println("importWalletByKeystore failed !!");
} finally {
StringUtils.clear(password);
StringUtils.clear(passwdByte);
}

}

private char[] bytesToChars(byte[] bytes) {
char[] chars = new char[bytes.length];
for (int i = 0; i < bytes.length; i++) {
Expand Down Expand Up @@ -4663,6 +4745,14 @@ private void run() {
exportWalletMnemonic();
break;
}
case "exportwalletkeystore": {
exportWalletKeystore(parameters);
break;
}
case "importwalletbykeystore": {
importWalletByKeystore(parameters);
break;
}
case "getaddress": {
getAddress();
break;
Expand Down
32 changes: 32 additions & 0 deletions src/main/java/org/tron/walletcli/WalletApiWrapper.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import org.tron.common.utils.AbiUtil;
import org.tron.common.utils.ByteArray;
import org.tron.common.utils.ByteUtil;
import org.tron.common.utils.PathUtil;
import org.tron.common.utils.Utils;
import org.tron.core.exception.CancelException;
import org.tron.core.exception.CipherException;
Expand All @@ -29,6 +30,7 @@
import org.tron.core.zen.address.FullViewingKey;
import org.tron.core.zen.address.SpendingKey;
import org.tron.keystore.StringUtils;
import org.tron.keystore.Wallet;
import org.tron.keystore.WalletFile;
import org.tron.keystore.WalletUtils;
import org.tron.mnemonic.MnemonicUtils;
Expand Down Expand Up @@ -187,6 +189,36 @@ public byte[] exportWalletMnemonic() throws IOException, CipherException {
return MnemonicUtils.exportMnemonic(passwd, getAddress());
}

public String exportKeystore(String walletChannel, File exportFullDir)
throws IOException, CipherException {
if (wallet == null || !wallet.isLoginState()) {
System.out.println("Warning: ExportKeystore failed, Please login first !!");
return null;
}

//1.input password
System.out.println("Please input your password.");
char[] password = Utils.inputPassword(false);
byte[] passwd = StringUtils.char2Byte(password);
try {
wallet.checkPassword(passwd);
} finally {
StringUtils.clear(password);
StringUtils.clear(passwd);
}

return wallet.exportKeystore(walletChannel, exportFullDir);
}

public String importWalletByKeystore(byte[] passwdByte, char[] password, File importFile)
throws IOException, CipherException {
WalletFile walletFile = WalletUtils.loadWalletFile(importFile);
byte[] priKey = Wallet.decrypt2PrivateBytes(passwdByte, walletFile);
String fileName = importWallet(password, priKey, null);

return fileName;
}

public String getAddress() {
if (wallet == null || !wallet.isLoginState()) {
// System.out.println("Warning: GetAddress failed, Please login first !!");
Expand Down
35 changes: 35 additions & 0 deletions src/main/java/org/tron/walletserver/WalletApi.java
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@
import org.tron.common.crypto.sm2.SM2;
import org.tron.common.utils.Base58;
import org.tron.common.utils.ByteArray;
import org.tron.common.utils.PathUtil;
import org.tron.common.utils.TransactionUtils;
import org.tron.common.utils.Utils;
import org.tron.common.zksnark.JLibrustzcash;
Expand Down Expand Up @@ -340,6 +341,30 @@ public byte[] getPrivateBytes(byte[] password) throws CipherException, IOExcepti
return Wallet.decrypt2PrivateBytes(password, walletFile);
}

public String exportKeystore(String walletChannel, File exportFullDir) throws IOException {
String ret = null;
try {
WalletFile walletFile = loadWalletFile();
String walletAddress = walletFile.getAddress();
String walletHexAddress = getHexAddress(walletFile.getAddress());
walletFile.setAddress(walletHexAddress);

ret = WalletUtils.exportWalletFile(walletFile, walletAddress, exportFullDir);
} catch (Exception e) {
System.out.println("exportKeystore failed. " + e.getMessage());
}
return ret;
}

public boolean importKeystore(String walletChannel, String walletImportPath) throws IOException {
String importFilePath = PathUtil.toAbsolutePath(walletImportPath);
File importFile = new File(importFilePath);

//WalletFile walletFile =
//WalletUtils.importWalletFile(walletFile, importFile);
return true;
}

public byte[] getAddress() {
return address;
}
Expand Down Expand Up @@ -371,6 +396,7 @@ public static String store2Keystore(WalletFile walletFile) throws IOException {
return WalletUtils.generateWalletFile(walletFile, file);
}


public static File selcetWalletFile() {
File file = new File(FilePath);
if (!file.exists() || !file.isDirectory()) {
Expand Down Expand Up @@ -1146,6 +1172,15 @@ public static byte[] decodeFromBase58Check(String addressBase58) {
return address;
}

public static String getHexAddress(final String address) {
if (address != null) {
byte[] addressByte = decodeFromBase58Check(address);
return ByteArray.toHexString(addressByte);
} else {
return null;
}
}

public static boolean priKeyValid(byte[] priKey) {
if (ArrayUtils.isEmpty(priKey)) {
System.out.println("Warning: PrivateKey is empty !!");
Expand Down