forked from OpenBazaar/openbazaar-go
/
publish.go
139 lines (115 loc) · 3.48 KB
/
publish.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
package ipfs
import (
"errors"
"context"
"fmt"
"github.com/ipfs/go-ipfs/core"
"github.com/ipfs/go-ipfs/namesys"
pb "github.com/ipfs/go-ipfs/namesys/pb"
path "github.com/ipfs/go-ipfs/path"
"github.com/op/go-logging"
"gx/ipfs/QmTiWLZ6Fo5j4KcTVutZJ5KWRRJrbxzmxA4td8NfEdrPh7/go-libp2p-routing"
dshelp "gx/ipfs/QmTmqJGRQfuH8eKWD1FjThwPRipt1QhqJQNZ8MpzmfAAxo/go-ipfs-ds-help"
dhtpb "gx/ipfs/QmUpttFinNDmNPgFwKN8sZK6BUtBmA68Y4KdSBDXa8t9sJ/go-libp2p-record/pb"
ds "gx/ipfs/QmXRKBQA4wXP7xWbFiZsR1GP4HV6wMDQ1aWFxZZ4uBcPX9/go-datastore"
proto "gx/ipfs/QmZ4Qi3GaRbjcx28Sme5eMH7RQjGkt8wHxt2a65oLaeFEV/gogo-protobuf/proto"
mh "gx/ipfs/QmZyZDi491cCNTLfAhwcaDii2Kg4pwKRkhqQzURGDvY6ua/go-multihash"
ci "gx/ipfs/QmaPbCnUMBohSGo3KnxEa2bHqyJVVeEEcwtqJAYxerieBo/go-libp2p-crypto"
"time"
)
var log = logging.MustGetLogger("ipfs")
var pubErr = errors.New(`Name publish failed`)
// Publish a signed IPNS record to our Peer ID
func Publish(n *core.IpfsNode, hash string) error {
err := n.Namesys.Publish(context.Background(), n.PrivateKey, path.FromString("/ipfs/"+hash))
if err == nil {
log.Infof("Published %s to IPNS", hash)
return nil
} else {
return pubErr
}
}
// Publish another IPFS record at /ipns/<peerID>:<altRoot>
func PublishAltRoot(nd *core.IpfsNode, altRoot string, value path.Path, eol time.Time) error {
hash, err := mh.FromB58String(nd.Identity.Pretty())
if err != nil {
return err
}
ipnskey := "/ipns/" + string(hash) + ":" + altRoot
// get previous records sequence number
seqnum, err := getPreviousSeqNo(context.Background(), nd, ipnskey)
if err != nil {
return err
}
// increment it
seqnum++
return PutRecordToRouting(context.Background(), ipnskey, nd.PrivateKey, value, seqnum, eol, nd.Routing)
}
func getPreviousSeqNo(ctx context.Context, nd *core.IpfsNode, ipnskey string) (uint64, error) {
prevrec, err := nd.Repo.Datastore().Get(dshelp.NewKeyFromBinary([]byte(ipnskey)))
if err != nil && err != ds.ErrNotFound {
return 0, err
}
var val []byte
if err == nil {
prbytes, ok := prevrec.([]byte)
if !ok {
return 0, fmt.Errorf("unexpected type returned from datastore: %#v", prevrec)
}
dhtrec := new(dhtpb.Record)
err := proto.Unmarshal(prbytes, dhtrec)
if err != nil {
return 0, err
}
val = dhtrec.GetValue()
} else {
// try and check the dht for a record
ctx, cancel := context.WithTimeout(ctx, time.Second*30)
defer cancel()
rv, err := nd.Routing.GetValue(ctx, ipnskey)
if err != nil {
// no such record found, start at zero!
return 0, nil
}
val = rv
}
e := new(pb.IpnsEntry)
err = proto.Unmarshal(val, e)
if err != nil {
return 0, err
}
return e.GetSequence(), nil
}
func PutRecordToRouting(ctx context.Context, ipnskey string, k ci.PrivKey, value path.Path, seqnum uint64, eol time.Time, r routing.ValueStore) error {
ctx, cancel := context.WithCancel(ctx)
defer cancel()
entry, err := namesys.CreateRoutingEntryData(k, value, seqnum, eol)
if err != nil {
return err
}
ttl, ok := checkCtxTTL(ctx)
if ok {
entry.Ttl = proto.Uint64(uint64(ttl.Nanoseconds()))
}
errs := make(chan error, 1)
go func() {
errs <- namesys.PublishEntry(ctx, r, ipnskey, entry)
}()
return waitOnErrChan(ctx, errs)
}
func waitOnErrChan(ctx context.Context, errs chan error) error {
select {
case err := <-errs:
return err
case <-ctx.Done():
return ctx.Err()
}
}
func checkCtxTTL(ctx context.Context) (time.Duration, bool) {
v := ctx.Value("ipns-publish-ttl")
if v == nil {
return 0, false
}
d, ok := v.(time.Duration)
return d, ok
}