Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
69 commits
Select commit Hold shift + click to select a range
8586ae9
Add sql for blobber meta table
May 17, 2021
8ef3690
Add api for marketplace public keys
May 17, 2021
e30411f
Refactor and add bash scripts for stop
May 17, 2021
9ff0170
Update table name
May 17, 2021
dae9b42
Add keypair to database
May 17, 2021
fa10267
Use db reference for api response
May 17, 2021
61f18e2
Add api test
May 18, 2021
c3cbd1d
Fix bug and add test for insert
May 18, 2021
9053c88
Updates
May 18, 2021
5b7f7ed
Hide private keys from api
May 18, 2021
f51bc71
Add mnemonic to table
May 19, 2021
0ea4fb0
Fix permission
May 19, 2021
de960e7
Fix blobber commit ref
May 21, 2021
8d567ac
Add test for invalid signature
May 21, 2021
356f6e7
Fix verifysignature by removing encryption.hash
May 24, 2021
176e4cd
Remove unused import
May 24, 2021
8c5caf4
Add dev files
May 24, 2021
1992935
Updates
May 24, 2021
234cf81
Add test for same key for all blobbers
May 24, 2021
b7eb155
Updates
May 24, 2021
50b452e
Add 0box config for getting share info
May 27, 2021
a69635f
Reencrypt using regen key at blobber
May 27, 2021
4e56f66
Read mnemonic from table
May 27, 2021
ca6993d
Fixes from testing
May 28, 2021
577cb92
Add detailed error capture and logging
May 30, 2021
399dcf6
Blobber updates
May 30, 2021
41f4fe6
Fix marshall
May 31, 2021
ba24919
Add chuked transfer of reencrypted data
May 31, 2021
4b43806
Update download chunking
May 31, 2021
16fbbeb
Add api to insert auth ticket
Jun 1, 2021
a98de97
Add tests
Jun 2, 2021
8bf7acc
Update error message on unauthorized download
Jun 3, 2021
dd629f4
Update blobber handler
Jun 3, 2021
a6a5069
Use filepath hash
Jun 3, 2021
4396bb8
Cleanup
Jun 4, 2021
2852417
Remove dead code
Jun 4, 2021
fdf02f2
Remove dead code
Jun 4, 2021
93d035e
Add test for upload
Jun 4, 2021
009b45c
Add proxy encryption download UML
Jun 4, 2021
d0d853d
Update uml
Jun 7, 2021
d59f6ea
Remove pre at blobber
Jun 8, 2021
7432dfa
Add remove share handler
Jun 15, 2021
5bb2e85
Fix blobber get hash data
Jun 15, 2021
d0002c5
Add revoke api test
Jun 15, 2021
641e64b
Fix db handler
Jun 16, 2021
2bbfcb4
Add test for download file
Jun 17, 2021
62b0162
Add mock file store
Jun 17, 2021
acaadef
Add test for object_operation_handler download
Jun 19, 2021
4f30571
Add test for reencrypt
Jun 19, 2021
45d26a5
Enable folder meta
Jun 30, 2021
b970bf2
Modify get share logic on download to check for parent folder share
Jun 30, 2021
f561fe8
Updates to logic
Jul 1, 2021
b8294b2
Add revoke flag, add indexes to reference objects
Jul 3, 2021
78e5d45
Fix logic for update
Jul 3, 2021
af331c1
Updates to zero value update
Jul 3, 2021
73ddb9c
Add uml diagram for share and share revoke
Jul 5, 2021
22db299
Merge
Jul 6, 2021
0acfdc7
Replace gosdk version
Jul 6, 2021
fbc9fd7
Update sql version
Jul 7, 2021
4518c89
Force authticket check when provided
Jul 7, 2021
73d1867
Merge pull request #241 from 0chain/merge-to-master
Is2PidGuy Jul 7, 2021
03969da
Merge branch 'master' into buy-sell-marketplace
Jul 7, 2021
09a1e09
Fix dummy db connection snippet
Jul 7, 2021
d546f66
fix lint issues
Sriep Jul 17, 2021
0ecaaca
fix tests, wrap hidden error
Sriep Jul 17, 2021
958dd13
Merge remote-tracking branch 'origin/master' into buy-sell-marketplace
Sriep Jul 17, 2021
b707163
merge issues
Sriep Jul 17, 2021
e1ac618
merge issues
Sriep Jul 17, 2021
c15c513
merge issues
Sriep Jul 17, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,13 @@ docker network create --driver=bridge --subnet=198.18.0.0/15 --gateway=198.18.0.

