Closed onesand closed 3 years ago
In Trust Wallet we use derivation path m/84'/0'/0'/0/0
, and SegwitAddress (native segwit).
Please double check derivation path, and prefix used. How did you derive expected address? If you provide an example with a private key that can be shared, we can check.
StoredKey storedKey = StoredKey.importHDWallet(mnemonic,"test",newPassword.getBytes(),CoinType.ETHEREUM);
HDWallet wallet = storedKey.wallet(newPassword.getBytes());
String bip49DerivationPath = "m/49'/0'/0'/0/0";
PrivateKey bip49PrivateKey = wallet.getKey(CoinType.BITCOIN,bip49DerivationPath);
PublicKey publicKey = bip49PrivateKey.getPublicKeySecp256k1(true);
BitcoinAddress bitcoinAddress = new BitcoinAddress(publicKey,CoinType.BITCOIN.p2shPrefix());
LogUtils.ln("bitcoinAddress.description()",bitcoinAddress.description());
print:33KPW4uKuyVFsCEh4YgDMF58zprnb817jZ
But in this(https://iancoleman.io/bip39/) is 3PQ5BD39rDikf7YW6pJ9a9tbS3QhvwvzTG
my mnemonic:cluster model myself pet impose acquire flip breeze pass energy inch grant
I have verified that public key matches ('039d645d2ce630c2a9a6dbe0cbd0a8fcb7b70241cb8a48424f25593290af2494b9'), this means derivation path, mnemonic, private key also matches. Derived address is indeed different. Investigating.
cluster model myself pet impose acquire flip breeze pass energy inch grant
m/49'/0'/0'/0/0
and coin 0
: aa3858e668530a3cc6e1b4c685c190994a7dc6adfd4423cd48ad1599a897c48c
039d645d2ce630c2a9a6dbe0cbd0a8fcb7b70241cb8a48424f25593290af2494b9
11d91ce1cc681f95583da3f4a6841c174be950c7
05
prepended, and Base58-encoded: '33KPW4uKuyVFsCEh4YgDMF58zprnb817jZ'The reference iancoleman test produces the same 2. & 3., 4. is not visible, and the address 5. is different:
'3PQ5BD39rDikf7YW6pJ9a9tbS3QhvwvzTG'
This corresponds to data 05ee1e69460b59027d9df0a79ca2c92aa382a25fb7
.
The difference seems to be in getting the address from public key (so not with HD derivation, derivation path or prefix byte).
Here is the answer: The Bitcoin::Address class is used for both p2pkh and p2sh addresses. The pubkey-based constructor makes sense only for p2pkh addresses, but not for p2sh. For p2sh one has to take the pubkey hash, build a script (prepend 0014), take the script hash, prepend 05, and create Address from that data.
See also: https://github.com/trustwallet/wallet-core/discussions/1342
Test code:
const auto wallet = HDWallet("cluster model myself pet impose acquire flip breeze pass energy inch grant", "");
const auto privateKey = wallet.getKey(TWCoinTypeBitcoin, DerivationPath("m/49'/0'/0'/0/0")); // aa3858e668530a3cc6e1b4c685c190994a7dc6adfd4423cd48ad1599a897c48c
const auto publicKey = privateKey.getPublicKey(TWPublicKeyTypeSECP256k1); // 039d645d2ce630c2a9a6dbe0cbd0a8fcb7b70241cb8a48424f25593290af2494b9
const auto pubKeyHash = publicKey.hash({}); // 11d91ce1cc681f95583da3f4a6841c174be950c7
const auto script = Script::buildPayToWitnessProgram(pubKeyHash); // 0014 11d91ce1cc681f95583da3f4a6841c174be950c
const auto scriptHash = Hash::sha256ripemd(script.bytes.data(), script.bytes.size()); // ee1e69460b59027d9df0a79ca2c92aa382a25fb7
Data addrdat = {TWCoinTypeP2shPrefix(TWCoinTypeBitcoin)};
TW::append(addrdat, scriptHash); // 05ee1e69460b59027d9df0a79ca2c92aa382a25fb7
const auto addr = Address(addrdat); // 3PQ5BD39rDikf7YW6pJ9a9tbS3QhvwvzTG
Thank you for your help.
But how to write in java or kotlin?I can't find buildPayToWitnessProgram
Here is the answer: The Bitcoin::Address class is used for both p2pkh and p2sh addresses. The pubkey-based constructor makes sense only for p2pkh addresses, but not for p2sh. For p2sh one has to take the pubkey hash, build a script (prepend 0014), take the script hash, prepend 05, and create Address from that data.
See also: #1342
Test code:
const auto wallet = HDWallet("cluster model myself pet impose acquire flip breeze pass energy inch grant", ""); const auto privateKey = wallet.getKey(TWCoinTypeBitcoin, DerivationPath("m/49'/0'/0'/0/0")); // aa3858e668530a3cc6e1b4c685c190994a7dc6adfd4423cd48ad1599a897c48c const auto publicKey = privateKey.getPublicKey(TWPublicKeyTypeSECP256k1); // 039d645d2ce630c2a9a6dbe0cbd0a8fcb7b70241cb8a48424f25593290af2494b9 const auto pubKeyHash = publicKey.hash({}); // 11d91ce1cc681f95583da3f4a6841c174be950c7 const auto script = Script::buildPayToWitnessProgram(pubKeyHash); // 0014 11d91ce1cc681f95583da3f4a6841c174be950c const auto scriptHash = Hash::sha256ripemd(script.bytes.data(), script.bytes.size()); // ee1e69460b59027d9df0a79ca2c92aa382a25fb7 Data addrdat = {TWCoinTypeP2shPrefix(TWCoinTypeBitcoin)}; TW::append(addrdat, scriptHash); // 05ee1e69460b59027d9df0a79ca2c92aa382a25fb7 const auto addr = Address(addrdat); // 3PQ5BD39rDikf7YW6pJ9a9tbS3QhvwvzTG
Check out TWHashRIPEMD
in TWHash
(it is exposed to java side)
can i spend p2sh's address utxo? @optout21 , i found buildPayToWitnessScriptHash
, buildPayToWitnessPubkeyHash
, not found buildPayToWitnessProgram
.
bitcoinAddress.description() = 31tg3fdy2Nbm7KtQQZ5stx3op2FdxoL4aY
But real address is 3KMuxpzDyXkaFEa54AiToSvnyqhBAG6gK5