89 lines
2 KiB
Go
89 lines
2 KiB
Go
package stateroot
|
|
|
|
import (
|
|
"encoding/binary"
|
|
|
|
"github.com/nspcc-dev/neo-go/pkg/core/state"
|
|
"github.com/nspcc-dev/neo-go/pkg/core/storage"
|
|
"github.com/nspcc-dev/neo-go/pkg/io"
|
|
)
|
|
|
|
const (
|
|
prefixGC = 0x01
|
|
prefixLocal = 0x02
|
|
prefixValidated = 0x03
|
|
)
|
|
|
|
func (s *Module) addLocalStateRoot(sr *state.MPTRoot) error {
|
|
key := makeStateRootKey(sr.Index)
|
|
if err := s.putStateRoot(key, sr); err != nil {
|
|
return err
|
|
}
|
|
|
|
data := make([]byte, 4)
|
|
binary.LittleEndian.PutUint32(data, sr.Index)
|
|
if err := s.Store.Put([]byte{byte(storage.DataMPT), prefixLocal}, data); err != nil {
|
|
return err
|
|
}
|
|
s.currentLocal.Store(sr.Root)
|
|
s.localHeight.Store(sr.Index)
|
|
if s.bc.GetConfig().StateRootInHeader {
|
|
s.validatedHeight.Store(sr.Index)
|
|
updateStateHeightMetric(sr.Index)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (s *Module) putStateRoot(key []byte, sr *state.MPTRoot) error {
|
|
w := io.NewBufBinWriter()
|
|
sr.EncodeBinary(w.BinWriter)
|
|
return s.Store.Put(key, w.Bytes())
|
|
}
|
|
|
|
func (s *Module) getStateRoot(key []byte) (*state.MPTRoot, error) {
|
|
data, err := s.Store.Get(key)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
sr := new(state.MPTRoot)
|
|
r := io.NewBinReaderFromBuf(data)
|
|
sr.DecodeBinary(r)
|
|
return sr, r.Err
|
|
}
|
|
|
|
func makeStateRootKey(index uint32) []byte {
|
|
key := make([]byte, 5)
|
|
key[0] = byte(storage.DataMPT)
|
|
binary.BigEndian.PutUint32(key, index)
|
|
return key
|
|
}
|
|
|
|
// AddStateRoot adds validated state root provided by network.
|
|
func (s *Module) AddStateRoot(sr *state.MPTRoot) error {
|
|
if err := s.VerifyStateRoot(sr); err != nil {
|
|
return err
|
|
}
|
|
key := makeStateRootKey(sr.Index)
|
|
local, err := s.getStateRoot(key)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if local.Witness != nil {
|
|
return nil
|
|
}
|
|
if err := s.putStateRoot(key, sr); err != nil {
|
|
return err
|
|
}
|
|
|
|
data := make([]byte, 4)
|
|
binary.LittleEndian.PutUint32(data, sr.Index)
|
|
if err := s.Store.Put([]byte{byte(storage.DataMPT), prefixValidated}, data); err != nil {
|
|
return err
|
|
}
|
|
s.validatedHeight.Store(sr.Index)
|
|
if !s.bc.GetConfig().StateRootInHeader {
|
|
updateStateHeightMetric(sr.Index)
|
|
}
|
|
return nil
|
|
}
|