Skip to content

Commit

Permalink
Tor:
Browse files Browse the repository at this point in the history
- LND can use Tor.
- WebDav remote server backup/restore can use Tor.
- Add breez/tor package.

- It's not possible to run concurrent instances of Tor (ref. ipsn/go-libtor#22).
- Use one global instance of Tor.
  • Loading branch information
nochiel committed Aug 7, 2021
1 parent 9ab0c14 commit 69c41fc
Show file tree
Hide file tree
Showing 24 changed files with 389 additions and 373 deletions.
2 changes: 1 addition & 1 deletion account/connect.go
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,7 @@ func (a *Service) openChannel(l lsp, force bool) error {
a.log.Info("openChannel started...")
_, err, _ := createChannelGroup.Do("createChannel", func() (interface{}, error) {
err := a.connectAndOpenChannel(l, force)
a.log.Info("openChannel finished, error = %v", err)
a.log.Infof("openChannel finished, error = %v", err)
return nil, err
})
return err
Expand Down
2 changes: 1 addition & 1 deletion account/lnurl.go
Original file line number Diff line number Diff line change
Expand Up @@ -476,7 +476,7 @@ func (a *Service) DecryptLNUrlPayMessage(paymentHash string, preimage []byte) (s
return "", fmt.Errorf("Could not save deciphered message: %s", err)
}

a.log.Info("DecryptLNUrlPayMessage: message = %q", info.SuccessAction.Message)
a.log.Infof("DecryptLNUrlPayMessage: message = %q", info.SuccessAction.Message)
return info.SuccessAction.Message, nil
}