```

To link to local gosdk so that the changes are reflected on the blobber build please use the below command

```

$ ./docker.local/bin/build.blobber.dev.sh

```
For Apple M1 chip builds:

```
Expand Down
8 changes: 4 additions & 4 deletions code/go/0chain.net/blobbercore/datastore/store.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ import (
"fmt"
"time"

"github.com/0chain/blobber/code/go/0chain.net/blobbercore/config"
"github.com/0chain/blobber/code/go/0chain.net/blobbercore/errors"
"github.com/0chain/blobber/code/go/0chain.net/core/common"

"github.com/0chain/blobber/code/go/0chain.net/blobbercore/config"
"gorm.io/driver/postgres"
"gorm.io/gorm"

Expand Down Expand Up @@ -39,12 +39,12 @@ func (store *Store) Open() error {
config.Configuration.DBUserName, config.Configuration.DBName,
config.Configuration.DBPassword)), &gorm.Config{})
if err != nil {
return errors.DBOpenError
return common.NewErrorf("db_open_error", "Error opening the DB connection: %v", err)
}

sqldb, err := db.DB()
if err != nil {
return errors.DBOpenError
return common.NewErrorf("db_open_error", "Error opening the DB connection: %v", err)
}

sqldb.SetMaxIdleConns(100)
Expand Down
10 changes: 0 additions & 10 deletions code/go/0chain.net/blobbercore/errors/errors.go

This file was deleted.

