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.

- iOS isn't officially supported in go-libtor dependency.
    - An iOS wrapper is needed in upstream go-libtor (ref. ipsn/go-libtor#3).
  • Loading branch information
nochiel committed Aug 12, 2021
1 parent 672d1da commit acdb895
Show file tree
Hide file tree
Showing 26 changed files with 459 additions and 389 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
12 changes: 9 additions & 3 deletions account/payments.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import (
"net/http"
"sort"
"strings"

"time"

breezservice "github.com/breez/breez/breez"
Expand Down Expand Up @@ -228,9 +227,17 @@ 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
if useTor, _ := a.breezDB.GetUseTor(); useTor {
/* @nochiel: If Tor is active, extend the timeout to avoid
frequent payment timeout failures observed in testing.
*/
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 Expand Up @@ -447,7 +454,6 @@ func (a *Service) sendPayment(paymentHash string, payReq *lnrpc.PayReq, sendRequ
}
a.log.Infof("sendPaymentForRequest finished successfully")
a.syncSentPayments()
// TODO(@nochiel) FINDOUT Should we notify client here? If we do, what breaks?
// a.notifyPaymentResult(true, sendRequest.PaymentRequest, paymentHash, "", "")
return "", nil
}
Expand Down
55 changes: 53 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,41 @@ 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
}

if useTor, _ := a.breezDB.GetUseTor(); useTor {
a.log.Info("app.Start: useTor.")
var err error
if a.tor, err = tor.StartTor(); err != nil {
a.breezDB.SetUseTor(false)
err = fmt.Errorf("app.Start: app unable to start Tor: %w", err)
a.log.Errorf("%v", err)
return err
} else {

/* The current backup provider has a pointer to a.tor
but if a.tor was nil, then setting a.BackupManager.Tor
will only affect newly created backup providers.
Reset the current provider's tor pointer here.
*/
provider := a.BackupManager.GetProvider()
provider.SetTor(a.tor)
a.BackupManager.SetProvider(provider)

a.BackupManager.Tor = a.tor

if a.lnDaemon.TorConfig, err = a.tor.GetTorConfig(); err != nil {
a.breezDB.SetUseTor(false)
err = fmt.Errorf("app.Start: unable to get Tor config for daemon : %w", err)
a.log.Errorf("%v", err)
return err
}

}
}

services := []Service{
a.lnDaemon,
a.ServicesClient,
Expand Down Expand Up @@ -85,6 +117,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 +433,18 @@ 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?")

b, err := a.breezDB.GetUseTor()
if err != nil {
a.log.Infof("IsTorActive: %v", err)
}
return b
}
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
10 changes: 9 additions & 1 deletion backup/drive.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ import (
"strings"
"time"

"github.com/breez/breez/tor"

"github.com/btcsuite/btclog"
"golang.org/x/oauth2"
drive "google.golang.org/api/drive/v3"
Expand All @@ -35,6 +37,7 @@ type driveServiceError struct {
func (d *driveServiceError) Error() string {
return d.err.Error()
}

func (d *driveServiceError) IsAuthError() bool {
if ferr, ok := d.err.(*googleapi.Error); ok {
return ferr.Code == 401 || ferr.Code == 403
Expand Down Expand Up @@ -196,7 +199,8 @@ func (p *GoogleDriveProvider) UploadBackupFiles(file string, nodeID string, encr
p.log.Infof("Uploading file %v size: %v", fileName, info.Size())
uploadedFile, err := p.driveService.Files.Create(&drive.File{
Name: fileName,
Parents: []string{newBackupFolder.Id}},
Parents: []string{newBackupFolder.Id},
},
).Media(file).Fields("md5Checksum").Do()
if err != nil {
p.log.Infof("uploadBackupFiles failed to upload file at folder:%v", newBackupFolder.Id)
Expand Down Expand Up @@ -313,6 +317,10 @@ func (p *GoogleDriveProvider) DownloadBackupFiles(nodeID, backupID string) ([]st
return downloaded, nil
}

func (p *GoogleDriveProvider) SetTor(tor *tor.Tor) {
return
}

// nodeFolder is responsible for fetching the node folder. If it doesn't exist it creates it.
func (p *GoogleDriveProvider) nodeFolder(nodeID string) (*drive.File, error) {
r, err := p.driveService.Files.List().Spaces("appDataFolder").
Expand Down
45 changes: 29 additions & 16 deletions backup/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,26 +8,37 @@ 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)
},
"remoteserver": func(authService AuthService, authData string, log btclog.Logger) (Provider, error) {
var providerData ProviderData
_ = json.Unmarshal([]byte(authData), &providerData)
return NewRemoteServerProvider(providerData, log)
},
}
)
var providersFactory = map[string]ProviderFactory{
"gdrive": func(providerFactoryInfo ProviderFactoryInfo) (Provider, error) {
return NewGoogleDriveProvider(providerFactoryInfo.authService, providerFactoryInfo.log)
},
"remoteserver": func(providerFactoryInfo ProviderFactoryInfo) (Provider, error) {
var providerData ProviderData
_ = json.Unmarshal([]byte(providerFactoryInfo.authData), &providerData)
return NewRemoteServerProvider(
providerData,
providerFactoryInfo.log,
providerFactoryInfo.tor,
)
},
}

// Manager holds the data needed for the backup to execute its work.
type Manager struct {
Expand All @@ -47,6 +58,8 @@ type Manager struct {
encryptionType string
mu sync.Mutex
wg sync.WaitGroup

Tor *tor.Tor
}

// NewManager creates a new Manager
Expand All @@ -61,7 +74,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 +104,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: 3 additions & 0 deletions backup/interface.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package backup

import "github.com/breez/breez/tor"

// SnapshotInfo is an existing backup information for a specific node id.
type SnapshotInfo struct {
NodeID string
Expand All @@ -23,6 +25,7 @@ type Provider interface {
UploadBackupFiles(file string, nodeID string, encryptionType string) (string, error)
AvailableSnapshots() ([]SnapshotInfo, error)
DownloadBackupFiles(nodeID, backupID string) ([]string, error)
SetTor(t *tor.Tor)
}

// ProviderError is the error that is used by the Provider to tell the BackupService
Expand Down
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
8 changes: 7 additions & 1 deletion backup/manager_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (

"github.com/breez/breez/config"
"github.com/breez/breez/data"
"github.com/breez/breez/tor"
"github.com/btcsuite/btclog"
)

Expand All @@ -30,6 +31,7 @@ type MockTester struct {
AvailableSnapshotsImpl func() ([]SnapshotInfo, error)
DownloadBackupFilesImpl func(nodeID, backupID string) ([]string, error)
MsgChannel chan data.NotificationEvent
tor *tor.Tor
}

func newDefaultMockTester() *MockTester {
Expand Down Expand Up @@ -63,13 +65,17 @@ func (m *MockTester) DownloadBackupFiles(nodeID, backupID string) ([]string, err
return m.DownloadBackupFilesImpl(nodeID, backupID)
}

func (m *MockTester) SetTor(tor *tor.Tor) {
m.tor = tor
}

func prepareBackupData() (paths []string, nodeID string, err error) {
return []string{"file1"}, "test-node-id", nil
}

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
Loading

0 comments on commit acdb895

Please sign in to comment.