This repository has been archived by the owner on Mar 28, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 284
/
core.go
183 lines (155 loc) · 5.14 KB
/
core.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
package core
import (
"bytes"
"errors"
routing "gx/ipfs/QmNdaQ8itUU9jEZUwTsG4gHMaPmRfi6FEe89QjQAFbep3M/go-libp2p-routing"
libp2p "gx/ipfs/QmP1DfoUjiWH2ZBo1PBH6FupdBucbDepx3HpWmEY6JMUpY/go-libp2p-crypto"
peer "gx/ipfs/QmdS9KpbDyPrieswibZhkod1oXqRwZJrUPzxCofAMWpFGq/go-libp2p-peer"
gonet "net"
"net/http"
"net/url"
"path"
"time"
"github.com/OpenBazaar/openbazaar-go/api/notifications"
"github.com/OpenBazaar/openbazaar-go/bitcoin"
"github.com/OpenBazaar/openbazaar-go/ipfs"
"github.com/OpenBazaar/openbazaar-go/namesys"
"github.com/OpenBazaar/openbazaar-go/net"
rep "github.com/OpenBazaar/openbazaar-go/net/repointer"
ret "github.com/OpenBazaar/openbazaar-go/net/retriever"
"github.com/OpenBazaar/openbazaar-go/repo"
sto "github.com/OpenBazaar/openbazaar-go/storage"
"github.com/OpenBazaar/wallet-interface"
"github.com/ipfs/go-ipfs/commands"
"github.com/ipfs/go-ipfs/core"
"github.com/op/go-logging"
"golang.org/x/net/context"
"golang.org/x/net/proxy"
"sync"
)
var (
VERSION = "0.9.2"
USERAGENT = "/openbazaar-go:" + VERSION + "/"
)
var log = logging.MustGetLogger("core")
var Node *OpenBazaarNode
var inflightPublishRequests int
type OpenBazaarNode struct {
// Context for issuing IPFS commands
Context commands.Context
// IPFS node object
IpfsNode *core.IpfsNode
/* The roothash of the node directory inside the openbazaar repo.
This directory hash is published on IPNS at our peer ID making
the directory publicly viewable on the network. */
RootHash string
// The path to the openbazaar repo in the file system
RepoPath string
// The OpenBazaar network service for direct communication between peers
Service net.NetworkService
// Database for storing node specific data
Datastore repo.Datastore
// Websocket channel used for pushing data to the UI
Broadcast chan interface{}
// Bitcoin wallet implementation
Wallet wallet.Wallet
// Storage for our outgoing messages
MessageStorage sto.OfflineMessagingStorage
// A service that periodically checks the dht for outstanding messages
MessageRetriever *ret.MessageRetriever
// A service that periodically republishes active pointers
PointerRepublisher *rep.PointerRepublisher
// Used to resolve domains to OpenBazaar IDs
NameSystem *namesys.NameSystem
// A service that periodically fetches and caches the bitcoin exchange rates
ExchangeRates bitcoin.ExchangeRates
// An optional gateway URL where we can crosspost data to ensure persistence
CrosspostGateways []*url.URL
// The user-agent for this node
UserAgent string
// A dialer for Tor if available
TorDialer proxy.Dialer
// Manage blocked peers
BanManager *net.BanManager
}
// Unpin the current node repo, re-add it, then publish to IPNS
var seedLock sync.Mutex
func (n *OpenBazaarNode) SeedNode() error {
seedLock.Lock()
ipfs.UnPinDir(n.Context, n.RootHash)
var aerr error
var rootHash string
// There's an IPFS bug on Windows that might be related to the Windows indexer that could cause this to fail
// If we fail the first time, let's retry a couple times before giving up.
for i := 0; i < 3; i++ {
rootHash, aerr = ipfs.AddDirectory(n.Context, path.Join(n.RepoPath, "root"))
if aerr == nil {
break
}
time.Sleep(time.Millisecond * 500)
}
if aerr != nil {
seedLock.Unlock()
return aerr
}
seedLock.Unlock()
for _, g := range n.CrosspostGateways {
go func(u *url.URL) {
req, err := http.NewRequest("PUT", u.String()+path.Join("ipfs", rootHash), new(bytes.Buffer))
if err != nil {
return
}
dial := gonet.Dial
if n.TorDialer != nil {
dial = n.TorDialer.Dial
}
tbTransport := &http.Transport{Dial: dial}
client := &http.Client{Transport: tbTransport, Timeout: time.Minute}
client.Do(req)
}(g)
}
go n.publish(rootHash)
return nil
}
func (n *OpenBazaarNode) publish(hash string) {
if inflightPublishRequests == 0 {
n.Broadcast <- notifications.StatusNotification{"publishing"}
}
var err error
inflightPublishRequests++
_, err = ipfs.Publish(n.Context, hash)
inflightPublishRequests--
if inflightPublishRequests == 0 {
if err != nil {
log.Error(err)
n.Broadcast <- notifications.StatusNotification{"error publishing"}
} else {
n.Broadcast <- notifications.StatusNotification{"publish complete"}
}
}
}
/* This is a placeholder until the libsignal is operational.
For now we will just encrypt outgoing offline messages with the long lived identity key.
Optionally you may provide a public key, to avoid doing an IPFS lookup */
func (n *OpenBazaarNode) EncryptMessage(peerID peer.ID, peerKey *libp2p.PubKey, message []byte) (ct []byte, rerr error) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
if peerKey == nil {
pubKey, err := routing.GetPublicKey(n.IpfsNode.Routing, ctx, []byte(peerID))
if err != nil {
log.Errorf("Failed to find public key for %s", peerID.Pretty())
return nil, err
}
peerKey = &pubKey
}
if peerID.MatchesPublicKey(*peerKey) {
ciphertext, err := net.Encrypt(*peerKey, message)
if err != nil {
return nil, err
}
return ciphertext, nil
} else {
log.Errorf("peer public key and id do not match for peer: %s", peerID.Pretty())
return nil, errors.New("peer public key and id do not match")
}
}