117 changes: 67 additions & 50 deletions code/go/0chain.net/blobbercore/filestore/fs_store.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,66 @@ type MinioConfiguration struct {

var MinioConfig MinioConfiguration

type IFileBlockGetter interface {
GetFileBlock(fsStore *FileFSStore, allocationID string, fileData *FileInputData, blockNum int64, numBlocks int64) ([]byte, error)
}

type FileBlockGetter struct {
}

func (FileBlockGetter) GetFileBlock(fs *FileFSStore, allocationID string, fileData *FileInputData, blockNum int64, numBlocks int64) ([]byte, error) {
allocation, err := fs.SetupAllocation(allocationID, true)
if err != nil {
return nil, common.NewError("invalid_allocation", "Invalid allocation. "+err.Error())
}
dirPath, destFile := GetFilePathFromHash(fileData.Hash)
fileObjectPath := filepath.Join(allocation.ObjectsPath, dirPath)
fileObjectPath = filepath.Join(fileObjectPath, destFile)

file, err := os.Open(fileObjectPath)
if err != nil {
if os.IsNotExist(err) && fileData.OnCloud {
err = fs.DownloadFromCloud(fileData.Hash, fileObjectPath)
if err != nil {
return nil, common.NewError("minio_download_failed", "Unable to download from minio with err "+err.Error())
}
file, err = os.Open(fileObjectPath)
if err != nil {
return nil, err
}
} else {
return nil, err
}
}
defer file.Close()
fileinfo, err := file.Stat()
if err != nil {
return nil, err
}

filesize := int(fileinfo.Size())
maxBlockNum := int64(filesize / CHUNK_SIZE)
// check for any left over bytes. Add one more go routine if required.
if remainder := filesize % CHUNK_SIZE; remainder != 0 {
maxBlockNum++
}

if blockNum > maxBlockNum || blockNum < 1 {
return nil, common.NewError("invalid_block_number", "Invalid block number")
}
buffer := make([]byte, CHUNK_SIZE*numBlocks)
n, err := file.ReadAt(buffer, ((blockNum - 1) * CHUNK_SIZE))
if err != nil && err != io.EOF {
return nil, err
}

return buffer[:n], nil
}

type FileFSStore struct {
RootDirectory string
Minio *minio.Client
RootDirectory string
Minio *minio.Client
fileBlockGetter IFileBlockGetter
}

type StoreAllocation struct {
Expand All @@ -61,9 +118,14 @@ func SetupFSStore(rootDir string) (FileStore, error) {
if err := createDirs(rootDir); err != nil {
return nil, err
}
return SetupFSStoreI(rootDir, FileBlockGetter{})
}

func SetupFSStoreI(rootDir string, fileBlockGetter IFileBlockGetter) (FileStore, error) {
fsStore = &FileFSStore{
RootDirectory: rootDir,
Minio: intializeMinio(),
RootDirectory: rootDir,
Minio: intializeMinio(),
fileBlockGetter: fileBlockGetter,
}
return fsStore, nil
}
Expand Down Expand Up @@ -280,52 +342,7 @@ func (fs *FileFSStore) GetFileBlockForChallenge(allocationID string, fileData *F
}

func (fs *FileFSStore) GetFileBlock(allocationID string, fileData *FileInputData, blockNum int64, numBlocks int64) ([]byte, error) {
allocation, err := fs.SetupAllocation(allocationID, true)
if err != nil {
return nil, common.NewError("invalid_allocation", "Invalid allocation. "+err.Error())
}
dirPath, destFile := GetFilePathFromHash(fileData.Hash)
fileObjectPath := filepath.Join(allocation.ObjectsPath, dirPath)
fileObjectPath = filepath.Join(fileObjectPath, destFile)

file, err := os.Open(fileObjectPath)
if err != nil {
if os.IsNotExist(err) && fileData.OnCloud {
err = fs.DownloadFromCloud(fileData.Hash, fileObjectPath)
if err != nil {
return nil, common.NewError("minio_download_failed", "Unable to download from minio with err "+err.Error())
}
file, err = os.Open(fileObjectPath)
if err != nil {
return nil, err
}
} else {
return nil, err
}
}
defer file.Close()
fileinfo, err := file.Stat()
if err != nil {
return nil, err
}

filesize := int(fileinfo.Size())
maxBlockNum := int64(filesize / CHUNK_SIZE)
// check for any left over bytes. Add one more go routine if required.
if remainder := filesize % CHUNK_SIZE; remainder != 0 {
maxBlockNum++
}

if blockNum > maxBlockNum || blockNum < 1 {
return nil, common.NewError("invalid_block_number", "Invalid block number")
}
buffer := make([]byte, CHUNK_SIZE*numBlocks)
n, err := file.ReadAt(buffer, ((blockNum - 1) * CHUNK_SIZE))
if err != nil && err != io.EOF {
return nil, err
}

return buffer[:n], nil
return fs.fileBlockGetter.GetFileBlock(fs, allocationID, fileData, blockNum, numBlocks)
}

func (fs *FileFSStore) DeleteTempFile(allocationID string, fileData *FileInputData, connectionID string) error {
Expand Down
145 changes: 145 additions & 0 deletions code/go/0chain.net/blobbercore/handler/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,18 @@ package handler

import (
"context"
"encoding/json"
"errors"
"net/http"
"os"
"runtime/pprof"
"time"

"github.com/0chain/blobber/code/go/0chain.net/blobbercore/readmarker"
"github.com/0chain/blobber/code/go/0chain.net/blobbercore/reference"
"github.com/0chain/gosdk/zboxcore/fileref"
"gorm.io/gorm"

"go.uber.org/zap"

"github.com/0chain/blobber/code/go/0chain.net/blobbercore/config"
Expand Down Expand Up @@ -59,6 +66,9 @@ func SetupHandlers(r *mux.Router) {
r.HandleFunc("/_statsJSON", common.UserRateLimit(common.ToJSONResponse(stats.StatsJSONHandler)))
r.HandleFunc("/_cleanupdisk", common.UserRateLimit(common.ToJSONResponse(WithReadOnlyConnection(CleanupDiskHandler))))
r.HandleFunc("/getstats", common.UserRateLimit(common.ToJSONResponse(stats.GetStatsHandler)))

//marketplace related
r.HandleFunc("/v1/marketplace/shareinfo/{allocation}", common.UserRateLimit(common.ToJSONResponse(WithConnection(MarketPlaceShareInfoHandler))))
}

func WithReadOnlyConnection(handler common.JSONResponderF) common.JSONResponderF {
Expand Down Expand Up @@ -329,3 +339,138 @@ func CleanupDiskHandler(ctx context.Context, r *http.Request) (interface{}, erro
err := CleanupDiskFiles(ctx)
return "cleanup", err
}

func RevokeShare(ctx context.Context, r *http.Request) (interface{}, error) {
ctx = setupHandlerContext(ctx, r)

allocationID := ctx.Value(constants.ALLOCATION_CONTEXT_KEY).(string)
allocationObj, err := storageHandler.verifyAllocation(ctx, allocationID, true)
if err != nil {
return nil, common.NewError("invalid_parameters", "Invalid allocation id passed."+err.Error())
}

sign := r.Header.Get(common.ClientSignatureHeader)
allocation, ok := mux.Vars(r)["allocation"]
if !ok {
return false, common.NewError("invalid_params", "Missing allocation tx")
}
valid, err := verifySignatureFromRequest(allocation, sign, allocationObj.OwnerPublicKey)
if !valid || err != nil {
return nil, common.NewError("invalid_signature", "Invalid signature")
}

path := r.FormValue("path")
refereeClientID := r.FormValue("refereeClientID")
filePathHash := fileref.GetReferenceLookup(allocationID, path)
_, err = reference.GetReferenceFromLookupHash(ctx, allocationID, filePathHash)
if err != nil {
return nil, common.NewError("invalid_parameters", "Invalid file path. "+err.Error())
}
clientID := ctx.Value(constants.CLIENT_CONTEXT_KEY).(string)
if clientID != allocationObj.OwnerID {
return nil, common.NewError("invalid_operation", "Operation needs to be performed by the owner of the allocation")
}
err = reference.DeleteShareInfo(ctx, reference.ShareInfo{
ClientID: refereeClientID,
FilePathHash: filePathHash,
})
if errors.Is(err, gorm.ErrRecordNotFound) {
resp := map[string]interface{}{
"status": http.StatusNotFound,
"message": "Path not found",
}
return resp, nil
}
if err != nil {
return nil, err
}
resp := map[string]interface{}{
"status": http.StatusNoContent,
"message": "Path successfully removed from allocation",
}
return resp, nil
}

func InsertShare(ctx context.Context, r *http.Request) (interface{}, error) {
ctx = setupHandlerContext(ctx, r)

allocationID := ctx.Value(constants.ALLOCATION_CONTEXT_KEY).(string)
allocationObj, err := storageHandler.verifyAllocation(ctx, allocationID, true)
if err != nil {
return nil, common.NewError("invalid_parameters", "Invalid allocation id passed."+err.Error())
}

sign := r.Header.Get(common.ClientSignatureHeader)
allocation, ok := mux.Vars(r)["allocation"]
if !ok {
return false, common.NewError("invalid_params", "Missing allocation tx")
}
valid, err := verifySignatureFromRequest(allocation, sign, allocationObj.OwnerPublicKey)
if !valid || err != nil {
return nil, common.NewError("invalid_signature", "Invalid signature")
}

encryptionPublicKey := r.FormValue("encryption_public_key")
authTicketString := r.FormValue("auth_ticket")
authTicket := &readmarker.AuthTicket{}

err = json.Unmarshal([]byte(authTicketString), &authTicket)
if err != nil {
return false, common.NewError("invalid_parameters", "Error parsing the auth ticket for download."+err.Error())
}

fileref, err := reference.GetReferenceFromLookupHash(ctx, allocationID, authTicket.FilePathHash)
if err != nil {
return nil, common.NewError("invalid_parameters", "Invalid file path. "+err.Error())
}

authTicketVerified, err := storageHandler.verifyAuthTicket(ctx, authTicketString, allocationObj, fileref, authTicket.ClientID)
if !authTicketVerified {
return nil, common.NewError("auth_ticket_verification_failed", "Could not verify the auth ticket. "+err.Error())
}

if err != nil {
return nil, err
}

shareInfo := reference.ShareInfo{
OwnerID: authTicket.OwnerID,
ClientID: authTicket.ClientID,
FilePathHash: authTicket.FilePathHash,
ReEncryptionKey: authTicket.ReEncryptionKey,
ClientEncryptionPublicKey: encryptionPublicKey,
ExpiryAt: common.ToTime(authTicket.Expiration),
}

existingShare, err := reference.GetShareInfo(ctx, authTicket.ClientID, authTicket.FilePathHash)
if err != nil {
return nil, err
}

if existingShare != nil {
err = reference.UpdateShareInfo(ctx, shareInfo)
} else {
err = reference.AddShareInfo(ctx, shareInfo)
}
if err != nil {
return nil, err
}

resp := map[string]interface{}{
"message": "Share info added successfully",
}

return resp, nil
}

func MarketPlaceShareInfoHandler(ctx context.Context, r *http.Request) (interface{}, error) {
if r.Method == "DELETE" {
return RevokeShare(ctx, r)
}

if r.Method == "POST" {
return InsertShare(ctx, r)
}

return nil, errors.New("invalid request method, only POST is allowed")
}
Loading