forked from TrueCloudLab/neoneo-go
c80ee952a1
add processing of validators while block persist; add validator structure with decoding/encoding; add validator get from store; add EnrollmentTX and StateTX processing; add pubkey decode bytes, unique and contains functions;
109 lines
3.1 KiB
Go
109 lines
3.1 KiB
Go
package core
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"github.com/CityOfZion/neo-go/pkg/core/storage"
|
|
"github.com/CityOfZion/neo-go/pkg/crypto/keys"
|
|
"github.com/CityOfZion/neo-go/pkg/io"
|
|
"github.com/CityOfZion/neo-go/pkg/util"
|
|
)
|
|
|
|
// Validators is a mapping between public keys and ValidatorState.
|
|
type Validators map[*keys.PublicKey]*ValidatorState
|
|
|
|
func (v Validators) getAndUpdate(s storage.Store, publicKey *keys.PublicKey) (*ValidatorState, error) {
|
|
if validator, ok := v[publicKey]; ok {
|
|
return validator, nil
|
|
}
|
|
|
|
validatorState, err := getValidatorStateFromStore(s, publicKey)
|
|
if err != nil {
|
|
if err != storage.ErrKeyNotFound {
|
|
return nil, err
|
|
}
|
|
validatorState = &ValidatorState{PublicKey: publicKey}
|
|
}
|
|
v[publicKey] = validatorState
|
|
return validatorState, nil
|
|
|
|
}
|
|
|
|
// getValidatorsFromStore returns all validators from store.
|
|
func getValidatorsFromStore(s storage.Store) []*ValidatorState {
|
|
var validators []*ValidatorState
|
|
s.Seek(storage.STValidator.Bytes(), func(k, v []byte) {
|
|
r := io.NewBinReaderFromBuf(v)
|
|
validator := &ValidatorState{}
|
|
validator.DecodeBinary(r)
|
|
if r.Err != nil {
|
|
return
|
|
}
|
|
validators = append(validators, validator)
|
|
})
|
|
return validators
|
|
}
|
|
|
|
// getValidatorStateFromStore returns validator by publicKey.
|
|
func getValidatorStateFromStore(s storage.Store, publicKey *keys.PublicKey) (*ValidatorState, error) {
|
|
validatorState := &ValidatorState{}
|
|
key := storage.AppendPrefix(storage.STValidator, publicKey.Bytes())
|
|
if b, err := s.Get(key); err == nil {
|
|
r := io.NewBinReaderFromBuf(b)
|
|
validatorState.DecodeBinary(r)
|
|
if r.Err != nil {
|
|
return nil, fmt.Errorf("failed to decode (ValidatorState): %s", r.Err)
|
|
}
|
|
} else {
|
|
return nil, err
|
|
}
|
|
return validatorState, nil
|
|
}
|
|
|
|
// commit writes all validator states to the given Batch.
|
|
func (v Validators) commit(store storage.Store) error {
|
|
for _, validator := range v {
|
|
if err := putValidatorStateIntoStore(store, validator); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// putValidatorStateIntoStore puts given ValidatorState into the given store.
|
|
func putValidatorStateIntoStore(store storage.Store, vs *ValidatorState) error {
|
|
buf := io.NewBufBinWriter()
|
|
vs.EncodeBinary(buf.BinWriter)
|
|
if buf.Err != nil {
|
|
return buf.Err
|
|
}
|
|
key := storage.AppendPrefix(storage.STValidator, vs.PublicKey.Bytes())
|
|
return store.Put(key, buf.Bytes())
|
|
}
|
|
|
|
// ValidatorState holds the state of a validator.
|
|
type ValidatorState struct {
|
|
PublicKey *keys.PublicKey
|
|
Registered bool
|
|
Votes util.Fixed8
|
|
}
|
|
|
|
// RegisteredAndHasVotes returns true or false whether Validator is registered and has votes.
|
|
func (vs *ValidatorState) RegisteredAndHasVotes() bool {
|
|
return vs.Registered && vs.Votes > util.Fixed8(0)
|
|
}
|
|
|
|
// EncodeBinary encodes ValidatorState to the given BinWriter.
|
|
func (vs *ValidatorState) EncodeBinary(bw *io.BinWriter) {
|
|
vs.PublicKey.EncodeBinary(bw)
|
|
bw.WriteLE(vs.Registered)
|
|
bw.WriteLE(vs.Votes)
|
|
}
|
|
|
|
// DecodeBinary decodes ValidatorState from the given BinReader.
|
|
func (vs *ValidatorState) DecodeBinary(reader *io.BinReader) {
|
|
vs.PublicKey = &keys.PublicKey{}
|
|
vs.PublicKey.DecodeBinary(reader)
|
|
reader.ReadLE(&vs.Registered)
|
|
reader.ReadLE(&vs.Votes)
|
|
}
|