5bf00db2c9
The logic here is that we'll have all binary encoding/decoding done via our io package, which simplifies error handling. This functionality doesn't belong to util, so it's moved. This also expands BufBinWriter with Reset() method to fit the needs of core package.
96 lines
2.5 KiB
Go
96 lines
2.5 KiB
Go
package storage
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/binary"
|
|
"sort"
|
|
|
|
"github.com/CityOfZion/neo-go/pkg/io"
|
|
"github.com/CityOfZion/neo-go/pkg/util"
|
|
)
|
|
|
|
// Version will attempt to get the current version stored in the
|
|
// underlying Store.
|
|
func Version(s Store) (string, error) {
|
|
version, err := s.Get(SYSVersion.Bytes())
|
|
return string(version), err
|
|
}
|
|
|
|
// PutVersion will store the given version in the underlying Store.
|
|
func PutVersion(s Store, v string) error {
|
|
return s.Put(SYSVersion.Bytes(), []byte(v))
|
|
}
|
|
|
|
// CurrentBlockHeight returns the current block height found in the
|
|
// underlying Store.
|
|
func CurrentBlockHeight(s Store) (uint32, error) {
|
|
b, err := s.Get(SYSCurrentBlock.Bytes())
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
return binary.LittleEndian.Uint32(b[32:36]), nil
|
|
}
|
|
|
|
// CurrentHeaderHeight returns the current header height and hash from
|
|
// the underlying Store.
|
|
func CurrentHeaderHeight(s Store) (i uint32, h util.Uint256, err error) {
|
|
var b []byte
|
|
b, err = s.Get(SYSCurrentHeader.Bytes())
|
|
if err != nil {
|
|
return
|
|
}
|
|
i = binary.LittleEndian.Uint32(b[32:36])
|
|
h, err = util.Uint256DecodeReverseBytes(b[:32])
|
|
return
|
|
}
|
|
|
|
// uint32Slice attaches the methods of Interface to []int, sorting in increasing order.
|
|
type uint32Slice []uint32
|
|
|
|
func (p uint32Slice) Len() int { return len(p) }
|
|
func (p uint32Slice) Less(i, j int) bool { return p[i] < p[j] }
|
|
func (p uint32Slice) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
|
|
|
|
// HeaderHashes returns a sorted list of header hashes retrieved from
|
|
// the given underlying Store.
|
|
func HeaderHashes(s Store) ([]util.Uint256, error) {
|
|
hashMap := make(map[uint32][]util.Uint256)
|
|
s.Seek(IXHeaderHashList.Bytes(), func(k, v []byte) {
|
|
storedCount := binary.LittleEndian.Uint32(k[1:])
|
|
hashes, err := read2000Uint256Hashes(v)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
hashMap[storedCount] = hashes
|
|
})
|
|
|
|
var (
|
|
hashes = make([]util.Uint256, 0, len(hashMap))
|
|
sortedKeys = make([]uint32, 0, len(hashMap))
|
|
)
|
|
|
|
for k := range hashMap {
|
|
sortedKeys = append(sortedKeys, k)
|
|
}
|
|
sort.Sort(uint32Slice(sortedKeys))
|
|
|
|
for _, key := range sortedKeys {
|
|
hashes = append(hashes[:key], hashMap[key]...)
|
|
}
|
|
|
|
return hashes, nil
|
|
}
|
|
|
|
// read2000Uint256Hashes attempts to read 2000 Uint256 hashes from
|
|
// the given byte array.
|
|
func read2000Uint256Hashes(b []byte) ([]util.Uint256, error) {
|
|
r := bytes.NewReader(b)
|
|
br := io.NewBinReaderFromIO(r)
|
|
lenHashes := br.ReadVarUint()
|
|
hashes := make([]util.Uint256, lenHashes)
|
|
br.ReadLE(hashes)
|
|
if br.Err != nil {
|
|
return nil, br.Err
|
|
}
|
|
return hashes, nil
|
|
}
|