mirror of
https://github.com/nspcc-dev/neo-go.git
synced 2024-10-16 15:43:25 +00:00
d143696328
It was completely ruined by bf20db09e0
. MPT was
updating bc.dao directly which shouldn't ever happen, it must write into the
same cache and then Persist these KVs as usual.
80 lines
1.9 KiB
Go
80 lines
1.9 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(store *storage.MemCachedStore, sr *state.MPTRoot) error {
|
|
key := makeStateRootKey(sr.Index)
|
|
if err := putStateRoot(store, key, sr); err != nil {
|
|
return err
|
|
}
|
|
|
|
data := make([]byte, 4)
|
|
binary.LittleEndian.PutUint32(data, sr.Index)
|
|
return store.Put([]byte{byte(storage.DataMPT), prefixLocal}, data)
|
|
}
|
|
|
|
func putStateRoot(store *storage.MemCachedStore, key []byte, sr *state.MPTRoot) error {
|
|
w := io.NewBufBinWriter()
|
|
sr.EncodeBinary(w.BinWriter)
|
|
return 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 := &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 len(local.Witness) != 0 {
|
|
return nil
|
|
}
|
|
if err := putStateRoot(s.Store, 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
|
|
}
|