mirror of
https://github.com/PeernetOfficial/core.git
synced 2026-07-17 02:47:51 +01:00
120 lines
3.3 KiB
Go
120 lines
3.3 KiB
Go
/*
|
|
File Username: Profile.go
|
|
Copyright: 2021 Peernet s.r.o.
|
|
Author: Peter Kleissner
|
|
*/
|
|
|
|
package blockchain
|
|
|
|
// ProfileReadField reads the specified profile field. See ProfileX for the list of recognized fields. The encoding depends on the field type. Status is StatusX.
|
|
func (blockchain *Blockchain) ProfileReadField(index uint16) (data []byte, status int) {
|
|
found := false
|
|
|
|
status = blockchain.Iterate(func(block *Block) (statusI int) {
|
|
fields, err := decodeBlockRecordProfile(block.RecordsRaw)
|
|
if err != nil {
|
|
return StatusCorruptBlockRecord
|
|
} else if len(fields) == 0 {
|
|
return StatusOK
|
|
}
|
|
|
|
// Check if the field is available in the profile record. If there are multiple records, only return the latest one.
|
|
for n := range fields {
|
|
if fields[n].Type == index {
|
|
data = fields[n].Data
|
|
found = true
|
|
}
|
|
}
|
|
|
|
return StatusOK
|
|
})
|
|
|
|
if status != StatusOK {
|
|
return nil, status
|
|
} else if !found {
|
|
return nil, StatusDataNotFound
|
|
}
|
|
|
|
return data, StatusOK
|
|
}
|
|
|
|
// ProfileList lists all profile fields. Status is StatusX.
|
|
func (blockchain *Blockchain) ProfileList() (fields []BlockRecordProfile, status int) {
|
|
uniqueFields := make(map[uint16][]byte)
|
|
|
|
status = blockchain.Iterate(func(block *Block) (statusI int) {
|
|
fields, err := decodeBlockRecordProfile(block.RecordsRaw)
|
|
if err != nil {
|
|
return StatusCorruptBlockRecord
|
|
}
|
|
|
|
for n := range fields {
|
|
uniqueFields[fields[n].Type] = fields[n].Data
|
|
}
|
|
|
|
return StatusOK
|
|
})
|
|
|
|
for key, value := range uniqueFields {
|
|
fields = append(fields, BlockRecordProfile{Type: key, Data: value})
|
|
}
|
|
|
|
return fields, status
|
|
}
|
|
|
|
// ProfileWrite writes profile fields and blobs to the blockchain. Status is StatusX.
|
|
func (blockchain *Blockchain) ProfileWrite(fields []BlockRecordProfile) (newHeight, newVersion uint64, status int) {
|
|
encodeProfileAppend := func(fields []BlockRecordProfile) (newHeight, newVersion uint64, status int) {
|
|
encoded, err := encodeBlockRecordProfile(fields)
|
|
if err != nil {
|
|
return 0, 0, StatusCorruptBlockRecord
|
|
}
|
|
|
|
return blockchain.Append(encoded)
|
|
}
|
|
|
|
blockSize := uint64(blockHeaderSize)
|
|
var recordFields []BlockRecordProfile
|
|
|
|
for _, field := range fields {
|
|
recordSize := field.SizeInBlock()
|
|
|
|
// need to create a new block due to target block size?
|
|
if len(recordFields) > 0 && blockSize+recordSize > TargetBlockSize {
|
|
if newHeight, newVersion, status = encodeProfileAppend(recordFields); status != StatusOK {
|
|
return newHeight, newVersion, status
|
|
}
|
|
|
|
blockSize = blockHeaderSize
|
|
recordFields = nil
|
|
}
|
|
|
|
blockSize += recordSize
|
|
recordFields = append(recordFields, field)
|
|
}
|
|
|
|
return encodeProfileAppend(recordFields)
|
|
}
|
|
|
|
// ProfileDelete deletes fields and blobs from the blockchain. Status is StatusX.
|
|
func (blockchain *Blockchain) ProfileDelete(fields []uint16) (newHeight, newVersion uint64, status int) {
|
|
return blockchain.IterateDeleteRecord(nil, func(record *BlockRecordRaw) (deleteAction int) {
|
|
if record.Type != RecordTypeProfile {
|
|
return 0 // no action
|
|
}
|
|
|
|
existingFields, err := decodeBlockRecordProfile([]BlockRecordRaw{*record})
|
|
if err != nil || len(existingFields) != 1 {
|
|
return 3 // error blockchain corrupt
|
|
}
|
|
|
|
for _, i := range fields {
|
|
if i == existingFields[0].Type { // found a file ID to delete?
|
|
return 1 // delete record
|
|
}
|
|
}
|
|
|
|
return 0 // no action on record
|
|
})
|
|
}
|