github.com/iotexproject/iotex-core@v1.14.1-rc1/action/protocol/staking/patchstore.go (about)

     1  // Copyright (c) 2020 IoTeX Foundation
     2  // This source code is provided 'as is' and no warranties are given as to title or non-infringement, merchantability
     3  // or fitness for purpose and, to the extent permitted by law, all liability for your use of the code is disclaimed.
     4  // This source code is governed by Apache License 2.0 that can be found in the LICENSE file.
     5  
     6  package staking
     7  
     8  import (
     9  	"encoding/csv"
    10  	"encoding/hex"
    11  	"fmt"
    12  	"io"
    13  	"os"
    14  	"path/filepath"
    15  
    16  	"github.com/pkg/errors"
    17  )
    18  
    19  const (
    20  	_name     = "name"
    21  	_operator = "operator"
    22  )
    23  
    24  // PatchStore is the patch store of staking protocol
    25  type PatchStore struct {
    26  	dir string
    27  }
    28  
    29  // NewPatchStore creates a new staking patch store
    30  func NewPatchStore(dir string) *PatchStore {
    31  	return &PatchStore{dir: dir}
    32  }
    33  
    34  func (store *PatchStore) pathOf(height uint64) string {
    35  	return filepath.Join(store.dir, fmt.Sprintf("%d.patch", height))
    36  }
    37  
    38  func (store *PatchStore) read(reader *csv.Reader) (CandidateList, error) {
    39  	record, err := reader.Read()
    40  	if err != nil {
    41  		return nil, err
    42  	}
    43  	if len(record) != 1 {
    44  		return nil, errors.Errorf("invalid record %+v", record)
    45  	}
    46  	data, err := hex.DecodeString(record[0])
    47  	if err != nil {
    48  		return nil, err
    49  	}
    50  	var list CandidateList
    51  	if err := list.Deserialize(data); err != nil {
    52  		return nil, err
    53  	}
    54  	return list, nil
    55  }
    56  
    57  // Read reads CandidateList by name and CandidateList by operator of given height
    58  func (store *PatchStore) Read(height uint64) (CandidateList, CandidateList, CandidateList, error) {
    59  	file, err := os.Open(store.pathOf(height))
    60  	if err != nil {
    61  		return nil, nil, nil, err
    62  	}
    63  	reader := csv.NewReader(file)
    64  	reader.FieldsPerRecord = -1
    65  	listByName, err := store.read(reader)
    66  	if err != nil {
    67  		return nil, nil, nil, err
    68  	}
    69  	listByOperator, err := store.read(reader)
    70  	if err != nil {
    71  		return nil, nil, nil, err
    72  	}
    73  	listByOwner, err := store.read(reader)
    74  	if err != nil && err != io.EOF {
    75  		// io.EOF indicates an empty owner list
    76  		return nil, nil, nil, err
    77  	}
    78  	return listByName, listByOperator, listByOwner, nil
    79  }