126 lines
2.9 KiB
Go
126 lines
2.9 KiB
Go
package encoding
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
|
|
corestore "cosmossdk.io/core/store"
|
|
)
|
|
|
|
// encodedSize returns the size of the encoded Changeset.
|
|
func encodedSize(cs *corestore.Changeset) int {
|
|
size := EncodeUvarintSize(uint64(len(cs.Changes)))
|
|
for _, changes := range cs.Changes {
|
|
size += EncodeBytesSize(changes.Actor)
|
|
size += EncodeUvarintSize(uint64(len(changes.StateChanges)))
|
|
for _, pair := range changes.StateChanges {
|
|
size += EncodeBytesSize(pair.Key)
|
|
size += EncodeUvarintSize(1) // pair.Remove
|
|
if !pair.Remove {
|
|
size += EncodeBytesSize(pair.Value)
|
|
}
|
|
}
|
|
}
|
|
return size
|
|
}
|
|
|
|
// MarshalChangeset returns the encoded byte representation of Changeset.
|
|
// NOTE: The Changeset is encoded as follows:
|
|
// - number of store keys (uvarint)
|
|
// - for each store key:
|
|
// -- store key (bytes)
|
|
// -- number of pairs (uvarint)
|
|
// -- for each pair:
|
|
// --- key (bytes)
|
|
// --- remove (1 byte)
|
|
// --- value (bytes)
|
|
func MarshalChangeset(cs *corestore.Changeset) ([]byte, error) {
|
|
var buf bytes.Buffer
|
|
buf.Grow(encodedSize(cs))
|
|
|
|
if err := EncodeUvarint(&buf, uint64(len(cs.Changes))); err != nil {
|
|
return nil, err
|
|
}
|
|
for _, changes := range cs.Changes {
|
|
if err := EncodeBytes(&buf, changes.Actor); err != nil {
|
|
return nil, err
|
|
}
|
|
if err := EncodeUvarint(&buf, uint64(len(changes.StateChanges))); err != nil {
|
|
return nil, err
|
|
}
|
|
for _, pair := range changes.StateChanges {
|
|
if err := EncodeBytes(&buf, pair.Key); err != nil {
|
|
return nil, err
|
|
}
|
|
if pair.Remove {
|
|
if err := EncodeUvarint(&buf, 1); err != nil {
|
|
return nil, err
|
|
}
|
|
} else {
|
|
if err := EncodeUvarint(&buf, 0); err != nil {
|
|
return nil, err
|
|
}
|
|
if err := EncodeBytes(&buf, pair.Value); err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return buf.Bytes(), nil
|
|
}
|
|
|
|
// UnmarshalChangeset decodes the Changeset from the given byte slice.
|
|
func UnmarshalChangeset(cs *corestore.Changeset, buf []byte) error {
|
|
storeCount, n, err := DecodeUvarint(buf)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
buf = buf[n:]
|
|
changes := make([]corestore.StateChanges, storeCount)
|
|
for i := uint64(0); i < storeCount; i++ {
|
|
storeKey, n, err := DecodeBytes(buf)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
buf = buf[n:]
|
|
|
|
pairCount, n, err := DecodeUvarint(buf)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
buf = buf[n:]
|
|
|
|
pairs := make([]corestore.KVPair, pairCount)
|
|
for j := uint64(0); j < pairCount; j++ {
|
|
pairs[j].Key, n, err = DecodeBytes(buf)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
buf = buf[n:]
|
|
|
|
remove, n, err := DecodeUvarint(buf)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
buf = buf[n:]
|
|
if remove == 0 {
|
|
pairs[j].Remove = false
|
|
pairs[j].Value, n, err = DecodeBytes(buf)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
buf = buf[n:]
|
|
} else if remove == 1 {
|
|
pairs[j].Remove = true
|
|
} else {
|
|
return fmt.Errorf("invalid remove flag: %d", remove)
|
|
}
|
|
}
|
|
changes[i] = corestore.StateChanges{Actor: storeKey, StateChanges: pairs}
|
|
}
|
|
cs.Changes = changes
|
|
|
|
return nil
|
|
}
|