webapi: Set merkle fields of file records when adding files to the blockchain.

This commit is contained in:
Kleissner
2021-11-28 22:03:08 +01:00
parent e5c2d8d91d
commit 793e586234
3 changed files with 62 additions and 7 deletions

View File

@@ -12,6 +12,8 @@ import (
"github.com/PeernetOfficial/core"
"github.com/PeernetOfficial/core/blockchain"
"github.com/PeernetOfficial/core/merkle"
"github.com/PeernetOfficial/core/protocol"
"github.com/PeernetOfficial/core/warehouse"
"github.com/google/uuid"
)
@@ -38,7 +40,7 @@ type apiFile struct {
Name string `json:"name"` // Name of the file
Description string `json:"description"` // Description. This is expected to be multiline and contain hashtags!
Date time.Time `json:"date"` // Date shared
NodeID []byte `json:"nodeid"` // Node ID, owner of the file
NodeID []byte `json:"nodeid"` // Node ID, owner of the file. Read only.
Metadata []apiFileMetadata `json:"metadata"` // Additional metadata.
}
@@ -139,6 +141,10 @@ func apiBlockchainFileAdd(w http.ResponseWriter, r *http.Request) {
var filesAdd []blockchain.BlockRecordFile
for _, file := range input.Files {
if len(file.Hash) != protocol.HashSize {
http.Error(w, "", http.StatusBadRequest)
return
}
if file.ID == uuid.Nil { // if the ID is not provided by the caller, set it
file.ID = uuid.New()
}
@@ -154,9 +160,20 @@ func apiBlockchainFileAdd(w http.ResponseWriter, r *http.Request) {
} else {
file.Size = uint64(fileInfo.Size())
}
} else {
file.Hash = protocol.HashData(nil)
file.Size = 0
}
filesAdd = append(filesAdd, blockRecordFileFromAPI(file))
blockRecord := blockRecordFileFromAPI(file)
// Set the merkle tree info as appropriate.
if !setFileMerkleInfo(&blockRecord) {
EncodeJSON(w, r, apiBlockchainBlockStatus{Status: blockchain.StatusNotInWarehouse})
return
}
filesAdd = append(filesAdd, blockRecord)
}
newHeight, newVersion, status := core.UserBlockchain.AddFiles(filesAdd)
@@ -233,7 +250,10 @@ func apiBlockchainFileUpdate(w http.ResponseWriter, r *http.Request) {
var filesAdd []blockchain.BlockRecordFile
for _, file := range input.Files {
if file.ID == uuid.Nil { // if the ID is not provided by the caller, abort
if len(file.Hash) != protocol.HashSize {
http.Error(w, "", http.StatusBadRequest)
return
} else if file.ID == uuid.Nil { // if the ID is not provided by the caller, abort
http.Error(w, "", http.StatusBadRequest)
return
}
@@ -249,9 +269,20 @@ func apiBlockchainFileUpdate(w http.ResponseWriter, r *http.Request) {
} else {
file.Size = uint64(fileInfo.Size())
}
} else {
file.Hash = protocol.HashData(nil)
file.Size = 0
}
filesAdd = append(filesAdd, blockRecordFileFromAPI(file))
blockRecord := blockRecordFileFromAPI(file)
// Set the merkle tree info as appropriate.
if !setFileMerkleInfo(&blockRecord) {
EncodeJSON(w, r, apiBlockchainBlockStatus{Status: blockchain.StatusNotInWarehouse})
return
}
filesAdd = append(filesAdd, blockRecord)
}
newHeight, newVersion, status := core.UserBlockchain.ReplaceFiles(filesAdd)
@@ -285,3 +316,23 @@ func (info *apiFileMetadata) GetNumber() uint64 {
func (file *apiFile) IsVirtualFolder() bool {
return file.Type == core.TypeFolder && file.Format == core.FormatFolder
}
// setFileMerkleInfo sets the merkle fields in the BlockRecordFile
func setFileMerkleInfo(file *blockchain.BlockRecordFile) (valid bool) {
if file.Size <= merkle.MinimumFragmentSize {
// If smaller or equal than the minimum fragment size, the merkle tree is not used.
file.MerkleRootHash = file.Hash
file.FragmentSize = merkle.MinimumFragmentSize
} else {
// Get the information from the Warehouse .merkle companion file.
tree, status, _ := core.UserWarehouse.ReadMerkleTree(file.Hash, true)
if status != warehouse.StatusOK {
return false
}
file.MerkleRootHash = tree.RootHash
file.FragmentSize = tree.FragmentSize
}
return true
}

View File

@@ -27,7 +27,7 @@ Request: POST /warehouse/create with raw data to create as new file
Response: 200 with JSON structure WarehouseResult
*/
func apiWarehouseCreateFile(w http.ResponseWriter, r *http.Request) {
hash, status, err := core.UserWarehouse.CreateFile(r.Body)
hash, status, err := core.UserWarehouse.CreateFile(r.Body, 0)
if err != nil {
core.Filters.LogError("warehouse.CreateFile", "status %d error: %v", status, err)

View File

@@ -229,7 +229,7 @@ type apiFile struct {
Name string `json:"name"` // Name of the file
Description string `json:"description"` // Description. This is expected to be multiline and contain hashtags!
Date time.Time `json:"date"` // Date shared
NodeID []byte `json:"nodeid"` // Node ID, owner of the file
NodeID []byte `json:"nodeid"` // Node ID, owner of the file. Read only.
Metadata []apiFileMetadata `json:"metadata"` // Additional metadata.
}
@@ -262,7 +262,8 @@ This adds a file with the provided information to the blockchain. The date field
Any file added is publicly accessible. The user should be informed about this fact in advance. The user is responsible and liable for any files shared.
Each file must be already stored in the Warehouse (virtual folders are exempt). If any file is not stored in the Warehouse, the function aborts with the status code StatusNotInWarehouse. Files can be added to the Warehouse via `/warehouse/create` and `/warehouse/create/path`.
Each file must be already stored in the Warehouse (virtual folders are exempt). Files in the Warehouse are identified using the hash.
If any file is not stored in the Warehouse, the function aborts with the status code StatusNotInWarehouse. Files can be added to the Warehouse via `/warehouse/create` and `/warehouse/create/path`.
If the block record encoding fails for any file, this function aborts with the status code StatusCorruptBlockRecord. In case the function aborts, the blockchain remains unchanged.
@@ -945,6 +946,9 @@ Status codes:
| 11 | StatusErrorReadFile | Error reading file. |
| 12 | StatusErrorSeekFile | Error seeking to position in file. |
| 13 | StatusErrorTargetExists | Target file already exists. |
| 14 | StatusErrorCreateTarget | Error creating target file. |
| 15 | StatusErrorCreateMerkle | Error creating merkle tree. |
| 16 | StatusErrorMerkleTreeFile | Invalid merkle tree companion file. |
### Create File