neo-go/pkg/core/mpt/helpers.go
2020-06-03 13:33:44 +03:00

86 lines
1.9 KiB
Go

package mpt
import (
"github.com/nspcc-dev/neo-go/pkg/core/state"
"github.com/nspcc-dev/neo-go/pkg/io"
"github.com/nspcc-dev/neo-go/pkg/util"
)
// lcp returns longest common prefix of a and b.
// Note: it does no allocations.
func lcp(a, b []byte) []byte {
if len(a) < len(b) {
return lcp(b, a)
}
var i int
for i = 0; i < len(b); i++ {
if a[i] != b[i] {
break
}
}
return a[:i]
}
// copySlice is a helper for copying slice if needed.
func copySlice(a []byte) []byte {
b := make([]byte, len(a))
copy(b, a)
return b
}
// toNibbles mangles path by splitting every byte into 2 containing low- and high- 4-byte part.
func toNibbles(path []byte) []byte {
result := make([]byte, len(path)*2)
for i := range path {
result[i*2] = path[i] >> 4
result[i*2+1] = path[i] & 0x0F
}
return result
}
// ToNeoStorageKey converts storage key to C# neo node's format.
// Key is expected to be at least 20 bytes in length.
// our format: script hash in BE + key
// neo format: script hash in LE + key with 0 between every 16 bytes, padded to len 16.
func ToNeoStorageKey(key []byte) []byte {
const groupSize = 16
var nkey []byte
for i := util.Uint160Size - 1; i >= 0; i-- {
nkey = append(nkey, key[i])
}
key = key[util.Uint160Size:]
index := 0
remain := len(key)
for remain >= groupSize {
nkey = append(nkey, key[index:index+groupSize]...)
nkey = append(nkey, 0)
index += groupSize
remain -= groupSize
}
if remain > 0 {
nkey = append(nkey, key[index:]...)
}
padding := groupSize - remain
for i := 0; i < padding; i++ {
nkey = append(nkey, 0)
}
return append(nkey, byte(padding))
}
// ToNeoStorageValue serializes si to a C# neo node's format.
// It has additional version (0x00) byte at the beginning.
func ToNeoStorageValue(si *state.StorageItem) []byte {
const version = 0
buf := io.NewBufBinWriter()
buf.BinWriter.WriteB(version)
si.EncodeBinary(buf.BinWriter)
return buf.Bytes()
}