mirror of
https://github.com/nspcc-dev/neo-go.git
synced 2024-12-13 15:45:01 +00:00
mpt: implement NEO storage key conversion
This commit is contained in:
parent
103c45850a
commit
314430be1d
3 changed files with 68 additions and 29 deletions
|
@ -8,6 +8,7 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
|
"github.com/nspcc-dev/neo-go/pkg/core/mpt"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/core/storage"
|
"github.com/nspcc-dev/neo-go/pkg/core/storage"
|
||||||
"github.com/nspcc-dev/neo-go/pkg/util"
|
"github.com/nspcc-dev/neo-go/pkg/util"
|
||||||
)
|
)
|
||||||
|
@ -33,35 +34,7 @@ func toNeoStorageKey(key []byte) []byte {
|
||||||
if len(key) < util.Uint160Size {
|
if len(key) < util.Uint160Size {
|
||||||
panic("invalid key in storage")
|
panic("invalid key in storage")
|
||||||
}
|
}
|
||||||
|
return mpt.ToNeoStorageKey(key)
|
||||||
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 >= 16 {
|
|
||||||
nkey = append(nkey, key[index:index+16]...)
|
|
||||||
nkey = append(nkey, 0)
|
|
||||||
index += 16
|
|
||||||
remain -= 16
|
|
||||||
}
|
|
||||||
|
|
||||||
if remain > 0 {
|
|
||||||
nkey = append(nkey, key[index:]...)
|
|
||||||
}
|
|
||||||
|
|
||||||
padding := 16 - remain
|
|
||||||
for i := 0; i < padding; i++ {
|
|
||||||
nkey = append(nkey, 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
nkey = append(nkey, byte(padding))
|
|
||||||
|
|
||||||
return nkey
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// batchToMap converts batch to a map so that JSON is compatible
|
// batchToMap converts batch to a map so that JSON is compatible
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package mpt
|
package mpt
|
||||||
|
|
||||||
|
import "github.com/nspcc-dev/neo-go/pkg/util"
|
||||||
|
|
||||||
// lcp returns longest common prefix of a and b.
|
// lcp returns longest common prefix of a and b.
|
||||||
// Note: it does no allocations.
|
// Note: it does no allocations.
|
||||||
func lcp(a, b []byte) []byte {
|
func lcp(a, b []byte) []byte {
|
||||||
|
@ -33,3 +35,37 @@ func toNibbles(path []byte) []byte {
|
||||||
}
|
}
|
||||||
return result
|
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))
|
||||||
|
}
|
||||||
|
|
30
pkg/core/mpt/helpers_test.go
Normal file
30
pkg/core/mpt/helpers_test.go
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
package mpt
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/hex"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestToNeoStorageKey(t *testing.T) {
|
||||||
|
testCases := []struct{ key, res string }{
|
||||||
|
{
|
||||||
|
"0102030405060708091011121314151617181920",
|
||||||
|
"20191817161514131211100908070605040302010000000000000000000000000000000010",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"010203040506070809101112131415161718192021222324",
|
||||||
|
"2019181716151413121110090807060504030201212223240000000000000000000000000c",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"0102030405060708091011121314151617181920212223242526272829303132333435363738",
|
||||||
|
"20191817161514131211100908070605040302012122232425262728293031323334353600373800000000000000000000000000000e",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tc := range testCases {
|
||||||
|
key, _ := hex.DecodeString(tc.key)
|
||||||
|
res, _ := hex.DecodeString(tc.res)
|
||||||
|
require.Equal(t, res, ToNeoStorageKey(key))
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue