mirror of
https://github.com/rclone/rclone.git
synced 2024-12-11 17:51:12 +01:00
e7bd392a69
This fixes an important bug with listing that affects users with more than 500 objects in a listing operation.
90 lines
2.0 KiB
Go
90 lines
2.0 KiB
Go
// Copyright (c) 2019 Storj Labs, Inc.
|
|
// See LICENSE for copying information.
|
|
|
|
package identity
|
|
|
|
import (
|
|
"context"
|
|
"crypto"
|
|
|
|
"storj.io/common/pkcrypto"
|
|
"storj.io/common/storj"
|
|
)
|
|
|
|
// GenerateKey generates a private key with a node id with difficulty at least
|
|
// minDifficulty. No parallelism is used.
|
|
func GenerateKey(ctx context.Context, minDifficulty uint16, version storj.IDVersion) (
|
|
k crypto.PrivateKey, id storj.NodeID, err error) {
|
|
defer mon.Task()(&ctx)(&err)
|
|
|
|
var d uint16
|
|
for {
|
|
err = ctx.Err()
|
|
if err != nil {
|
|
break
|
|
}
|
|
k, err = version.NewPrivateKey()
|
|
if err != nil {
|
|
break
|
|
}
|
|
|
|
var pubKey crypto.PublicKey
|
|
pubKey, err = pkcrypto.PublicKeyFromPrivate(k)
|
|
if err != nil {
|
|
break
|
|
}
|
|
|
|
id, err = NodeIDFromKey(pubKey, version)
|
|
if err != nil {
|
|
break
|
|
}
|
|
d, err = id.Difficulty()
|
|
if err != nil {
|
|
break
|
|
}
|
|
if d >= minDifficulty {
|
|
return k, id, nil
|
|
}
|
|
}
|
|
return k, id, storj.ErrNodeID.Wrap(err)
|
|
}
|
|
|
|
// GenerateCallback indicates that key generation is done when done is true.
|
|
// if err != nil key generation will stop with that error.
|
|
type GenerateCallback func(crypto.PrivateKey, storj.NodeID) (done bool, err error)
|
|
|
|
// GenerateKeys continues to generate keys until found returns done == false,
|
|
// or the ctx is canceled.
|
|
func GenerateKeys(ctx context.Context, minDifficulty uint16, concurrency int, version storj.IDVersion, found GenerateCallback) (err error) {
|
|
defer mon.Task()(&ctx)(&err)
|
|
ctx, cancel := context.WithCancel(ctx)
|
|
defer cancel()
|
|
errchan := make(chan error, concurrency)
|
|
|
|
for i := 0; i < concurrency; i++ {
|
|
go func() {
|
|
for {
|
|
k, id, err := GenerateKey(ctx, minDifficulty, version)
|
|
if err != nil {
|
|
errchan <- err
|
|
return
|
|
}
|
|
|
|
done, err := found(k, id)
|
|
if err != nil {
|
|
errchan <- err
|
|
return
|
|
}
|
|
if done {
|
|
errchan <- nil
|
|
return
|
|
}
|
|
}
|
|
}()
|
|
}
|
|
|
|
// we only care about the first error. the rest of the errors will be
|
|
// context cancellation errors
|
|
return <-errchan
|
|
}
|