mirror of
https://github.com/bisq-network/bisq.git
synced 2025-02-24 07:07:43 +01:00
Perform segwit BSQ wallet migration upon startup
Uncomment & enable the m/44'/142'/1' native segwit BSQ account path and add code to migrate the user's BSQ wallet to segwit upon startup, along the same lines as the existing BTC wallet segwit migration logic. That is, set P2WPKH as the default output type, add a native segwit key chain (set to active) to the BSQ wallet and back up the old 'bisq_BSQ.wallet' file to 'pre_segwit_bisq_BSQ.wallet.backup'. Also filter out legacy addresses coming from the original keychain from BsqWalletService.get(Unused|Change)Address.
This commit is contained in:
parent
3470429746
commit
5f1e32a226
6 changed files with 54 additions and 34 deletions
|
@ -581,7 +581,8 @@ class CoreWalletsService {
|
|||
if (btcWalletService.getAesKey() == null || bsqWalletService.getAesKey() == null) {
|
||||
KeyParameter aesKey = new KeyParameter(tempAesKey.getKey());
|
||||
walletsManager.setAesKey(aesKey);
|
||||
walletsSetup.getWalletConfig().maybeAddSegwitKeychain(walletsSetup.getWalletConfig().btcWallet(), aesKey);
|
||||
walletsSetup.getWalletConfig().maybeAddSegwitKeychain(walletsSetup.getWalletConfig().btcWallet(), aesKey, false);
|
||||
walletsSetup.getWalletConfig().maybeAddSegwitKeychain(walletsSetup.getWalletConfig().bsqWallet(), aesKey, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -424,7 +424,9 @@ public class BisqSetup {
|
|||
requestWalletPasswordHandler.accept(aesKey -> {
|
||||
walletsManager.setAesKey(aesKey);
|
||||
walletsSetup.getWalletConfig().maybeAddSegwitKeychain(walletsSetup.getWalletConfig().btcWallet(),
|
||||
aesKey);
|
||||
aesKey, false);
|
||||
walletsSetup.getWalletConfig().maybeAddSegwitKeychain(walletsSetup.getWalletConfig().bsqWallet(),
|
||||
aesKey, true);
|
||||
if (getResyncSpvSemaphore()) {
|
||||
if (showFirstPopupIfResyncSPVRequestedHandler != null)
|
||||
showFirstPopupIfResyncSPVRequestedHandler.run();
|
||||
|
|
|
@ -47,13 +47,12 @@ public class BisqKeyChainGroupStructure implements KeyChainGroupStructure {
|
|||
new ChildNumber(142, true),
|
||||
ChildNumber.ZERO_HARDENED);
|
||||
|
||||
// We don't use segwit for BSQ
|
||||
// public static final ImmutableList<ChildNumber> BIP44_BSQ_SEGWIT_ACCOUNT_PATH = ImmutableList.of(
|
||||
// new ChildNumber(44, true),
|
||||
// new ChildNumber(142, true),
|
||||
// ChildNumber.ONE_HARDENED);
|
||||
public static final ImmutableList<ChildNumber> BIP44_BSQ_SEGWIT_ACCOUNT_PATH = ImmutableList.of(
|
||||
new ChildNumber(44, true),
|
||||
new ChildNumber(142, true),
|
||||
ChildNumber.ONE_HARDENED);
|
||||
|
||||
private boolean isBsqWallet;
|
||||
private final boolean isBsqWallet;
|
||||
|
||||
public BisqKeyChainGroupStructure(boolean isBsqWallet) {
|
||||
this.isBsqWallet = isBsqWallet;
|
||||
|
@ -72,8 +71,7 @@ public class BisqKeyChainGroupStructure implements KeyChainGroupStructure {
|
|||
if (outputScriptType == null || outputScriptType == Script.ScriptType.P2PKH)
|
||||
return BIP44_BSQ_NON_SEGWIT_ACCOUNT_PATH;
|
||||
else if (outputScriptType == Script.ScriptType.P2WPKH)
|
||||
//return BIP44_BSQ_SEGWIT_ACCOUNT_PATH;
|
||||
throw new IllegalArgumentException(outputScriptType.toString());
|
||||
return BIP44_BSQ_SEGWIT_ACCOUNT_PATH;
|
||||
else
|
||||
throw new IllegalArgumentException(outputScriptType.toString());
|
||||
}
|
||||
|
|
|
@ -57,6 +57,7 @@ import com.google.common.util.concurrent.Futures;
|
|||
import com.google.common.util.concurrent.ListenableFuture;
|
||||
import com.google.common.util.concurrent.MoreExecutors;
|
||||
|
||||
import javafx.beans.binding.BooleanExpression;
|
||||
import javafx.beans.property.BooleanProperty;
|
||||
import javafx.beans.property.SimpleBooleanProperty;
|
||||
|
||||
|
@ -143,7 +144,11 @@ public class WalletConfig extends AbstractIdleService {
|
|||
@Setter
|
||||
private int minBroadcastConnections;
|
||||
@Getter
|
||||
private BooleanProperty migratedWalletToSegwit = new SimpleBooleanProperty(false);
|
||||
private BooleanProperty migratedWalletToBtcSegwit = new SimpleBooleanProperty(false);
|
||||
@Getter
|
||||
private BooleanProperty migratedWalletToBsqSegwit = new SimpleBooleanProperty(false);
|
||||
@Getter
|
||||
private BooleanExpression migratedWalletToSegwit = migratedWalletToBtcSegwit.and(migratedWalletToBsqSegwit);
|
||||
|
||||
/**
|
||||
* Creates a new WalletConfig, with a newly created {@link Context}. Files will be stored in the given directory.
|
||||
|
@ -406,15 +411,13 @@ public class WalletConfig extends AbstractIdleService {
|
|||
wallet = serializer.readWallet(params, extArray, proto);
|
||||
if (shouldReplayWallet)
|
||||
wallet.reset();
|
||||
if (!isBsqWallet) {
|
||||
maybeAddSegwitKeychain(wallet, null);
|
||||
}
|
||||
maybeAddSegwitKeychain(wallet, null, isBsqWallet);
|
||||
}
|
||||
return wallet;
|
||||
}
|
||||
|
||||
protected Wallet createWallet(boolean isBsqWallet) {
|
||||
Script.ScriptType preferredOutputScriptType = isBsqWallet ? Script.ScriptType.P2PKH : Script.ScriptType.P2WPKH;
|
||||
Script.ScriptType preferredOutputScriptType = Script.ScriptType.P2WPKH;
|
||||
KeyChainGroupStructure structure = new BisqKeyChainGroupStructure(isBsqWallet);
|
||||
KeyChainGroup.Builder kcgBuilder = KeyChainGroup.builder(params, structure);
|
||||
if (restoreFromSeed != null) {
|
||||
|
@ -545,21 +548,29 @@ public class WalletConfig extends AbstractIdleService {
|
|||
return directory;
|
||||
}
|
||||
|
||||
public void maybeAddSegwitKeychain(Wallet wallet, KeyParameter aesKey) {
|
||||
if (BisqKeyChainGroupStructure.BIP44_BTC_NON_SEGWIT_ACCOUNT_PATH.equals(wallet.getActiveKeyChain().getAccountPath())) {
|
||||
public void maybeAddSegwitKeychain(Wallet wallet, KeyParameter aesKey, boolean isBsqWallet) {
|
||||
var nonSegwitAccountPath = isBsqWallet
|
||||
? BisqKeyChainGroupStructure.BIP44_BSQ_NON_SEGWIT_ACCOUNT_PATH
|
||||
: BisqKeyChainGroupStructure.BIP44_BTC_NON_SEGWIT_ACCOUNT_PATH;
|
||||
var preSegwitBackupFilename = isBsqWallet
|
||||
? WalletsSetup.PRE_SEGWIT_BSQ_WALLET_BACKUP
|
||||
: WalletsSetup.PRE_SEGWIT_BTC_WALLET_BACKUP;
|
||||
var walletFilename = isBsqWallet ? "bisq_BSQ.wallet" : "bisq_BTC.wallet";
|
||||
|
||||
if (nonSegwitAccountPath.equals(wallet.getActiveKeyChain().getAccountPath())) {
|
||||
if (wallet.isEncrypted() && aesKey == null) {
|
||||
// wait for the aesKey to be set and this method to be invoked again.
|
||||
return;
|
||||
}
|
||||
// Do a backup of the wallet
|
||||
File backup = new File(directory, WalletsSetup.PRE_SEGWIT_WALLET_BACKUP);
|
||||
File backup = new File(directory, preSegwitBackupFilename);
|
||||
try {
|
||||
FileUtil.copyFile(new File(directory, "bisq_BTC.wallet"), backup);
|
||||
FileUtil.copyFile(new File(directory, walletFilename), backup);
|
||||
} catch (IOException e) {
|
||||
log.error(e.toString(), e);
|
||||
}
|
||||
|
||||
// Btc wallet does not have a native segwit keychain, we should add one.
|
||||
// Wallet does not have a native segwit keychain, we should add one.
|
||||
DeterministicSeed seed = wallet.getKeyChainSeed();
|
||||
if (aesKey != null) {
|
||||
// If wallet is encrypted, decrypt the seed.
|
||||
|
@ -568,7 +579,7 @@ public class WalletConfig extends AbstractIdleService {
|
|||
}
|
||||
DeterministicKeyChain nativeSegwitKeyChain = DeterministicKeyChain.builder().seed(seed)
|
||||
.outputScriptType(Script.ScriptType.P2WPKH)
|
||||
.accountPath(new BisqKeyChainGroupStructure(false).accountPathFor(Script.ScriptType.P2WPKH)).build();
|
||||
.accountPath(new BisqKeyChainGroupStructure(isBsqWallet).accountPathFor(Script.ScriptType.P2WPKH)).build();
|
||||
if (aesKey != null) {
|
||||
// If wallet is encrypted, encrypt the new keychain.
|
||||
KeyCrypter keyCrypter = wallet.getKeyCrypter();
|
||||
|
@ -576,7 +587,11 @@ public class WalletConfig extends AbstractIdleService {
|
|||
}
|
||||
wallet.addAndActivateHDChain(nativeSegwitKeyChain);
|
||||
}
|
||||
migratedWalletToSegwit.set(true);
|
||||
if (isBsqWallet) {
|
||||
migratedWalletToBsqSegwit.set(true);
|
||||
} else {
|
||||
migratedWalletToBtcSegwit.set(true);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean stateStartingOrRunning() {
|
||||
|
|
|
@ -109,7 +109,8 @@ import static com.google.common.base.Preconditions.checkNotNull;
|
|||
@Slf4j
|
||||
public class WalletsSetup {
|
||||
|
||||
public static final String PRE_SEGWIT_WALLET_BACKUP = "pre_segwit_bisq_BTC.wallet.backup";
|
||||
public static final String PRE_SEGWIT_BTC_WALLET_BACKUP = "pre_segwit_bisq_BTC.wallet.backup";
|
||||
public static final String PRE_SEGWIT_BSQ_WALLET_BACKUP = "pre_segwit_bisq_BSQ.wallet.backup";
|
||||
|
||||
@Getter
|
||||
public final BooleanProperty walletsSetupFailed = new SimpleBooleanProperty();
|
||||
|
@ -427,12 +428,14 @@ public class WalletsSetup {
|
|||
e.printStackTrace();
|
||||
}
|
||||
|
||||
File segwitBackup = new File(walletDir, PRE_SEGWIT_WALLET_BACKUP);
|
||||
List.of(PRE_SEGWIT_BTC_WALLET_BACKUP, PRE_SEGWIT_BSQ_WALLET_BACKUP).forEach(filename -> {
|
||||
File segwitBackup = new File(walletDir, filename);
|
||||
try {
|
||||
FileUtil.deleteFileIfExists(segwitBackup);
|
||||
} catch (IOException e) {
|
||||
log.error(e.toString(), e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -42,7 +42,6 @@ import org.bitcoinj.core.AddressFormatException;
|
|||
import org.bitcoinj.core.BlockChain;
|
||||
import org.bitcoinj.core.Coin;
|
||||
import org.bitcoinj.core.InsufficientMoneyException;
|
||||
import org.bitcoinj.core.LegacyAddress;
|
||||
import org.bitcoinj.core.NetworkParameters;
|
||||
import org.bitcoinj.core.Sha256Hash;
|
||||
import org.bitcoinj.core.Transaction;
|
||||
|
@ -50,6 +49,7 @@ import org.bitcoinj.core.TransactionConfidence;
|
|||
import org.bitcoinj.core.TransactionInput;
|
||||
import org.bitcoinj.core.TransactionOutPoint;
|
||||
import org.bitcoinj.core.TransactionOutput;
|
||||
import org.bitcoinj.script.Script;
|
||||
import org.bitcoinj.script.ScriptException;
|
||||
import org.bitcoinj.wallet.CoinSelection;
|
||||
import org.bitcoinj.wallet.CoinSelector;
|
||||
|
@ -807,12 +807,13 @@ public class BsqWalletService extends WalletService implements DaoStateListener
|
|||
// Addresses
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
private LegacyAddress getChangeAddress() {
|
||||
private Address getChangeAddress() {
|
||||
return getUnusedAddress();
|
||||
}
|
||||
|
||||
public LegacyAddress getUnusedAddress() {
|
||||
return (LegacyAddress) wallet.getIssuedReceiveAddresses().stream()
|
||||
public Address getUnusedAddress() {
|
||||
return wallet.getIssuedReceiveAddresses().stream()
|
||||
.filter(address -> Script.ScriptType.P2WPKH.equals(address.getOutputScriptType()))
|
||||
.filter(this::isAddressUnused)
|
||||
.findAny()
|
||||
.orElse(wallet.freshReceiveAddress());
|
||||
|
|
Loading…
Add table
Reference in a new issue