Use backing database for aliases and/or access checks
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
parent
569d295120
commit
e1d0e27c29
|
@ -5,8 +5,8 @@ name: default
|
|||
|
||||
steps:
|
||||
- name: backend
|
||||
image: golang:1.18-rc-bullseye
|
||||
image: golang:1.17-bullseye
|
||||
commands:
|
||||
- GOAMD64=v2 go build -v -o fcmm .
|
||||
- go build -v -o fcmm .
|
||||
|
||||
...
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
FROM golang:1.18-rc-bullseye
|
||||
FROM golang:1.17-bullseye
|
||||
|
||||
COPY . /src
|
||||
|
||||
WORKDIR /src
|
||||
RUN GOAMD64=v2 go build -v -o fcmm . && mv fcmm /usr/bin && rm -rf /src
|
||||
RUN go build -v -o fcmm . && mv fcmm /usr/bin && rm -rf /src
|
||||
WORKDIR /
|
||||
|
||||
ENTRYPOINT ["/usr/bin/fcmm"]
|
|
@ -1,15 +1,13 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/rand"
|
||||
"crypto/tls"
|
||||
"encoding/binary"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"flag"
|
||||
"fmt"
|
||||
"git.gammaspectra.live/S.O.N.G/FinalCommander/content"
|
||||
"git.gammaspectra.live/S.O.N.G/FinalCommander/utilities"
|
||||
"git.gammaspectra.live/S.O.N.G/MakyuuIchaival"
|
||||
"git.gammaspectra.live/S.O.N.G/MakyuuIchaival/contentmessage"
|
||||
"git.gammaspectra.live/S.O.N.G/MakyuuIchaival/httputils"
|
||||
"git.gammaspectra.live/S.O.N.G/MakyuuIchaival/tlsutils"
|
||||
"github.com/cloudflare/circl/sign/ed25519"
|
||||
|
@ -18,65 +16,18 @@ import (
|
|||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
var privateKey ed25519.PrivateKey
|
||||
|
||||
var debugOutput = false
|
||||
var contentServers []*ContentServer
|
||||
var contentServers []*content.Server
|
||||
|
||||
type ContentServer struct {
|
||||
Index int
|
||||
Address string
|
||||
Weight uint
|
||||
LastCheckResult bool
|
||||
LastCheckMutex sync.RWMutex
|
||||
}
|
||||
var db *content.Database
|
||||
|
||||
func (s *ContentServer) getURL(args ...string) string {
|
||||
return fmt.Sprintf("https://%s/%s", s.Address, strings.Join(args, "/"))
|
||||
}
|
||||
|
||||
func (s *ContentServer) getCheckResult() bool {
|
||||
s.LastCheckMutex.RLock()
|
||||
defer s.LastCheckMutex.RUnlock()
|
||||
return s.LastCheckResult
|
||||
}
|
||||
|
||||
func (s *ContentServer) setCheckResult(result bool) {
|
||||
s.LastCheckMutex.Lock()
|
||||
defer s.LastCheckMutex.Unlock()
|
||||
s.LastCheckResult = result
|
||||
}
|
||||
|
||||
func (s *ContentServer) check() {
|
||||
customTransport := http.DefaultTransport.(*http.Transport).Clone()
|
||||
customTransport.TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
|
||||
client := &http.Client{
|
||||
Transport: customTransport,
|
||||
Timeout: 5 * time.Second,
|
||||
}
|
||||
response, err := client.Head(s.getURL())
|
||||
|
||||
if err != nil {
|
||||
s.setCheckResult(false)
|
||||
return
|
||||
}
|
||||
|
||||
defer response.Body.Close()
|
||||
|
||||
if response.StatusCode != http.StatusBadRequest {
|
||||
s.setCheckResult(false)
|
||||
return
|
||||
}
|
||||
s.setCheckResult(true)
|
||||
}
|
||||
|
||||
func selectNextContentServer(skip []int) *ContentServer {
|
||||
func selectNextContentServer(skip []int) *content.Server {
|
||||
inSkip := func(i int) bool {
|
||||
for _, c := range skip {
|
||||
if i == c {
|
||||
|
@ -88,7 +39,7 @@ func selectNextContentServer(skip []int) *ContentServer {
|
|||
|
||||
var choosingList []weightedrand.Choice
|
||||
for _, c := range contentServers {
|
||||
if !inSkip(c.Index) && c.getCheckResult() {
|
||||
if !inSkip(c.Index) && c.GetCheckResult() {
|
||||
choosingList = append(choosingList, weightedrand.NewChoice(c, c.Weight))
|
||||
}
|
||||
}
|
||||
|
@ -99,7 +50,7 @@ func selectNextContentServer(skip []int) *ContentServer {
|
|||
return nil
|
||||
}
|
||||
|
||||
return chooser.Pick().(*ContentServer)
|
||||
return chooser.Pick().(*content.Server)
|
||||
}
|
||||
|
||||
func setOtherHeaders(ctx *httputils.RequestContext) {
|
||||
|
@ -123,37 +74,6 @@ func setCORSHeaders(ctx *httputils.RequestContext) {
|
|||
ctx.SetResponseHeader("Cross-Origin-Opener-Policy", "unsafe-none")
|
||||
}
|
||||
|
||||
func encodeIntegerList(data []int) []byte {
|
||||
message := &bytes.Buffer{}
|
||||
buf := make([]byte, binary.MaxVarintLen64)
|
||||
|
||||
for _, i := range data {
|
||||
n := binary.PutVarint(buf, int64(i))
|
||||
_, _ = message.Write(buf[:n])
|
||||
}
|
||||
|
||||
return message.Bytes()
|
||||
}
|
||||
func decodeIntegerList(data []byte) []int {
|
||||
buf := bytes.NewBuffer(data)
|
||||
var result []int
|
||||
|
||||
for {
|
||||
if buf.Len() <= 0 {
|
||||
break
|
||||
}
|
||||
|
||||
i, err := binary.ReadVarint(buf)
|
||||
if err != nil {
|
||||
//TODO: maybe should error
|
||||
break
|
||||
}
|
||||
result = append(result, int(i))
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
func handle(ctx *httputils.RequestContext) {
|
||||
if len(ctx.GetRequestHeader("Host")) > 0 && ctx.GetRequestHeader("Host") == ctx.GetTLSServerName() { //Prevents rebinding / DNS stuff
|
||||
ctx.SetResponseCode(http.StatusNotFound)
|
||||
|
@ -180,39 +100,134 @@ func handle(ctx *httputils.RequestContext) {
|
|||
return
|
||||
}
|
||||
|
||||
var skip []int
|
||||
|
||||
if len(pathElements) > 3 {
|
||||
data, err := MakyuuIchaival.Bech32Encoding.DecodeString(pathElements[3])
|
||||
if err != nil {
|
||||
ctx.SetResponseCode(http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
skip = decodeIntegerList(data)
|
||||
}
|
||||
|
||||
var mh multihash.Multihash
|
||||
if hashType == "sha256" && len(hash) == 32 {
|
||||
mh, _ = multihash.Encode(hash, multihash.SHA2_256)
|
||||
} else if hashType == "md5" && len(hash) == 16 {
|
||||
mh, _ = multihash.Encode(hash, multihash.MD5)
|
||||
} else {
|
||||
ctx.SetResponseCode(http.StatusNotFound)
|
||||
ctx.SetResponseCode(http.StatusNotImplemented)
|
||||
return
|
||||
}
|
||||
key := content.NewHashIdentifierFromMultihash(mh)
|
||||
|
||||
var skip []int
|
||||
|
||||
entry := getContentEntry(key)
|
||||
|
||||
if len(pathElements) > 3 {
|
||||
|
||||
if pathElements[3] == "information" {
|
||||
ctx.SetResponseHeader("Content-Type", "application/json")
|
||||
if entry != nil {
|
||||
b, _ := json.Marshal(struct {
|
||||
Known bool `json:"known"`
|
||||
CID string `json:"cid"`
|
||||
AccessTime int64 `json:"accessTime"`
|
||||
CheckTime int64 `json:"checkTime"`
|
||||
InvalidCount int `json:"invalidCount"`
|
||||
}{
|
||||
Known: true,
|
||||
CID: entry.CID().String(),
|
||||
AccessTime: entry.AccessTime,
|
||||
CheckTime: entry.CheckTime,
|
||||
InvalidCount: len(entry.InvalidList),
|
||||
})
|
||||
|
||||
ctx.ServeBytes(b)
|
||||
} else {
|
||||
b, _ := json.Marshal(struct {
|
||||
Known bool `json:"known"`
|
||||
CID string `json:"cid"`
|
||||
}{
|
||||
Known: false,
|
||||
CID: key.CID().String(),
|
||||
})
|
||||
|
||||
ctx.ServeBytes(b)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
//TODO: update entries with these instant returns
|
||||
data, err := MakyuuIchaival.Bech32Encoding.DecodeString(pathElements[3])
|
||||
if err != nil {
|
||||
ctx.SetResponseCode(http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
skip = utilities.DecodeIntegerList(data)
|
||||
}
|
||||
|
||||
if entry != nil {
|
||||
for _, ci := range skip {
|
||||
if !entry.InInvalidList(ci) {
|
||||
skip = append(skip, ci)
|
||||
}
|
||||
}
|
||||
contentServer := selectNextContentServer(skip)
|
||||
if contentServer == nil {
|
||||
ctx.SetResponseCode(http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
|
||||
//TODO: signing cache
|
||||
message := contentmessage.NewContentMessageV1(mh, privateKey)
|
||||
ctx.DoRedirect(contentServer.GetContentURL(entry, privateKey, skip), http.StatusFound)
|
||||
} else {
|
||||
contentServer := selectNextContentServer(skip)
|
||||
if contentServer == nil {
|
||||
ctx.SetResponseCode(http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
|
||||
skip = append(skip, contentServer.Index)
|
||||
//TODO: only trigger this when we don't get a 404
|
||||
go func() {
|
||||
|
||||
ctx.DoRedirect(contentServer.getURL(MakyuuIchaival.Bech32Encoding.EncodeToString(message.Encode()), MakyuuIchaival.Bech32Encoding.EncodeToString(encodeIntegerList(skip))), http.StatusFound)
|
||||
//e.CheckTime = time.Now().UTC().Unix() + 3600*24*365 //force a check next year as necessary
|
||||
|
||||
var newInvalidList []int
|
||||
var e *content.Entry
|
||||
|
||||
for _, c := range contentServers {
|
||||
if !c.GetCheckResult() {
|
||||
continue
|
||||
}
|
||||
|
||||
result := c.CheckEntryKey(key, privateKey)
|
||||
if result != nil {
|
||||
if e == nil {
|
||||
e = &content.Entry{
|
||||
Key: *result,
|
||||
Version: 0,
|
||||
AccessTime: time.Now().UTC().Unix(),
|
||||
CheckTime: time.Now().UTC().Unix() + 3600*24*3, // Check sooner after addition, not all servers might have it yet
|
||||
}
|
||||
}
|
||||
} else {
|
||||
newInvalidList = append(newInvalidList, c.Index)
|
||||
}
|
||||
}
|
||||
|
||||
if e != nil {
|
||||
if !key.IsKey() { //Check for entry already existing
|
||||
entry := getContentEntry(&e.Key)
|
||||
|
||||
if entry != nil {
|
||||
e = entry
|
||||
}
|
||||
//Add alias mapping
|
||||
_ = db.SetAlias(&content.Alias{
|
||||
Key: *key,
|
||||
Identifier: e.Key,
|
||||
})
|
||||
}
|
||||
|
||||
e.AccessTime = time.Now().UTC().Unix()
|
||||
e.InvalidList = newInvalidList
|
||||
_ = db.SetEntry(e)
|
||||
}
|
||||
}()
|
||||
|
||||
ctx.DoRedirect(contentServer.GetHashURL(mh, privateKey, skip), http.StatusFound)
|
||||
}
|
||||
} else if ctx.IsOptions() {
|
||||
setOtherHeaders(ctx)
|
||||
setCORSHeaders(ctx)
|
||||
|
@ -222,9 +237,43 @@ func handle(ctx *httputils.RequestContext) {
|
|||
}
|
||||
}
|
||||
|
||||
func getContentEntry(key *content.HashIdentifier) *content.Entry {
|
||||
entry := db.GetEntry(*key)
|
||||
|
||||
if entry != nil {
|
||||
entry.UpdateAccessTime(db)
|
||||
|
||||
if entry.NeedsCheck() {
|
||||
go func() {
|
||||
b, _ := entry.Encode() //Encode/decode to copy object
|
||||
e := content.DecodeEntry(entry.Key, b)
|
||||
e.CheckTime = time.Now().UTC().Unix() + 3600*24*365 //force a check next year as necessary
|
||||
|
||||
var newInvalidList []int
|
||||
|
||||
for _, c := range contentServers {
|
||||
if !c.GetCheckResult() {
|
||||
if e.InInvalidList(c.Index) { //Keep old result if down
|
||||
newInvalidList = append(newInvalidList, c.Index)
|
||||
}
|
||||
continue
|
||||
}
|
||||
if c.CheckEntryKey(&e.Key, privateKey) == nil {
|
||||
newInvalidList = append(newInvalidList, c.Index)
|
||||
}
|
||||
}
|
||||
|
||||
e.InvalidList = newInvalidList
|
||||
_ = db.SetEntry(e)
|
||||
}()
|
||||
}
|
||||
}
|
||||
return entry
|
||||
}
|
||||
|
||||
func checkContentServers() {
|
||||
for _, c := range contentServers {
|
||||
c.check()
|
||||
c.Check()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -232,6 +281,7 @@ func main() {
|
|||
//TODO: OCSP
|
||||
certificatePath := flag.String("certificate", "", "Path to SSL certificate file.")
|
||||
keypairPath := flag.String("keypair", "", "Path to SSL key file.")
|
||||
databasePath := flag.String("dbpath", "database", "Path to key/value database.")
|
||||
|
||||
listenAddress := flag.String("listen", ":7777", "Address/port to lisent on.")
|
||||
|
||||
|
@ -245,44 +295,52 @@ func main() {
|
|||
|
||||
privateKeyEnv := os.Getenv("PRIVATE_KEY")
|
||||
|
||||
if privateKeyEnv == "" {
|
||||
log.Print("No PRIVATE_KEY environment variable specified, generating new identity")
|
||||
publicKey, privateKey, _ := ed25519.GenerateKey(rand.Reader)
|
||||
if privateKeyEnv != "" {
|
||||
log.Print("PRIVATE_KEY is deprecated. Use PRIVATE_SEED instead with seed")
|
||||
privateKey, _ := MakyuuIchaival.Bech32Encoding.DecodeString(privateKeyEnv)
|
||||
|
||||
log.Printf("Public Ed25519 key (share this): %s", MakyuuIchaival.Bech32Encoding.EncodeToString(publicKey))
|
||||
log.Printf("Private Ed25519 key (keep safe!): %s", MakyuuIchaival.Bech32Encoding.EncodeToString(privateKey))
|
||||
log.Printf("Private Ed25519 seed (keep safe!): %s", MakyuuIchaival.Bech32Encoding.EncodeToString(ed25519.PrivateKey(privateKey).Seed()))
|
||||
return
|
||||
}
|
||||
|
||||
privateKey, err = MakyuuIchaival.Bech32Encoding.DecodeString(privateKeyEnv)
|
||||
privateSeedEnv := os.Getenv("PRIVATE_SEED")
|
||||
|
||||
if privateSeedEnv == "" {
|
||||
log.Print("No PRIVATE_SEED environment variable specified, generating new identity")
|
||||
publicKey, privateKey, _ := ed25519.GenerateKey(rand.Reader)
|
||||
|
||||
log.Printf("Public Ed25519 key (share this): %s", MakyuuIchaival.Bech32Encoding.EncodeToString(publicKey))
|
||||
log.Printf("Private Ed25519 seed (keep safe!): %s", MakyuuIchaival.Bech32Encoding.EncodeToString(privateKey.Seed()))
|
||||
return
|
||||
}
|
||||
|
||||
privateSeed, err := MakyuuIchaival.Bech32Encoding.DecodeString(privateSeedEnv)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
publicKey := make([]byte, ed25519.PublicKeySize)
|
||||
copy(publicKey, privateKey[32:])
|
||||
log.Printf("Loaded Private Ed25519 key, Public %s", MakyuuIchaival.Bech32Encoding.EncodeToString(publicKey))
|
||||
|
||||
if len(privateKey) != ed25519.PrivateKeySize {
|
||||
if len(privateSeed) != ed25519.SeedSize {
|
||||
log.Fatal("Wrong Private key length")
|
||||
}
|
||||
|
||||
for i, s := range strings.Split(*weightedServerList, ",") {
|
||||
p := strings.Split(s, "/")
|
||||
if len(p) != 2 {
|
||||
log.Fatalf("Invalid weighted server %s", s)
|
||||
}
|
||||
privateKey = ed25519.NewKeyFromSeed(privateSeed)
|
||||
publicKey := make([]byte, ed25519.PublicKeySize)
|
||||
copy(publicKey, privateKey[ed25519.PublicKeySize:])
|
||||
log.Printf("Loaded Private Ed25519 key, Public %s", MakyuuIchaival.Bech32Encoding.EncodeToString(publicKey))
|
||||
|
||||
weight, err := strconv.ParseUint(p[1], 10, 32)
|
||||
db, err = content.OpenDatabase(*databasePath)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
defer db.Close()
|
||||
|
||||
contentServers = append(contentServers, &ContentServer{
|
||||
Index: i,
|
||||
Address: p[0],
|
||||
Weight: uint(weight),
|
||||
LastCheckResult: false,
|
||||
})
|
||||
for i, s := range strings.Split(*weightedServerList, ",") {
|
||||
cs, err := content.NewContentServerFromArgument(s, i)
|
||||
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
contentServers = append(contentServers, cs)
|
||||
}
|
||||
|
||||
checkContentServers()
|
||||
|
|
81
content/database.go
Normal file
81
content/database.go
Normal file
|
@ -0,0 +1,81 @@
|
|||
package content
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/dgraph-io/badger/v3"
|
||||
)
|
||||
|
||||
type Database struct {
|
||||
handle *badger.DB
|
||||
}
|
||||
|
||||
func OpenDatabase(path string) (*Database, error) {
|
||||
opts := badger.DefaultOptions(path)
|
||||
opts.IndexCacheSize = 256 << 20 //256 MiB, TODO check relative to keys
|
||||
db, err := badger.Open(opts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &Database{
|
||||
handle: db,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (db *Database) GetEntry(key HashIdentifier) *Entry {
|
||||
var entry *Entry
|
||||
err := db.handle.View(func(txn *badger.Txn) error {
|
||||
var err error
|
||||
entry, err = db.getChain(txn, key)
|
||||
return err
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
return entry
|
||||
}
|
||||
|
||||
func (db *Database) SetAlias(alias *Alias) error {
|
||||
return db.handle.Update(func(txn *badger.Txn) error {
|
||||
return txn.Set(alias.Key.Encode(), alias.Encode())
|
||||
})
|
||||
}
|
||||
|
||||
func (db *Database) SetEntry(entry *Entry) error {
|
||||
return db.handle.Update(func(txn *badger.Txn) error {
|
||||
b, err := entry.Encode()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return txn.Set(entry.Key.Encode(), b)
|
||||
})
|
||||
}
|
||||
|
||||
func (db *Database) getChain(txn *badger.Txn, key HashIdentifier) (*Entry, error) {
|
||||
item, err := txn.Get(key.Encode())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var entry *Entry
|
||||
err = item.Value(func(val []byte) error {
|
||||
if key.IsKey() {
|
||||
entry = DecodeEntry(key, val)
|
||||
return nil
|
||||
} else {
|
||||
alias := DecodeAlias(key, val)
|
||||
if alias == nil {
|
||||
return fmt.Errorf("could not decode alias %x", key.Encode())
|
||||
}
|
||||
entry, err = db.getChain(txn, alias.Identifier)
|
||||
return err
|
||||
}
|
||||
})
|
||||
|
||||
return entry, err
|
||||
}
|
||||
|
||||
func (db *Database) Close() error {
|
||||
return db.handle.Close()
|
||||
}
|
169
content/entry.go
Normal file
169
content/entry.go
Normal file
|
@ -0,0 +1,169 @@
|
|||
package content
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"git.gammaspectra.live/S.O.N.G/FinalCommander/utilities"
|
||||
"github.com/ipfs/go-cid"
|
||||
"github.com/multiformats/go-multihash"
|
||||
"time"
|
||||
)
|
||||
|
||||
// HashIdentifier Main identifier
|
||||
type HashIdentifier multihash.DecodedMultihash
|
||||
|
||||
func (i *HashIdentifier) IsKey() bool {
|
||||
return i.Code == multihash.SHA2_256
|
||||
}
|
||||
func (i *HashIdentifier) Encode() []byte {
|
||||
b, _ := multihash.Encode(i.Digest, i.Code)
|
||||
return b
|
||||
}
|
||||
func (i *HashIdentifier) CID() cid.Cid {
|
||||
return cid.NewCidV1(cid.Raw, i.Hash())
|
||||
}
|
||||
func (i *HashIdentifier) Hash() multihash.Multihash {
|
||||
return i.Encode()
|
||||
}
|
||||
func (i *HashIdentifier) Equals(o *HashIdentifier) bool {
|
||||
return i.Code == o.Code && bytes.Compare(i.Digest, o.Digest) == 0
|
||||
}
|
||||
|
||||
func NewHashIdentifierFromMultihash(mh multihash.Multihash) *HashIdentifier {
|
||||
d, err := multihash.Decode(mh)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
i := HashIdentifier(*d)
|
||||
return &i
|
||||
}
|
||||
|
||||
type Entry struct {
|
||||
Key HashIdentifier
|
||||
Version uint64
|
||||
// CheckTime indicates relative unix time entry was accessed
|
||||
AccessTime int64
|
||||
// CheckTime indicates next unix time a check shall be made
|
||||
CheckTime int64
|
||||
InvalidList []int
|
||||
}
|
||||
|
||||
type Alias struct {
|
||||
Key HashIdentifier
|
||||
Identifier HashIdentifier
|
||||
}
|
||||
|
||||
func (e *Alias) Encode() []byte {
|
||||
return e.Identifier.Encode()
|
||||
}
|
||||
|
||||
func DecodeAlias(key HashIdentifier, message []byte) *Alias {
|
||||
buffer := bytes.NewBuffer(message)
|
||||
read, mh, err := multihash.MHFromBytes(buffer.Bytes())
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
buffer.Next(read)
|
||||
|
||||
if buffer.Len() != 0 { //Unknown extra data
|
||||
return nil
|
||||
}
|
||||
|
||||
return &Alias{
|
||||
Key: key,
|
||||
Identifier: *NewHashIdentifierFromMultihash(mh),
|
||||
}
|
||||
}
|
||||
|
||||
func (e *Entry) Encode() ([]byte, error) {
|
||||
if !e.Valid() {
|
||||
return nil, fmt.Errorf("invalid Entry")
|
||||
}
|
||||
|
||||
message := &bytes.Buffer{}
|
||||
|
||||
buf := make([]byte, binary.MaxVarintLen64)
|
||||
|
||||
n := binary.PutUvarint(buf, e.Version)
|
||||
_, _ = message.Write(buf[:n])
|
||||
|
||||
if e.Version == 0 {
|
||||
n := binary.PutVarint(buf, e.AccessTime)
|
||||
_, _ = message.Write(buf[:n])
|
||||
n = binary.PutVarint(buf, e.CheckTime)
|
||||
_, _ = message.Write(buf[:n])
|
||||
message.Write(utilities.EncodeIntegerList(e.InvalidList))
|
||||
}
|
||||
|
||||
return message.Bytes(), nil
|
||||
}
|
||||
|
||||
func DecodeEntry(key HashIdentifier, message []byte) *Entry {
|
||||
entry := Entry{
|
||||
Key: key,
|
||||
}
|
||||
var err error
|
||||
buffer := bytes.NewBuffer(message)
|
||||
|
||||
entry.Version, err = binary.ReadUvarint(buffer)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
if entry.Version == 0 {
|
||||
entry.AccessTime, err = binary.ReadVarint(buffer)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
entry.CheckTime, err = binary.ReadVarint(buffer)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
entry.InvalidList = utilities.DecodeIntegerList(buffer.Bytes())
|
||||
|
||||
return &entry
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e *Entry) UpdateAccessTime(db *Database) {
|
||||
now := time.Now().UTC().Unix()
|
||||
|
||||
diff := e.AccessTime - now
|
||||
e.AccessTime = now
|
||||
|
||||
if diff < 0 {
|
||||
diff = -diff
|
||||
}
|
||||
|
||||
if diff > 3600*24 { //Update max every day
|
||||
_ = db.SetEntry(e)
|
||||
}
|
||||
}
|
||||
|
||||
func (e *Entry) InInvalidList(i int) bool {
|
||||
for _, v := range e.InvalidList {
|
||||
if i == v {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (e *Entry) NeedsCheck() bool {
|
||||
return e.CheckTime < time.Now().UTC().Unix()
|
||||
}
|
||||
|
||||
func (e *Entry) Valid() bool {
|
||||
return e.Key.IsKey() && e.AccessTime != 0 && e.CheckTime != 0
|
||||
}
|
||||
|
||||
func (e *Entry) Multihash() multihash.Multihash {
|
||||
return e.Key.Hash()
|
||||
}
|
||||
|
||||
func (e *Entry) CID() cid.Cid {
|
||||
return e.Key.CID()
|
||||
}
|
133
content/server.go
Normal file
133
content/server.go
Normal file
|
@ -0,0 +1,133 @@
|
|||
package content
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"git.gammaspectra.live/S.O.N.G/FinalCommander/utilities"
|
||||
"git.gammaspectra.live/S.O.N.G/MakyuuIchaival"
|
||||
"git.gammaspectra.live/S.O.N.G/MakyuuIchaival/contentmessage"
|
||||
"github.com/cloudflare/circl/sign/ed25519"
|
||||
"github.com/multiformats/go-multihash"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
type Server struct {
|
||||
Index int
|
||||
Address string
|
||||
Weight uint
|
||||
LastCheckResult bool
|
||||
LastCheckMutex sync.RWMutex
|
||||
}
|
||||
|
||||
func NewContentServerFromArgument(arg string, index int) (*Server, error) {
|
||||
//Format address:PORT/WEIGHT[/publicKey],
|
||||
p := strings.Split(arg, "/")
|
||||
if len(p) < 2 {
|
||||
return nil, fmt.Errorf("invalid weighted server %s", arg)
|
||||
}
|
||||
|
||||
weight, err := strconv.ParseUint(p[1], 10, 32)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cs := &Server{
|
||||
Index: index,
|
||||
Address: p[0],
|
||||
Weight: uint(weight),
|
||||
LastCheckResult: false,
|
||||
}
|
||||
|
||||
return cs, nil
|
||||
}
|
||||
|
||||
func (s *Server) GetContentURL(content *Entry, key ed25519.PrivateKey, skip []int) string {
|
||||
message := contentmessage.NewContentMessageV1(content.Multihash(), key)
|
||||
skip = append(skip, s.Index)
|
||||
return s.getURL(MakyuuIchaival.Bech32Encoding.EncodeToString(message.Encode()), MakyuuIchaival.Bech32Encoding.EncodeToString(utilities.EncodeIntegerList(skip)))
|
||||
}
|
||||
|
||||
func (s *Server) GetHashURL(mh multihash.Multihash, key ed25519.PrivateKey, skip []int) string {
|
||||
message := contentmessage.NewContentMessageV1(mh, key)
|
||||
skip = append(skip, s.Index)
|
||||
return s.getURL(MakyuuIchaival.Bech32Encoding.EncodeToString(message.Encode()), MakyuuIchaival.Bech32Encoding.EncodeToString(utilities.EncodeIntegerList(skip)))
|
||||
}
|
||||
|
||||
func (s *Server) getURL(args ...string) string {
|
||||
return fmt.Sprintf("https://%s/%s", s.Address, strings.Join(args, "/"))
|
||||
}
|
||||
|
||||
func (s *Server) GetCheckResult() bool {
|
||||
s.LastCheckMutex.RLock()
|
||||
defer s.LastCheckMutex.RUnlock()
|
||||
return s.LastCheckResult
|
||||
}
|
||||
|
||||
func (s *Server) setCheckResult(result bool) {
|
||||
s.LastCheckMutex.Lock()
|
||||
defer s.LastCheckMutex.Unlock()
|
||||
s.LastCheckResult = result
|
||||
}
|
||||
|
||||
func (s *Server) Check() {
|
||||
customTransport := http.DefaultTransport.(*http.Transport).Clone()
|
||||
customTransport.TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
|
||||
client := &http.Client{
|
||||
Transport: customTransport,
|
||||
Timeout: 5 * time.Second,
|
||||
}
|
||||
response, err := client.Head(s.getURL())
|
||||
|
||||
if err != nil {
|
||||
s.setCheckResult(false)
|
||||
return
|
||||
}
|
||||
|
||||
defer response.Body.Close()
|
||||
|
||||
if response.StatusCode != http.StatusBadRequest {
|
||||
s.setCheckResult(false)
|
||||
return
|
||||
}
|
||||
s.setCheckResult(true)
|
||||
}
|
||||
|
||||
func (s *Server) CheckEntryKey(key *HashIdentifier, privateKey ed25519.PrivateKey) *HashIdentifier {
|
||||
customTransport := http.DefaultTransport.(*http.Transport).Clone()
|
||||
customTransport.TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
|
||||
client := &http.Client{
|
||||
Transport: customTransport,
|
||||
Timeout: 5 * time.Second,
|
||||
}
|
||||
response, err := client.Head(s.GetHashURL(key.Hash(), privateKey, []int{}))
|
||||
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
defer response.Body.Close()
|
||||
|
||||
if response.StatusCode != http.StatusOK {
|
||||
return nil
|
||||
}
|
||||
|
||||
v := strings.Split(response.Header.Get("Digest"), "=")
|
||||
if len(v) >= 2 && v[0] == "sha-256" {
|
||||
sha, err := base64.StdEncoding.DecodeString(strings.Join(v[1:], "="))
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
mh, err := multihash.Encode(sha, multihash.SHA2_256)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
return NewHashIdentifierFromMultihash(mh)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
18
go.mod
18
go.mod
|
@ -3,19 +3,30 @@ module git.gammaspectra.live/S.O.N.G/FinalCommander
|
|||
go 1.17
|
||||
|
||||
require (
|
||||
git.gammaspectra.live/S.O.N.G/MakyuuIchaival v0.0.0-20220118183219-7bfcd667a183
|
||||
git.gammaspectra.live/S.O.N.G/MakyuuIchaival v0.0.0-20220119201433-39050c16549d
|
||||
github.com/cloudflare/circl v1.1.0
|
||||
github.com/dgraph-io/badger/v3 v3.2103.2
|
||||
github.com/ipfs/go-cid v0.1.0
|
||||
github.com/mroth/weightedrand v0.4.1
|
||||
github.com/multiformats/go-multihash v0.1.0
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/andybalholm/brotli v1.0.4 // indirect
|
||||
github.com/cespare/xxhash v1.1.0 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.1.2 // indirect
|
||||
github.com/cheekybits/genny v1.0.0 // indirect
|
||||
github.com/dgraph-io/ristretto v0.1.0 // indirect
|
||||
github.com/dgrr/http2 v0.3.3 // indirect
|
||||
github.com/dustin/go-humanize v1.0.0 // indirect
|
||||
github.com/fsnotify/fsnotify v1.5.1 // indirect
|
||||
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 // indirect
|
||||
github.com/ipfs/go-cid v0.1.0 // indirect
|
||||
github.com/gogo/protobuf v1.3.2 // indirect
|
||||
github.com/golang/glog v1.0.0 // indirect
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
||||
github.com/golang/protobuf v1.5.2 // indirect
|
||||
github.com/golang/snappy v0.0.4 // indirect
|
||||
github.com/google/flatbuffers v2.0.5+incompatible // indirect
|
||||
github.com/klauspost/compress v1.14.1 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.0.9 // indirect
|
||||
github.com/lucas-clemente/quic-go v0.25.0 // indirect
|
||||
|
@ -32,10 +43,12 @@ require (
|
|||
github.com/multiformats/go-varint v0.0.6 // indirect
|
||||
github.com/nxadm/tail v1.4.8 // indirect
|
||||
github.com/onsi/ginkgo v1.16.5 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/spaolacci/murmur3 v1.1.0 // indirect
|
||||
github.com/valyala/bytebufferpool v1.0.0 // indirect
|
||||
github.com/valyala/fasthttp v1.32.0 // indirect
|
||||
github.com/valyala/fastrand v1.1.0 // indirect
|
||||
go.opencensus.io v0.23.0 // indirect
|
||||
golang.org/x/crypto v0.0.0-20220112180741-5e0467b6c7ce // indirect
|
||||
golang.org/x/mod v0.5.1 // indirect
|
||||
golang.org/x/net v0.0.0-20220114011407-0dd24b26b47d // indirect
|
||||
|
@ -43,6 +56,7 @@ require (
|
|||
golang.org/x/text v0.3.7 // indirect
|
||||
golang.org/x/tools v0.1.8 // indirect
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
|
||||
google.golang.org/protobuf v1.27.1 // indirect
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
|
||||
lukechampine.com/blake3 v1.1.7 // indirect
|
||||
)
|
||||
|
|
103
go.sum
103
go.sum
|
@ -9,27 +9,54 @@ dmitri.shuralyov.com/state v0.0.0-20180228185332-28bcc343414c/go.mod h1:0PRwlb0D
|
|||
git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg=
|
||||
git.gammaspectra.live/S.O.N.G/MakyuuIchaival v0.0.0-20220118183219-7bfcd667a183 h1:wF+oxs88n5p2O5ixy/vJN4KYefYOgwVmx+8a0xB7TPc=
|
||||
git.gammaspectra.live/S.O.N.G/MakyuuIchaival v0.0.0-20220118183219-7bfcd667a183/go.mod h1:z6KcP5RPhMxDJaVU48sBhiYRCJ6ZJBbx1iIhkUrrhfY=
|
||||
git.gammaspectra.live/S.O.N.G/MakyuuIchaival v0.0.0-20220119201433-39050c16549d h1:hgO2pPDG/cSFmCh7uzvbqvWHzSdPfO7sk2GuY929JyA=
|
||||
git.gammaspectra.live/S.O.N.G/MakyuuIchaival v0.0.0-20220119201433-39050c16549d/go.mod h1:z6KcP5RPhMxDJaVU48sBhiYRCJ6ZJBbx1iIhkUrrhfY=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE=
|
||||
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
|
||||
github.com/andybalholm/brotli v1.0.2/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y=
|
||||
github.com/andybalholm/brotli v1.0.4 h1:V7DdXeJtZscaqfNuAdSRuRFzuiKlHSC/Zh3zl9qY3JY=
|
||||
github.com/andybalholm/brotli v1.0.4/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
|
||||
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c=
|
||||
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
|
||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
||||
github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBTaaSFSlLx/70C2HPIMNZpVV8+vt/A+FMnYP11g=
|
||||
github.com/buger/jsonparser v0.0.0-20181115193947-bf1c66bbce23/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s=
|
||||
github.com/bwesterb/go-ristretto v1.2.0/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0=
|
||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
|
||||
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
|
||||
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE=
|
||||
github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/cheekybits/genny v1.0.0 h1:uGGa4nei+j20rOSeDeP5Of12XVm7TGUd4dJA9RDitfE=
|
||||
github.com/cheekybits/genny v1.0.0/go.mod h1:+tQajlRqAUrPI7DOSpB0XAqZYtQakVtB7wXkRAgjxjQ=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/cloudflare/circl v1.1.0 h1:bZgT/A+cikZnKIwn7xL2OBj012Bmvho/o6RpRvv3GKY=
|
||||
github.com/cloudflare/circl v1.1.0/go.mod h1:prBCrKB9DV4poKZY1l9zBXg2QJY7mvgRvtMxxK7fi4I=
|
||||
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
||||
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
|
||||
github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk=
|
||||
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
||||
github.com/coreos/go-systemd v0.0.0-20181012123002-c6f51f82210d/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
||||
github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/dgraph-io/badger/v3 v3.2103.2 h1:dpyM5eCJAtQCBcMCZcT4UBZchuTJgCywerHHgmxfxM8=
|
||||
github.com/dgraph-io/badger/v3 v3.2103.2/go.mod h1:RHo4/GmYcKKh5Lxu63wLEMHJ70Pac2JqZRYGhlyAo2M=
|
||||
github.com/dgraph-io/ristretto v0.1.0 h1:Jv3CGQHp9OjuMBSne1485aDpUkTKEcUqF+jm/LuerPI=
|
||||
github.com/dgraph-io/ristretto v0.1.0/go.mod h1:fux0lOrBhrVCJd3lcTHsIJhq1T2rokOu6v9Vcb3Q9ug=
|
||||
github.com/dgrr/http2 v0.3.3 h1:F5BlR5CCMCSoEuD6oQcUk9fercKwg01LoArgUP1ycJ4=
|
||||
github.com/dgrr/http2 v0.3.3/go.mod h1:OrmrVjQp6qa+E3VEiNB+fqpfl+8D9k1ZbBfK4RKU8D0=
|
||||
github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2 h1:tdlZCpZ/P9DhczCTSixgIKmwPv6+wP5DGjqLYw5SUiA=
|
||||
github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw=
|
||||
github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo=
|
||||
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
||||
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
|
||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||
github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
|
||||
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
|
||||
github.com/francoispqt/gojay v1.2.13/go.mod h1:ehT5mTG4ua4581f1++1WLG0vPdaA9HaiDsoyrBGkyDY=
|
||||
|
@ -43,7 +70,15 @@ github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm
|
|||
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 h1:p104kn46Q8WdvHunIJ9dAyjPVtrBPhSr3KT2yUst43I=
|
||||
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
|
||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
||||
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
github.com/golang/glog v1.0.0 h1:nfP3RFugxnNRyKgeWd4oI1nYvXpxrx8ck8ZrcizshdQ=
|
||||
github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4=
|
||||
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E=
|
||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
|
@ -52,39 +87,56 @@ github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc=
|
|||
github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
|
||||
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
|
||||
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
|
||||
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
|
||||
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
|
||||
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
|
||||
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
|
||||
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||
github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
|
||||
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||
github.com/google/flatbuffers v1.12.1/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8=
|
||||
github.com/google/flatbuffers v2.0.5+incompatible h1:ANsW0idDAXIY+mNHzIHxWRfabV2x5LUEEIIWcwsYgB8=
|
||||
github.com/google/flatbuffers v2.0.5+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8=
|
||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
|
||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ=
|
||||
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
|
||||
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
||||
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
|
||||
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/googleapis/gax-go v2.0.0+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY=
|
||||
github.com/googleapis/gax-go/v2 v2.0.3/go.mod h1:LLvjysVCY1JZeum8Z6l8qUty8fiNwE08qbEPm1M08qg=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.5.0/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw=
|
||||
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
|
||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
||||
github.com/ipfs/go-cid v0.1.0 h1:YN33LQulcRHjfom/i25yoOZR4Telp1Hr/2RU3d0PnC0=
|
||||
github.com/ipfs/go-cid v0.1.0/go.mod h1:rH5/Xv83Rfy8Rw6xG+id3DYAMUVmem1MowoKwdXmN2o=
|
||||
github.com/jellevandenhooff/dkim v0.0.0-20150330215556-f50fe3d243e1/go.mod h1:E0B/fFc00Y+Rasa88328GlI/XbtyysCtTHZS8h7IrBU=
|
||||
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
||||
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
|
||||
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/klauspost/compress v1.12.2/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg=
|
||||
github.com/klauspost/compress v1.12.3/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg=
|
||||
github.com/klauspost/compress v1.13.4/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg=
|
||||
github.com/klauspost/compress v1.14.1 h1:hLQYb23E8/fO+1u53d02A97a8UnsddcvYzq4ERRU4ds=
|
||||
github.com/klauspost/compress v1.14.1/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
|
||||
|
@ -98,6 +150,7 @@ github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
|||
github.com/lucas-clemente/quic-go v0.25.0 h1:K+X9Gvd7JXsOHtU0N2icZ2Nw3rx82uBej3mP4CLgibc=
|
||||
github.com/lucas-clemente/quic-go v0.25.0/go.mod h1:YtzP8bxRVCBlO77yRanE264+fY/T2U9ZlW1AaHOsMOg=
|
||||
github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI=
|
||||
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||
github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||
github.com/marten-seemann/qpack v0.2.1 h1:jvTsT/HpCn2UZJdP+UUB53FfUUgeOyG5K1ns0OJOGVs=
|
||||
github.com/marten-seemann/qpack v0.2.1/go.mod h1:F7Gl5L1jIgN1D11ucXefiuJS9UMVP2opoCp2jDKb7wc=
|
||||
|
@ -117,6 +170,8 @@ github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1 h1:lYpkrQH5ajf0
|
|||
github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1/go.mod h1:pD8RvIylQ358TN4wwqatJ8rNavkEINozVn9DtGI3dfQ=
|
||||
github.com/minio/sha256-simd v1.0.0 h1:v1ta+49hkWZyvaKwrQB8elexRqm6Y0aMLjCNsrYxo6g=
|
||||
github.com/minio/sha256-simd v1.0.0/go.mod h1:OuYzVNI5vcoYIAmbIvHPl3N3jUzVedXbKy5RFepssQM=
|
||||
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
github.com/mr-tron/base58 v1.1.0/go.mod h1:xcD2VGqlgYjBdcBLw+TuYLr8afG+Hj8g2eTVqeSzSU8=
|
||||
|
@ -153,11 +208,15 @@ github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1y
|
|||
github.com/onsi/gomega v1.13.0 h1:7lLHu94wT9Ij0o6EWWclhu0aOh32VxhkwEJvzuWPeak=
|
||||
github.com/onsi/gomega v1.13.0/go.mod h1:lRk9szgn8TxENtWd0Tp4c3wjlRfMTMH27I+3Je41yGY=
|
||||
github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8=
|
||||
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/prometheus/client_golang v0.8.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
|
||||
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
|
||||
github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
|
||||
|
@ -186,15 +245,25 @@ github.com/shurcooL/users v0.0.0-20180125191416-49c67e49c537/go.mod h1:QJTqeLYED
|
|||
github.com/shurcooL/webdavfs v0.0.0-20170829043945-18c3829fa133/go.mod h1:hKmq5kWdCj2z2KEozexVbfEZIWiTjhE0+UjmZgPqehw=
|
||||
github.com/sourcegraph/annotate v0.0.0-20160123013949-f4cad6c6324d/go.mod h1:UdhH50NIW0fCiwBSr0co2m7BnFLdv4fQTgdqdJTHFeE=
|
||||
github.com/sourcegraph/syntaxhighlight v0.0.0-20170531221838-bd320f5d308e/go.mod h1:HuIsMU8RRBOtsCgI77wP899iHVBQpCmg4ErYMZB+2IA=
|
||||
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
||||
github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI=
|
||||
github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
||||
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
|
||||
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
|
||||
github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU=
|
||||
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
|
||||
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||
github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/summerwind/h2spec v2.2.1+incompatible/go.mod h1:eP7IHGVDEe9cbCxRNtmGfII77lBvLgJLNfJjTaKa9sI=
|
||||
github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA=
|
||||
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
|
||||
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
|
||||
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
|
||||
github.com/valyala/fasthttp v1.28.0/go.mod h1:cmWIqlu99AO/RKcp1HWaViTqc57FswJOfYYdPJBl8BA=
|
||||
|
@ -206,13 +275,19 @@ github.com/valyala/fastrand v1.1.0/go.mod h1:HWqCzkrkg6QXT8V2EXWvXCoow7vLwOFN002
|
|||
github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc=
|
||||
github.com/viant/assertly v0.4.8/go.mod h1:aGifi++jvCrUaklKEKT0BU95igDNaqkvz+49uaYMPRU=
|
||||
github.com/viant/toolbox v0.24.0/go.mod h1:OxMCG57V0PXuIP2HNQrtJf2CjqdmbrOx5EkMILuUhzM=
|
||||
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
|
||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||
github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||
go.opencensus.io v0.18.0/go.mod h1:vKdFvxhtzZ9onBp9VKHK8z/sRpBMnKAsufL7wlDrCOA=
|
||||
go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk=
|
||||
go.opencensus.io v0.23.0 h1:gqCw0LfLxScz8irSi8exQc7fyQ0fKQU/qnC/X8+V/1M=
|
||||
go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E=
|
||||
go4.org v0.0.0-20180809161055-417644f6feb5/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE=
|
||||
golang.org/x/build v0.0.0-20190111050920-041ab4dc3f9d/go.mod h1:OWs+y06UdEOHN4y+MfF/py+xQ/tYqIWW03b70/CG9Rw=
|
||||
golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
|
@ -228,6 +303,8 @@ golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL
|
|||
golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.5.1 h1:OJxoQ/rynoF0dcCdI7cLPktw/hR2cueqYfjm43oqK38=
|
||||
|
@ -243,9 +320,11 @@ golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn
|
|||
golang.org/x/net v0.0.0-20190313220215-9f648a60d977/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
||||
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
|
||||
|
@ -264,14 +343,17 @@ golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJ
|
|||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181029174526-d69651ed3497/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190316082340-a2f829d7f35f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
|
@ -283,6 +365,7 @@ golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210309074719-68d13333faf2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
|
@ -310,9 +393,13 @@ golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGm
|
|||
golang.org/x/tools v0.0.0-20181030000716-a0a13e073c7b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
||||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
golang.org/x/tools v0.1.8 h1:P1HhGGuLW4aAclzjtmJdf0mJOjVUZUzOTqkAkWL+l6w=
|
||||
golang.org/x/tools v0.1.8/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU=
|
||||
|
@ -333,21 +420,34 @@ google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoA
|
|||
google.golang.org/genproto v0.0.0-20181029155118-b69ba1387ce2/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/genproto v0.0.0-20181202183823-bd91e49a0898/go.mod h1:7Ep/1NZk928CDR8SjdVbjWNpdIf6nzjE3BTgJDr2Atg=
|
||||
google.golang.org/genproto v0.0.0-20190306203927-b5d61aea6440/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||
google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
||||
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
|
||||
google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
|
||||
google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio=
|
||||
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
|
||||
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
||||
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
|
||||
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||
google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
|
||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
|
||||
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
|
||||
google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
|
||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||
google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk=
|
||||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
google.golang.org/protobuf v1.27.1 h1:SnqbnDw1V7RiZcXPx5MEeqPv2s79L9i7BJUlG/+RurQ=
|
||||
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
|
||||
|
@ -364,6 +464,7 @@ grpc.go4.org v0.0.0-20170609214715-11d0a25b4919/go.mod h1:77eQGdRu53HpSqPFJFmuJd
|
|||
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
lukechampine.com/blake3 v1.1.6/go.mod h1:tkKEOtDkNtklkXtLNEOGNq5tcV90tJiA1vAA12R78LA=
|
||||
lukechampine.com/blake3 v1.1.7 h1:GgRMhmdsuK8+ii6UZFDL8Nb+VyMwadAgcJyfYHxG6n0=
|
||||
lukechampine.com/blake3 v1.1.7/go.mod h1:tkKEOtDkNtklkXtLNEOGNq5tcV90tJiA1vAA12R78LA=
|
||||
|
|
37
utilities/utilities.go
Normal file
37
utilities/utilities.go
Normal file
|
@ -0,0 +1,37 @@
|
|||
package utilities
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
)
|
||||
|
||||
func EncodeIntegerList(data []int) []byte {
|
||||
message := &bytes.Buffer{}
|
||||
buf := make([]byte, binary.MaxVarintLen64)
|
||||
|
||||
for _, i := range data {
|
||||
n := binary.PutVarint(buf, int64(i))
|
||||
_, _ = message.Write(buf[:n])
|
||||
}
|
||||
|
||||
return message.Bytes()
|
||||
}
|
||||
func DecodeIntegerList(data []byte) []int {
|
||||
buf := bytes.NewBuffer(data)
|
||||
var result []int
|
||||
|
||||
for {
|
||||
if buf.Len() <= 0 {
|
||||
break
|
||||
}
|
||||
|
||||
i, err := binary.ReadVarint(buf)
|
||||
if err != nil {
|
||||
//TODO: maybe should error
|
||||
break
|
||||
}
|
||||
result = append(result, int(i))
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
Loading…
Reference in a new issue