diff --git a/src/main/java/org/consenlabs/tokencore/wallet/Identity.java b/src/main/java/org/consenlabs/tokencore/wallet/Identity.java index 737cf0d..c9fcde2 100755 --- a/src/main/java/org/consenlabs/tokencore/wallet/Identity.java +++ b/src/main/java/org/consenlabs/tokencore/wallet/Identity.java @@ -175,6 +175,9 @@ public List deriveWallets(List chainTypes, String password) { case ChainType.EOS: wallet = deriveEOSWallet(mnemonics, password); break; + case ChainType.TRON: + wallet = deriveTronWallet(mnemonics, password); + break; default: throw new TokenException(String.format("Doesn't support deriving %s wallet", chainType)); } @@ -214,7 +217,9 @@ public List deriveWalletsByMnemonics(List chainTypes, String pas case ChainType.EOS: wallet = deriveEOSWallet(mnemonics, password); break; - + case ChainType.TRON: + wallet = deriveTronWallet(mnemonics, password); + break; default: throw new TokenException(String.format("Doesn't support deriving %s wallet", chainType)); } @@ -344,6 +349,16 @@ private Wallet deriveEthereumWallet(List mnemonics, String password) { return WalletManager.createWallet(keystore); } + private Wallet deriveTronWallet(List mnemonics, String password) { + Metadata walletMetadata = new Metadata(); + walletMetadata.setChainType(ChainType.TRON); + walletMetadata.setPasswordHint(this.getMetadata().getPasswordHint()); + walletMetadata.setSource(this.getMetadata().getSource()); + walletMetadata.setName("TRX"); + IMTKeystore keystore = V3MnemonicKeystore.create(walletMetadata, password, mnemonics, BIP44Util.TRON_PATH); + return WalletManager.createWallet(keystore); + } + private Wallet deriveEOSWallet(List mnemonics, String password) { Metadata metadata = new Metadata(); metadata.setChainType(ChainType.EOS); diff --git a/src/main/java/org/consenlabs/tokencore/wallet/address/AddressCreatorManager.java b/src/main/java/org/consenlabs/tokencore/wallet/address/AddressCreatorManager.java index 53cbec9..8ba2324 100755 --- a/src/main/java/org/consenlabs/tokencore/wallet/address/AddressCreatorManager.java +++ b/src/main/java/org/consenlabs/tokencore/wallet/address/AddressCreatorManager.java @@ -7,26 +7,40 @@ import org.consenlabs.tokencore.wallet.model.Messages; import org.consenlabs.tokencore.wallet.model.Metadata; import org.consenlabs.tokencore.wallet.model.TokenException; -import org.consenlabs.tokencore.wallet.network.LitecoinMainNetParams; +import org.consenlabs.tokencore.wallet.network.*; public class AddressCreatorManager { - public static AddressCreator getInstance(String type, boolean isMainnet, String segWit) { - if (ChainType.ETHEREUM.equals(type)) { - return new EthereumAddressCreator(); - }else if(ChainType.LITECOIN.equals(type)){ - NetworkParameters network= LitecoinMainNetParams.get(); - return new BitcoinAddressCreator(network); - } else if (ChainType.BITCOIN.equals(type)) { + public static AddressCreator getInstance(String type, boolean isMainnet, String segWit) { + if (ChainType.ETHEREUM.equals(type)) { + return new EthereumAddressCreator(); + } else if (ChainType.TRON.equals(type)) { + return new TronAddressCreator(); + } else if (ChainType.LITECOIN.equals(type)) { + NetworkParameters network = LitecoinMainNetParams.get(); + return new BitcoinAddressCreator(network); + } else if (ChainType.DASH.equals(type)) { + NetworkParameters network = DashMainNetParams.get(); + return new BitcoinAddressCreator(network); + } else if (ChainType.DOGECOIN.equals(type)) { + NetworkParameters network = DogecoinMainNetParams.get(); + return new BitcoinAddressCreator(network); + } else if (ChainType.BITCOINSV.equals(type)) { + NetworkParameters network = BitcoinSvMainNetParams.get(); + return new BitcoinAddressCreator(network); + } else if (ChainType.BITCOINCASH.equals(type)) { + NetworkParameters network = BitcoinCashMainNetParams.get(); + return new BitcoinAddressCreator(network); + } else if (ChainType.BITCOIN.equals(type)) { - NetworkParameters network = isMainnet ? MainNetParams.get() : TestNet3Params.get(); - if (Metadata.P2WPKH.equals(segWit)) { - return new SegWitBitcoinAddressCreator(network); - } - return new BitcoinAddressCreator(network); - } else { - throw new TokenException(Messages.WALLET_INVALID_TYPE); + NetworkParameters network = isMainnet ? MainNetParams.get() : TestNet3Params.get(); + if (Metadata.P2WPKH.equals(segWit)) { + return new SegWitBitcoinAddressCreator(network); + } + return new BitcoinAddressCreator(network); + } else { + throw new TokenException(Messages.WALLET_INVALID_TYPE); + } } - } } diff --git a/src/main/java/org/consenlabs/tokencore/wallet/address/TronAddressCreator.java b/src/main/java/org/consenlabs/tokencore/wallet/address/TronAddressCreator.java new file mode 100644 index 0000000..094c69a --- /dev/null +++ b/src/main/java/org/consenlabs/tokencore/wallet/address/TronAddressCreator.java @@ -0,0 +1,60 @@ +package org.consenlabs.tokencore.wallet.address; + +import org.bitcoinj.core.Base58; +import org.bitcoinj.core.ECKey; +import org.consenlabs.tokencore.foundation.crypto.Hash; +import org.consenlabs.tokencore.foundation.utils.NumericUtil; + +import java.math.BigInteger; +import java.util.Arrays; + +import static java.util.Arrays.copyOfRange; + +/** + * Created by pie on 2020/9/6 22: 28. + */ +public class TronAddressCreator implements AddressCreator { + + private static final byte ADD_PRE_FIX_BYTE_MAINNET = (byte) 0x41; + + private static final int PUBLIC_KEY_SIZE = 64; + + private String encode58Check(byte[] input) { + byte[] hash0 = Hash.sha256(input); + byte[] hash1 = Hash.sha256(hash0); + byte[] inputCheck = new byte[input.length + 4]; + System.arraycopy(input, 0, inputCheck, 0, input.length); + System.arraycopy(hash1, 0, inputCheck, input.length, 4); + return Base58.encode(inputCheck); + } + + public String fromPublicKey(BigInteger publicKey) { + byte[] pubKeyBytes = NumericUtil.bigIntegerToBytesWithZeroPadded(publicKey, PUBLIC_KEY_SIZE); + return publicKeyToAddress(pubKeyBytes); + } + + private String publicKeyToAddress(byte[] pubKeyBytes) { + byte[] hashedBytes = Hash.keccak256(pubKeyBytes); + byte[] address = copyOfRange(hashedBytes, 11, hashedBytes.length); + address[0] = ADD_PRE_FIX_BYTE_MAINNET; + return encode58Check(address); + } + + @Override + public String fromPrivateKey(String prvKeyHex) { + ECKey key = ECKey.fromPrivate(NumericUtil.hexToBytes(prvKeyHex), false); + return fromECKey(key); + } + + @Override + public String fromPrivateKey(byte[] prvKeyBytes) { + ECKey key = ECKey.fromPrivate(prvKeyBytes, false); + return fromECKey(key); + } + + private String fromECKey(ECKey key) { + byte[] pubKeyBytes = key.getPubKey(); + return publicKeyToAddress(Arrays.copyOfRange(pubKeyBytes, 1, pubKeyBytes.length)); + } + +} diff --git a/src/main/java/org/consenlabs/tokencore/wallet/model/BIP44Util.java b/src/main/java/org/consenlabs/tokencore/wallet/model/BIP44Util.java index 13728f6..f82e236 100755 --- a/src/main/java/org/consenlabs/tokencore/wallet/model/BIP44Util.java +++ b/src/main/java/org/consenlabs/tokencore/wallet/model/BIP44Util.java @@ -20,6 +20,7 @@ public class BIP44Util { public final static String EOS_PATH = "m/44'/194'"; public final static String EOS_SLIP48 = "m/48'/4'/0'/0'/0',m/48'/4'/1'/0'/0'"; public final static String EOS_LEDGER = "m/44'/194'/0'/0/0"; + public final static String TRON_PATH ="m/44'/195'/0'/0/0"; public static ImmutableList generatePath(String path) { diff --git a/src/main/java/org/consenlabs/tokencore/wallet/model/ChainType.java b/src/main/java/org/consenlabs/tokencore/wallet/model/ChainType.java index df470dc..d307f46 100755 --- a/src/main/java/org/consenlabs/tokencore/wallet/model/ChainType.java +++ b/src/main/java/org/consenlabs/tokencore/wallet/model/ChainType.java @@ -9,6 +9,7 @@ public class ChainType { public final static String BITCOINCASH = "BITCOINCASH"; public final static String BITCOINSV = "BITCOINSV"; public final static String DOGECOIN = "DOGECOIN"; + public final static String TRON = "TRON"; public static void validate(String type) { @@ -19,7 +20,8 @@ public static void validate(String type) { !DASH.equals(type) && !BITCOINSV.equals(type) && !BITCOINCASH.equals(type) && - !DOGECOIN.equals(type)) { + !DOGECOIN.equals(type) && + !TRON.equals(type)) { throw new TokenException(Messages.WALLET_INVALID_TYPE); } }