diff options
author | github-classroom[bot] <66690702+github-classroom[bot]@users.noreply.github.com> | 2022-02-28 19:36:23 +0000 |
---|---|---|
committer | github-classroom[bot] <66690702+github-classroom[bot]@users.noreply.github.com> | 2022-02-28 19:36:23 +0000 |
commit | 1dd0508d5d3c737f1ee9c723f580baf73b1cfd70 (patch) | |
tree | 6adcc5ef85f9cf0bbb205c577da0bac9148114dd /pkg/blockchain/chainwriter/chainwriter.go |
Initial commit
Diffstat (limited to 'pkg/blockchain/chainwriter/chainwriter.go')
-rw-r--r-- | pkg/blockchain/chainwriter/chainwriter.go | 127 |
1 files changed, 127 insertions, 0 deletions
diff --git a/pkg/blockchain/chainwriter/chainwriter.go b/pkg/blockchain/chainwriter/chainwriter.go new file mode 100644 index 0000000..67a7d49 --- /dev/null +++ b/pkg/blockchain/chainwriter/chainwriter.go @@ -0,0 +1,127 @@ +package chainwriter + +import ( + "Chain/pkg/block" + "Chain/pkg/blockchain/blockinfodatabase" + "Chain/pkg/pro" + "Chain/pkg/utils" + "google.golang.org/protobuf/proto" + "log" + "os" +) + +// ChainWriter handles all I/O for the BlockChain. It stores and retrieves +// Blocks and UndoBlocks. +// See config.go for more information on its fields. +// Block files are of the format: +// "DataDirectory/BlockFileName_CurrentBlockFileNumber.FileExtension" +// Ex: "data/block_0.txt" +// UndoBlock files are of the format: +// "DataDirectory/UndoFileName_CurrentUndoFileNumber.FileExtension" +// Ex: "data/undo_0.txt" +type ChainWriter struct { + // data storage information + FileExtension string + DataDirectory string + + // block information + BlockFileName string + CurrentBlockFileNumber uint32 + CurrentBlockOffset uint32 + MaxBlockFileSize uint32 + + // undo block information + UndoFileName string + CurrentUndoFileNumber uint32 + CurrentUndoOffset uint32 + MaxUndoFileSize uint32 +} + +// New returns a ChainWriter given a Config. +func New(config *Config) *ChainWriter { + if err := os.MkdirAll(config.DataDirectory, 0700); err != nil { + log.Fatalf("Could not create ChainWriter's data directory") + } + return &ChainWriter{ + FileExtension: config.FileExtension, + DataDirectory: config.DataDirectory, + BlockFileName: config.BlockFileName, + CurrentBlockFileNumber: 0, + CurrentBlockOffset: 0, + MaxBlockFileSize: config.MaxBlockFileSize, + UndoFileName: config.UndoFileName, + CurrentUndoFileNumber: 0, + CurrentUndoOffset: 0, + MaxUndoFileSize: config.MaxUndoFileSize, + } +} + +// StoreBlock stores a Block and its corresponding UndoBlock to Disk, +// returning a BlockRecord that contains information for later retrieval. +func (cw *ChainWriter) StoreBlock(bl *block.Block, undoBlock *UndoBlock, height uint32) *blockinfodatabase.BlockRecord { + // serialize block + b := block.EncodeBlock(bl) + serializedBlock, err := proto.Marshal(b) + if err != nil { + utils.Debug.Printf("Failed to marshal block") + } + // serialize undo block + ub := EncodeUndoBlock(undoBlock) + serializedUndoBlock, err := proto.Marshal(ub) + if err != nil { + utils.Debug.Printf("Failed to marshal undo block") + } + // write block to disk + bfi := cw.WriteBlock(serializedBlock) + // create an empty file info, which we will update if the function is passed an undo block. + ufi := &FileInfo{} + if undoBlock.Amounts != nil { + ufi = cw.WriteUndoBlock(serializedUndoBlock) + } + + return &blockinfodatabase.BlockRecord{ + Header: bl.Header, + Height: height, + NumberOfTransactions: uint32(len(bl.Transactions)), + BlockFile: bfi.FileName, + BlockStartOffset: bfi.StartOffset, + BlockEndOffset: bfi.EndOffset, + UndoFile: ufi.FileName, + UndoStartOffset: ufi.StartOffset, + UndoEndOffset: ufi.EndOffset, + } +} + +// WriteBlock writes a serialized Block to Disk and returns +// a FileInfo for storage information. +func (cw *ChainWriter) WriteBlock(serializedBlock []byte) *FileInfo { + //TODO + return nil +} + +// WriteUndoBlock writes a serialized UndoBlock to Disk and returns +// a FileInfo for storage information. +func (cw *ChainWriter) WriteUndoBlock(serializedUndoBlock []byte) *FileInfo { + //TODO + return nil +} + +// ReadBlock returns a Block given a FileInfo. +func (cw *ChainWriter) ReadBlock(fi *FileInfo) *block.Block { + bytes := readFromDisk(fi) + pb := &pro.Block{} + if err := proto.Unmarshal(bytes, pb); err != nil { + utils.Debug.Printf("failed to unmarshal block from file info {%v}", fi) + } + return block.DecodeBlock(pb) +} + +// ReadUndoBlock returns an UndoBlock given a FileInfo. +func (cw *ChainWriter) ReadUndoBlock(fi *FileInfo) *UndoBlock { + bytes := readFromDisk(fi) + pub := &pro.UndoBlock{} + if err := proto.Unmarshal(bytes, pub); err != nil { + utils.Debug.Printf("failed to unmarshal undo block from file info {%v}", fi) + } + return DecodeUndoBlock(pub) +} |