Expand Down
5 changes: 4 additions & 1 deletion account/payments.go
Original file line number Diff line number Diff line change
Expand Up @@ -228,9 +228,12 @@ func (a *Service) sendPaymentForRequest(paymentRequest string, amountSatoshi int
maxParts = 1
}
// At this stage we are ready to send asynchronously the payment through the daemon.
var timeoutSeconds int32 = 60
// TODO(nochiel) Check if Tor is active. If Tor is active, extend the timeout to avoid frequent failures.
timeoutSeconds *= 2
return a.sendPayment(decodedReq.PaymentHash, decodedReq, &routerrpc.SendPaymentRequest{
PaymentRequest: paymentRequest,
TimeoutSeconds: 60,
TimeoutSeconds: timeoutSeconds,
FeeLimitSat: math.MaxInt64,
MaxParts: maxParts,
Amt: amountSatoshi,
Expand Down
39 changes: 37 additions & 2 deletions app.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,15 @@ import (
"github.com/breez/breez/db"
"github.com/breez/breez/doubleratchet"
"github.com/breez/breez/lnnode"
"github.com/breez/breez/tor"
"github.com/btcsuite/btcwallet/walletdb"
"github.com/lightninglabs/neutrino/filterdb"
"github.com/lightningnetwork/lnd/channeldb"
"github.com/lightningnetwork/lnd/lnrpc"
"github.com/lightningnetwork/lnd/lnrpc/breezbackuprpc"
)

//Service is the interface to be implemeted by all breez services
// Service is the interface to be implemeted by all breez services
type Service interface {
Start() error
Stop() error
Expand All @@ -40,10 +41,28 @@ func (a *App) Start() error {

a.log.Info("app.start before bootstrap")
if err := chainservice.Bootstrap(a.cfg.WorkingDir); err != nil {
a.log.Info("app.start bootstrap error %v", err)
a.log.Infof("app.start bootstrap error %v", err)
return err
}

{
// a.breezDB.SetUseTor(true) // FIXME(nochiel) nocheckin

useTor, _ := a.breezDB.GetUseTor()
a.lnDaemon.UseTor = useTor
a.BackupManager.UseTor = useTor

if useTor {
var err error
if a.tor, err = tor.StartTor(); err != nil {
a.log.Errorf("daemon.go: Start: %v", err)
}

a.BackupManager.Tor = a.tor
a.lnDaemon.TorConfig, _ = a.tor.GetTorConfig()
}
}

services := []Service{
a.lnDaemon,
a.ServicesClient,
Expand Down Expand Up @@ -85,6 +104,10 @@ func (a *App) Stop() error {
doubleratchet.Stop()
a.releaseBreezDB()

if a.tor != nil {
a.tor.Close()
}

a.wg.Wait()
a.log.Infof("BreezApp shutdown successfully")
return nil
Expand Down Expand Up @@ -397,3 +420,15 @@ func (a *App) CheckLSPClosedChannelMismatch(
}
return &data.CheckLSPClosedChannelMismatchResponse{Mismatch: mismatch}, nil
}

func (a *App) EnableOrDisableTor(enable bool) error {
a.log.Infof("EnableOrDisableTor: setting enabled = %v", enable)
return a.breezDB.SetUseTor(enable)
}

func (a *App) IsTorActive() bool {
a.log.Info("IsTorActive?")

return (a.tor != nil)

}
4 changes: 4 additions & 0 deletions app_init.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import (
breezlog "github.com/breez/breez/log"
"github.com/breez/breez/services"
"github.com/breez/breez/swapfunds"
"github.com/breez/breez/tor"
"github.com/btcsuite/btclog"
"github.com/lightningnetwork/lnd/lnrpc"
"github.com/lightningnetwork/lnd/lnrpc/breezbackuprpc"
Expand Down Expand Up @@ -54,6 +55,8 @@ type App struct {
notificationsChan chan data.NotificationEvent

lspChanStateSyncer *lspChanStateSync

tor *tor.Tor
}

// AppServices defined the interface needed in Breez library in order to functional
Expand Down Expand Up @@ -132,6 +135,7 @@ func NewApp(workingDir string, applicationServices AppServices, startBeforeSync
if err != nil {
return nil, err
}

app.BackupManager, err = backup.NewManager(
applicationServices.BackupProviderName(),
&AuthService{appServices: applicationServices},
Expand Down
30 changes: 21 additions & 9 deletions backup/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,23 +8,32 @@ import (

"github.com/breez/breez/config"
"github.com/breez/breez/data"
"github.com/breez/breez/tor"

"github.com/btcsuite/btclog"
)

type ProviderFactoryInfo struct {
authService AuthService
authData string
log btclog.Logger
tor *tor.Tor
}

// ProviderFactory is a factory for create a specific provider.
// This is the function needed to be implemented for a new provider
// to be registered and used.
type ProviderFactory func(authService AuthService, authData string, log btclog.Logger) (Provider, error)
type ProviderFactory func(providerFactoryInfo ProviderFactoryInfo) (Provider, error)

var (
providersFactory = map[string]ProviderFactory{
"gdrive": func(authService AuthService, authData string, log btclog.Logger) (Provider, error) {
return NewGoogleDriveProvider(authService, log)
"gdrive": func(providerFactoryInfo ProviderFactoryInfo) (Provider, error) {
return NewGoogleDriveProvider(providerFactoryInfo.authService, providerFactoryInfo.log)
},
"remoteserver": func(authService AuthService, authData string, log btclog.Logger) (Provider, error) {
"remoteserver": func(providerFactoryInfo ProviderFactoryInfo) (Provider, error) {
var providerData ProviderData
_ = json.Unmarshal([]byte(authData), &providerData)
return NewRemoteServerProvider(providerData, log)
_ = json.Unmarshal([]byte(providerFactoryInfo.authData), &providerData)
return NewRemoteServerProvider(providerData, providerFactoryInfo.log, providerFactoryInfo.tor)
},
}
)
Expand All @@ -47,6 +56,9 @@ type Manager struct {
encryptionType string
mu sync.Mutex
wg sync.WaitGroup

Tor *tor.Tor
UseTor bool
}

// NewManager creates a new Manager
Expand All @@ -61,7 +73,7 @@ func NewManager(
var provider Provider
var err error
if providerName != "" {
provider, err = createBackupProvider(providerName, authService, "", log)
provider, err = createBackupProvider(providerName, ProviderFactoryInfo{authService, "", log, nil})
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -91,10 +103,10 @@ func RegisterProvider(providerName string, factory ProviderFactory) {
providersFactory[providerName] = factory
}

func createBackupProvider(providerName string, authService AuthService, authData string, log btclog.Logger) (Provider, error) {
func createBackupProvider(providerName string, providerFactoryInfo ProviderFactoryInfo) (Provider, error) {
factory, ok := providersFactory[providerName]
if !ok {
return nil, fmt.Errorf("provider not found for %v", providerName)
}
return factory(authService, authData, log)
return factory(providerFactoryInfo)
}
3 changes: 2 additions & 1 deletion backup/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,7 @@ func (b *Manager) Start() error {
return nil
}
b.wg.Add(1)

go func() {
defer b.wg.Done()

Expand Down Expand Up @@ -453,7 +454,7 @@ func (b *Manager) getBackupIdentifier() (string, error) {

func (b *Manager) SetBackupProvider(providerName, authData string) error {
b.log.Infof("setting backup provider %v, authData: %v", providerName, authData)
provider, err := createBackupProvider(providerName, b.authService, authData, b.log)
provider, err := createBackupProvider(providerName, ProviderFactoryInfo{b.authService, authData, b.log, b.Tor})
if err != nil {
return err
}
Expand Down
2 changes: 1 addition & 1 deletion backup/manager_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ func prepareBackupData() (paths []string, nodeID string, err error) {

func createTestManager(mp *MockTester) (manager *Manager, err error) {
backupDelay = time.Duration(0)
RegisterProvider("mock", func(authServie AuthService, logger btclog.Logger) (Provider, error) { return mp, nil })
RegisterProvider("mock", func(providerFactoryInfo ProviderFactoryInfo) (Provider, error) { return mp, nil })

ntfnChan := make(chan data.NotificationEvent, 100)
dir := os.TempDir()
Expand Down
14 changes: 13 additions & 1 deletion backup/webdav.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,16 @@ import (
"net/url"
"path/filepath"
"strings"

"github.com/breez/breez/tor"
)

// A client represents a client connection to a {own|next}cloud
type WebdavClient struct {
Url *url.URL
Username string
Password string
Tor *tor.Tor
}

type WebdavRequestError struct {
Expand Down Expand Up @@ -167,7 +170,16 @@ func (c *WebdavClient) ListDir(path string) (*ListFileResponse, error) {
func (c *WebdavClient) sendWebDavRequest(request string, path string, data []byte, headers map[string]string) ([]byte, error) {
fmt.Printf("webdav request %v: %v\n", request, path)

client := &http.Client{}
var client *http.Client
var err error
if c.Tor!= nil {
client, err = c.Tor.NewHttpClient()
if err != nil {
return nil, fmt.Errorf("sendWebDavRequest: unable to create tor http client: %w", err)
}
} else {
client = &http.Client{}
}
//joined := strings.Join([]string{c.Url.String(), relativeURL}, "/")
joined := joinPath(c.Url.String(), path)
req, err := http.NewRequest(request, joined, bytes.NewReader(data))
Expand Down
7 changes: 6 additions & 1 deletion backup/webdav_provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import (
"strings"
"time"

"github.com/breez/breez/tor"

"github.com/btcsuite/btclog"
)

Expand All @@ -21,6 +23,7 @@ const (
type RemoteServerProvider struct {
authData ProviderData
log btclog.Logger
tor *tor.Tor
}

type ProviderData struct {
Expand Down Expand Up @@ -51,15 +54,17 @@ func (d *webdavProviderError) IsAuthError() bool {
return false
}

func NewRemoteServerProvider(authData ProviderData, log btclog.Logger) (*RemoteServerProvider, error) {
func NewRemoteServerProvider(authData ProviderData, log btclog.Logger, tor *tor.Tor) (*RemoteServerProvider, error) {
return &RemoteServerProvider{
authData: authData,
log: log,
tor: tor,
}, nil
}

func (n *RemoteServerProvider) getClient() (string, *WebdavClient, error) {
c, err := Dial(n.authData.Url, n.authData.User, n.authData.Password)
c.Tor = n.tor
return n.authData.BreezDir, c, err
}

Expand Down
8 changes: 8 additions & 0 deletions bindings/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -948,6 +948,14 @@ func PublishTransaction(tx []byte) error {
return getBreezApp().AccountService.PublishTransaction(tx)
}

func EnableOrDisableTor(enable bool) (err error) {
return getBreezApp().EnableOrDisableTor(enable)
}

func IsTorActive() bool {
return getBreezApp().IsTorActive()
}

func deliverNotifications(notificationsChan chan data.NotificationEvent, appServices AppServices) {
for {
notification := <-notificationsChan
Expand Down
3 changes: 1 addition & 2 deletions bindings/native_backup_provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import (
"strings"

"github.com/breez/breez/backup"
"github.com/btcsuite/btclog"
)

// NativeBackupProvider is interface that serves as backup provider and is intended to be
Expand Down Expand Up @@ -74,7 +73,7 @@ func (b *NativeBackupProviderBridge) DownloadBackupFiles(nodeID, backupID string

// RegisterNativeBackupProvider registered a native backup provider
func RegisterNativeBackupProvider(name string, provider NativeBackupProvider) {
backup.RegisterProvider(name, func(authService backup.AuthService, authData string, log btclog.Logger) (backup.Provider, error) {
backup.RegisterProvider(name, func(providerFactoryInfo backup.ProviderFactoryInfo) (backup.Provider, error) {
return &NativeBackupProviderBridge{nativeProvider: provider}, nil
})
}
4 changes: 4 additions & 0 deletions config/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@ type Config struct {

//Job Options
JobCfg JobConfig `group:"Job Options"`

// Tor options
// TODO(nochiel) Store this with user settings, not global config.
UseTor bool `long:"usetor"`
}

// GetConfig returns the config object
Expand Down
Loading

0 comments on commit 69c41fc

Please sign in to comment.