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() }