diff --git a/blockchain/Block Records.go b/blockchain/Block Record File.go similarity index 66% rename from blockchain/Block Records.go rename to blockchain/Block Record File.go index 79f4c9d..dd0623b 100644 --- a/blockchain/Block Records.go +++ b/blockchain/Block Record File.go @@ -1,10 +1,8 @@ /* -File Name: Block Encoding.go +File Name: Block Record File.go Copyright: 2021 Peernet s.r.o. Author: Peter Kleissner -This files defines the encoding of blocks and records within. - File records: Offset Size Info 0 32 Hash blake3 of the file content @@ -24,11 +22,6 @@ Offset Size Info Tag data record contains only raw data and may be referenced by Tags in File records. This is a basic embedded way of compression when tags are repetitive in multiple files within the same block. -Profile records: -Offset Size Info -0 2 Type -2 ? Data according to the type - */ package blockchain @@ -41,19 +34,6 @@ import ( "github.com/google/uuid" ) -// ---- Block record structures (decoded) ---- - -// RecordTypeX defines the type of the record -const ( - RecordTypeProfile = 0 // Profile data about the end user. - RecordTypeTagData = 1 // Tag data record to be referenced by one or multiple tags. Only valid in the context of the current block. - RecordTypeFile = 2 // File - RecordTypeInvalid1 = 3 // Do not use. - RecordTypeCertificate = 4 // Certificate to certify provided information in the blockchain issued by a trusted 3rd party. - RecordTypeContentRating = 5 // Content rating (positive). - RecordTypeContentReport = 6 // Content report (negative). -) - // BlockRecordFile is the metadata of a file published on the blockchain type BlockRecordFile struct { Hash []byte // Hash of the file data @@ -74,8 +54,6 @@ type BlockRecordFileTag struct { // This is an embedded basic compression algorithm for repetitive tag. For example directory tags or album tags might be heavily repetitive among files. } -// ---- low-level encoding ---- - // decodeBlockRecordFiles decodes only file records. Other records are ignored. func decodeBlockRecordFiles(recordsRaw []BlockRecordRaw, nodeID []byte) (files []BlockRecordFile, err error) { for i, record := range recordsRaw { @@ -230,87 +208,3 @@ func intToBytes(number int) (buffer []byte) { binary.LittleEndian.PutUint64(buffer[0:8], uint64(number)) return buffer[0:8] } - -// ---- high-level decoding ---- - -// BlockDecoded contains the decoded records from a block -type BlockDecoded struct { - Block - RecordsDecoded []interface{} // Decoded records. See BlockRecordX structures. -} - -// decodeBlockRecords decodes all raw records in the block and returns a high-level decoded structure -// Use decodeBlockRecordX instead for specific record decoding. -func decodeBlockRecords(block *Block) (decoded *BlockDecoded, err error) { - decoded = &BlockDecoded{Block: *block} - - files, err := decodeBlockRecordFiles(block.RecordsRaw, block.NodeID) - if err != nil { - return nil, err - } - - for _, file := range files { - decoded.RecordsDecoded = append(decoded.RecordsDecoded, file) - } - - if profileFields, err := decodeBlockRecordProfile(block.RecordsRaw); err != nil { - return nil, err - } else if len(profileFields) > 0 { - decoded.RecordsDecoded = append(decoded.RecordsDecoded, profileFields) - } - - return decoded, nil -} - -// ---- Profile data ---- - -// BlockRecordProfile provides information about the end user. -type BlockRecordProfile struct { - Type uint16 // See ProfileX constants. - Data []byte // Data -} - -// decodeBlockRecordProfile decodes only profile records. Other records are ignored. -func decodeBlockRecordProfile(recordsRaw []BlockRecordRaw) (fields []BlockRecordProfile, err error) { - fieldMap := make(map[uint16][]byte) - - for _, record := range recordsRaw { - if record.Type != RecordTypeProfile { - continue - } - - if len(record.Data) < 2 { - return nil, errors.New("profile record invalid size") - } - - fieldType := binary.LittleEndian.Uint16(record.Data[0:2]) - fieldMap[fieldType] = record.Data[2:] - } - - for fieldType, fieldData := range fieldMap { - fields = append(fields, BlockRecordProfile{Type: fieldType, Data: fieldData}) - } - - return fields, nil -} - -// encodeBlockRecordProfile encodes the profile record. -func encodeBlockRecordProfile(fields []BlockRecordProfile) (recordsRaw []BlockRecordRaw, err error) { - if len(fields) > math.MaxUint16 { - return nil, errors.New("exceeding max count of fields") - } - - for n := range fields { - if len(fields[n].Data) > math.MaxUint32 { - return nil, errors.New("exceeding max field size") - } - - data := make([]byte, 2) - binary.LittleEndian.PutUint16(data[0:2], fields[n].Type) - data = append(data, fields[n].Data...) - - recordsRaw = append(recordsRaw, BlockRecordRaw{Type: RecordTypeProfile, Data: data}) - } - - return recordsRaw, nil -} diff --git a/blockchain/Block Record Profile.go b/blockchain/Block Record Profile.go new file mode 100644 index 0000000..eefff58 --- /dev/null +++ b/blockchain/Block Record Profile.go @@ -0,0 +1,70 @@ +/* +File Name: Block Record Profile.go +Copyright: 2021 Peernet s.r.o. +Author: Peter Kleissner + +Profile records: +Offset Size Info +0 2 Type +2 ? Data according to the type + +*/ + +package blockchain + +import ( + "encoding/binary" + "errors" + "math" +) + +// BlockRecordProfile provides information about the end user. +type BlockRecordProfile struct { + Type uint16 // See ProfileX constants. + Data []byte // Data +} + +// decodeBlockRecordProfile decodes only profile records. Other records are ignored. +func decodeBlockRecordProfile(recordsRaw []BlockRecordRaw) (fields []BlockRecordProfile, err error) { + fieldMap := make(map[uint16][]byte) + + for _, record := range recordsRaw { + if record.Type != RecordTypeProfile { + continue + } + + if len(record.Data) < 2 { + return nil, errors.New("profile record invalid size") + } + + fieldType := binary.LittleEndian.Uint16(record.Data[0:2]) + fieldMap[fieldType] = record.Data[2:] + } + + for fieldType, fieldData := range fieldMap { + fields = append(fields, BlockRecordProfile{Type: fieldType, Data: fieldData}) + } + + return fields, nil +} + +// encodeBlockRecordProfile encodes the profile record. +func encodeBlockRecordProfile(fields []BlockRecordProfile) (recordsRaw []BlockRecordRaw, err error) { + if len(fields) > math.MaxUint16 { + return nil, errors.New("exceeding max count of fields") + } + + for n := range fields { + if len(fields[n].Data) > math.MaxUint32 { + return nil, errors.New("exceeding max field size") + } + + data := make([]byte, 2) + binary.LittleEndian.PutUint16(data[0:2], fields[n].Type) + data = append(data, fields[n].Data...) + + recordsRaw = append(recordsRaw, BlockRecordRaw{Type: RecordTypeProfile, Data: data}) + } + + return recordsRaw, nil +} diff --git a/blockchain/Block Record.go b/blockchain/Block Record.go new file mode 100644 index 0000000..6e4020b --- /dev/null +++ b/blockchain/Block Record.go @@ -0,0 +1,55 @@ +/* +File Name: Block Record.go +Copyright: 2021 Peernet s.r.o. +Author: Peter Kleissner + +Each record inside the block has this basic structure: +Offset Size Info +0 1 Record type +1 8 Date created. This remains the same in case of block refactoring. +9 4 Size of data +13 ? Data (encoding depends on record type) + +*/ + +package blockchain + +// RecordTypeX defines the type of the record +const ( + RecordTypeProfile = 0 // Profile data about the end user. + RecordTypeTagData = 1 // Tag data record to be referenced by one or multiple tags. Only valid in the context of the current block. + RecordTypeFile = 2 // File + RecordTypeInvalid1 = 3 // Do not use. + RecordTypeCertificate = 4 // Certificate to certify provided information in the blockchain issued by a trusted 3rd party. + RecordTypeContentRating = 5 // Content rating (positive). + RecordTypeContentReport = 6 // Content report (negative). +) + +// BlockDecoded contains the decoded records from a block +type BlockDecoded struct { + Block + RecordsDecoded []interface{} // Decoded records. See BlockRecordX structures. +} + +// decodeBlockRecords decodes all raw records in the block and returns a high-level decoded structure +// Use decodeBlockRecordX instead for specific record decoding. +func decodeBlockRecords(block *Block) (decoded *BlockDecoded, err error) { + decoded = &BlockDecoded{Block: *block} + + files, err := decodeBlockRecordFiles(block.RecordsRaw, block.NodeID) + if err != nil { + return nil, err + } + + for _, file := range files { + decoded.RecordsDecoded = append(decoded.RecordsDecoded, file) + } + + if profileFields, err := decodeBlockRecordProfile(block.RecordsRaw); err != nil { + return nil, err + } else if len(profileFields) > 0 { + decoded.RecordsDecoded = append(decoded.RecordsDecoded, profileFields) + } + + return decoded, nil +} diff --git a/blockchain/Block Encoding.go b/blockchain/Block.go similarity index 91% rename from blockchain/Block Encoding.go rename to blockchain/Block.go index 162beb7..600f5a3 100644 --- a/blockchain/Block Encoding.go +++ b/blockchain/Block.go @@ -1,5 +1,5 @@ /* -File Name: Block Encoding.go +File Name: Block.go Copyright: 2021 Peernet s.r.o. Author: Peter Kleissner @@ -12,13 +12,6 @@ Offset Size Info 109 4 Size of entire block including this header 113 2 Count of records that follow -Each record inside the block has this basic structure: -Offset Size Info -0 1 Record type -1 8 Date created. This remains the same in case of block refactoring. -9 4 Size of data -13 ? Data (encoding depends on record type) - */ package blockchain diff --git a/blockchain/Blockchain File.go b/blockchain/File.go similarity index 95% rename from blockchain/Blockchain File.go rename to blockchain/File.go index 108d4f0..7713f26 100644 --- a/blockchain/Blockchain File.go +++ b/blockchain/File.go @@ -1,5 +1,5 @@ /* -File Name: Blockchain File.go +File Name: File.go Copyright: 2021 Peernet s.r.o. Author: Peter Kleissner diff --git a/blockchain/Blockchain Profile.go b/blockchain/Profile.go similarity index 95% rename from blockchain/Blockchain Profile.go rename to blockchain/Profile.go index 8283cfa..984fcda 100644 --- a/blockchain/Blockchain Profile.go +++ b/blockchain/Profile.go @@ -1,5 +1,5 @@ /* -File Name: Blockchain Profile.go +File Name: Profile.go Copyright: 2021 Peernet s.r.o. Author: Peter Kleissner */