Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add segwit support to the BTC wallet #4568

Merged
merged 30 commits into from
Oct 8, 2020
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
f13a7b1
Create a P2WPKH keychain for new btc wallets
oscarguindzberg Sep 14, 2020
cd28660
Add a P2WPKH keychain for existing wallets
oscarguindzberg Sep 14, 2020
ced357c
AddressEntry: Add boolean segwit flag
oscarguindzberg Sep 14, 2020
e85c66b
Stop using LegacyAddress for btc addresses
oscarguindzberg Sep 14, 2020
0c7f345
Fix log msg in BtcCoinSelector
oscarguindzberg Sep 14, 2020
0f4c66f
Comment out segwit BSQ account path
oscarguindzberg Sep 29, 2020
2551571
TradeWalletService: adapt to segwit wallet
oscarguindzberg Sep 29, 2020
d8b7557
WalletService: adapt to segwit wallet
oscarguindzberg Sep 29, 2020
a370848
New AddressEntry: use different script types
oscarguindzberg Sep 25, 2020
a9cc28f
AddressEntryList: arbitrator entry use P2PKH
oscarguindzberg Sep 25, 2020
f9f5d92
Add segwit/legacy checbox for address creation
oscarguindzberg Sep 25, 2020
1f3c585
Serialize tx without segwit
oscarguindzberg Sep 28, 2020
58afc00
Don't create an extra address at startup
oscarguindzberg Sep 28, 2020
e2f74f0
Don't create a wallet address when not needed
oscarguindzberg Sep 28, 2020
d1aeedd
Remove unused WalletService.findKeyFromPubKeyHash()
oscarguindzberg Sep 24, 2020
78a2a43
Remove unused import
oscarguindzberg Sep 14, 2020
01455d2
Enable reusing unused AVAILABLE entries
oscarguindzberg Oct 1, 2020
4a2c0ad
Make codacy happy
oscarguindzberg Oct 1, 2020
86ddd06
Validate AddressEntry.segwit
oscarguindzberg Oct 5, 2020
b9e404f
Make it clear segwit is not used for the trade protocol yet.
oscarguindzberg Oct 5, 2020
5524ba3
BtcWalletService.getFreshAddressEntry(): code clean up
oscarguindzberg Oct 5, 2020
d1aaf3e
Construct dummy outputs with LegacyAddress
oscarguindzberg Oct 5, 2020
3554e19
setWitness(): Code clean up
oscarguindzberg Oct 5, 2020
499d7b7
Use try-with-resources
oscarguindzberg Oct 5, 2020
1d82c01
Improve error handling for P2WPKH
oscarguindzberg Oct 5, 2020
694446c
Switch back to LegacyAddress for fee estimation
oscarguindzberg Oct 5, 2020
a747e83
Fix add segwit keychain for encrypted wallet
oscarguindzberg Oct 7, 2020
417daf5
Use bitcoinj 0.15.8 (commit a733034)
oscarguindzberg Oct 8, 2020
87da2ae
Do a backup of the wallet before segwit migration
oscarguindzberg Oct 8, 2020
261e0ec
Check migratedWalletToSegwit is true
oscarguindzberg Oct 8, 2020
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
2 changes: 2 additions & 0 deletions core/src/main/java/bisq/core/app/BisqSetup.java
Original file line number Diff line number Diff line change
Expand Up @@ -389,6 +389,8 @@ private void initWallet() {
if (requestWalletPasswordHandler != null) {
requestWalletPasswordHandler.accept(aesKey -> {
walletsManager.setAesKey(aesKey);
walletsSetup.getWalletConfig().maybeAddSegwitKeychain(walletsSetup.getWalletConfig().btcWallet(),
aesKey);
if (preferences.isResyncSpvRequested()) {
if (showFirstPopupIfResyncSPVRequestedHandler != null)
showFirstPopupIfResyncSPVRequestedHandler.run();
Expand Down
78 changes: 58 additions & 20 deletions core/src/main/java/bisq/core/btc/setup/WalletConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import com.google.common.util.concurrent.*;
import org.bitcoinj.core.listeners.*;
import org.bitcoinj.core.*;
import org.bitcoinj.crypto.KeyCrypter;
import org.bitcoinj.net.BlockingClientManager;
import org.bitcoinj.net.discovery.*;
import org.bitcoinj.script.Script;
Expand All @@ -35,6 +36,11 @@

import com.runjva.sourceforge.jsocks.protocol.Socks5Proxy;

import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;

import org.bouncycastle.crypto.params.KeyParameter;

import org.slf4j.*;

import javax.annotation.*;
Expand Down Expand Up @@ -103,6 +109,8 @@ public class WalletConfig extends AbstractIdleService {
@Getter
@Setter
private int minBroadcastConnections;
@Getter
private BooleanProperty migratedWalletToSegwit = new SimpleBooleanProperty(false);

/**
* Creates a new WalletConfig, with a newly created {@link Context}. Files will be stored in the given directory.
Expand Down Expand Up @@ -293,25 +301,34 @@ protected void startUp() throws Exception {
vPeerGroup.addWallet(vBsqWallet);
onSetupCompleted();

Futures.addCallback((ListenableFuture<?>) vPeerGroup.startAsync(), new FutureCallback<Object>() {
@Override
public void onSuccess(@Nullable Object result) {
//completeExtensionInitiations(vPeerGroup);
DownloadProgressTracker tracker = downloadListener == null ? new DownloadProgressTracker() : downloadListener;
vPeerGroup.startBlockChainDownload(tracker);
}

@Override
public void onFailure(Throwable t) {
throw new RuntimeException(t);
if (migratedWalletToSegwit.get()) {
startPeerGroup();
} else {
migratedWalletToSegwit.addListener((observable, oldValue, newValue) -> startPeerGroup());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should add a if(newValue) to make it more clear/safe. As we change only once from false to true it would not matter but feels more correct.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed 261e0ec

}

}
}, MoreExecutors.directExecutor());
} catch (BlockStoreException e) {
throw new IOException(e);
}
}

private void startPeerGroup() {
Futures.addCallback((ListenableFuture<?>) vPeerGroup.startAsync(), new FutureCallback<Object>() {
@Override
public void onSuccess(@Nullable Object result) {
//completeExtensionInitiations(vPeerGroup);
DownloadProgressTracker tracker = downloadListener == null ? new DownloadProgressTracker() : downloadListener;
vPeerGroup.startBlockChainDownload(tracker);
}

@Override
public void onFailure(Throwable t) {
throw new RuntimeException(t);

}
}, MoreExecutors.directExecutor());
}

private Wallet createOrLoadWallet(boolean shouldReplayWallet, File walletFile, boolean isBsqWallet) throws Exception {
Wallet wallet;

Expand Down Expand Up @@ -351,13 +368,8 @@ private Wallet loadWallet(boolean shouldReplayWallet, File walletFile, boolean i
wallet = serializer.readWallet(params, extArray, proto);
if (shouldReplayWallet)
wallet.reset();
if (!isBsqWallet && BisqKeyChainGroupStructure.BIP44_BTC_NON_SEGWIT_ACCOUNT_PATH.equals(wallet.getActiveKeyChain().getAccountPath())) {
// Btc wallet does not have a native segwit keychain, we should add one.
DeterministicSeed seed = wallet.getKeyChainSeed();
DeterministicKeyChain nativeSegwitKeyChain = DeterministicKeyChain.builder().seed(seed)
.outputScriptType(Script.ScriptType.P2WPKH)
.accountPath(new BisqKeyChainGroupStructure(isBsqWallet).accountPathFor(Script.ScriptType.P2WPKH)).build();
wallet.addAndActivateHDChain(nativeSegwitKeyChain);
if (!isBsqWallet) {
maybeAddSegwitKeychain(wallet, null);
}
}
return wallet;
Expand Down Expand Up @@ -491,4 +503,30 @@ public PeerGroup peerGroup() {
public File directory() {
return directory;
}

public void maybeAddSegwitKeychain(Wallet wallet, KeyParameter aesKey) {
if (BisqKeyChainGroupStructure.BIP44_BTC_NON_SEGWIT_ACCOUNT_PATH.equals(wallet.getActiveKeyChain().getAccountPath())) {
if (wallet.isEncrypted() && aesKey == null) {
// wait for the aesKey to be set and this method to be invoked again.
return;
}
// Btc 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.
KeyCrypter keyCrypter = wallet.getKeyCrypter();
seed = seed.decrypt(keyCrypter, DeterministicKeyChain.DEFAULT_PASSPHRASE_FOR_MNEMONIC, aesKey);
}
DeterministicKeyChain nativeSegwitKeyChain = DeterministicKeyChain.builder().seed(seed)
.outputScriptType(Script.ScriptType.P2WPKH)
.accountPath(new BisqKeyChainGroupStructure(false).accountPathFor(Script.ScriptType.P2WPKH)).build();
if (aesKey != null) {
// If wallet is encrypted, encrypt the new keychain.
KeyCrypter keyCrypter = wallet.getKeyCrypter();
nativeSegwitKeyChain = nativeSegwitKeyChain.toEncrypted(keyCrypter, aesKey);
}
wallet.addAndActivateHDChain(nativeSegwitKeyChain);
}
migratedWalletToSegwit.set(true);
}
}