forked from TrueCloudLab/neoneo-go
core: add MaxKeyLength restrictions to MPT's operations
This commit is contained in:
parent
b4e24bef14
commit
c8120a139d
3 changed files with 16 additions and 2 deletions
|
@ -40,12 +40,13 @@ func prepareMPTCompat() *Trie {
|
||||||
// There are some differences, though:
|
// There are some differences, though:
|
||||||
// 1. In our implementation delete is silent, i.e. we do not return an error is the key is missing or empty.
|
// 1. In our implementation delete is silent, i.e. we do not return an error is the key is missing or empty.
|
||||||
// However, we do return error when contents of hash node are missing from the store
|
// However, we do return error when contents of hash node are missing from the store
|
||||||
|
// (corresponds to exception in C# implementation). However, if the key is too big, an error is returned
|
||||||
// (corresponds to exception in C# implementation).
|
// (corresponds to exception in C# implementation).
|
||||||
// 2. In our implementation put returns error if something goes wrong, while C# implementation throws
|
// 2. In our implementation put returns error if something goes wrong, while C# implementation throws
|
||||||
// an exception and returns nothing.
|
// an exception and returns nothing.
|
||||||
// 3. In our implementation get does not immediately return error in case of an empty key. An error is returned
|
// 3. In our implementation get does not immediately return error in case of an empty key. An error is returned
|
||||||
// only if value is missing from the storage. C# implementation checks that key is not empty and throws an error
|
// only if value is missing from the storage. C# implementation checks that key is not empty and throws an error
|
||||||
// otherwice.
|
// otherwice. However, if the key is too big, an error is returned (corresponds to exception in C# implementation).
|
||||||
func TestCompatibility(t *testing.T) {
|
func TestCompatibility(t *testing.T) {
|
||||||
mainTrie := prepareMPTCompat()
|
mainTrie := prepareMPTCompat()
|
||||||
|
|
||||||
|
@ -59,6 +60,7 @@ func TestCompatibility(t *testing.T) {
|
||||||
tr.testHas(t, []byte{0xac, 0x01, 0x00}, nil)
|
tr.testHas(t, []byte{0xac, 0x01, 0x00}, nil)
|
||||||
tr.testHas(t, []byte{0xac, 0x99, 0x10}, nil)
|
tr.testHas(t, []byte{0xac, 0x99, 0x10}, nil)
|
||||||
tr.testHas(t, []byte{0xac, 0xf1}, nil)
|
tr.testHas(t, []byte{0xac, 0xf1}, nil)
|
||||||
|
tr.testHas(t, make([]byte, MaxKeyLength), nil)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("TryGetResolve", func(t *testing.T) {
|
t.Run("TryGetResolve", func(t *testing.T) {
|
||||||
|
@ -96,6 +98,7 @@ func TestCompatibility(t *testing.T) {
|
||||||
require.NoError(t, tr.Delete([]byte{0xac, 0x20}))
|
require.NoError(t, tr.Delete([]byte{0xac, 0x20}))
|
||||||
|
|
||||||
require.Error(t, tr.Delete([]byte{0xac, 0xf1})) // error for can't resolve
|
require.Error(t, tr.Delete([]byte{0xac, 0xf1})) // error for can't resolve
|
||||||
|
require.Error(t, tr.Delete(make([]byte, MaxKeyLength+1))) // error for too big key
|
||||||
|
|
||||||
// In our implementation missing keys are ignored.
|
// In our implementation missing keys are ignored.
|
||||||
require.NoError(t, tr.Delete([]byte{0xac}))
|
require.NoError(t, tr.Delete([]byte{0xac}))
|
||||||
|
@ -202,6 +205,7 @@ func TestCompatibility(t *testing.T) {
|
||||||
testGetProof(t, tr, nil, 0)
|
testGetProof(t, tr, nil, 0)
|
||||||
testGetProof(t, tr, []byte{0xac, 0x01, 0x00}, 0)
|
testGetProof(t, tr, []byte{0xac, 0x01, 0x00}, 0)
|
||||||
testGetProof(t, tr, []byte{0xac, 0xf1}, 0)
|
testGetProof(t, tr, []byte{0xac, 0xf1}, 0)
|
||||||
|
testGetProof(t, tr, make([]byte, MaxKeyLength), 0)
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("VerifyProof", func(t *testing.T) {
|
t.Run("VerifyProof", func(t *testing.T) {
|
||||||
|
|
|
@ -2,6 +2,7 @@ package mpt
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"errors"
|
||||||
|
|
||||||
"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/crypto/hash"
|
"github.com/nspcc-dev/neo-go/pkg/crypto/hash"
|
||||||
|
@ -13,6 +14,9 @@ import (
|
||||||
// Proof consist of serialized nodes occurring on path from the root to the leaf of key.
|
// Proof consist of serialized nodes occurring on path from the root to the leaf of key.
|
||||||
func (t *Trie) GetProof(key []byte) ([][]byte, error) {
|
func (t *Trie) GetProof(key []byte) ([][]byte, error) {
|
||||||
var proof [][]byte
|
var proof [][]byte
|
||||||
|
if len(key) > MaxKeyLength {
|
||||||
|
return nil, errors.New("key is too big")
|
||||||
|
}
|
||||||
path := toNibbles(key)
|
path := toNibbles(key)
|
||||||
r, err := t.getProof(t.root, path, &proof)
|
r, err := t.getProof(t.root, path, &proof)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -49,6 +49,9 @@ func NewTrie(root Node, enableRefCount bool, store *storage.MemCachedStore) *Tri
|
||||||
|
|
||||||
// Get returns value for the provided key in t.
|
// Get returns value for the provided key in t.
|
||||||
func (t *Trie) Get(key []byte) ([]byte, error) {
|
func (t *Trie) Get(key []byte) ([]byte, error) {
|
||||||
|
if len(key) > MaxKeyLength {
|
||||||
|
return nil, errors.New("key is too big")
|
||||||
|
}
|
||||||
path := toNibbles(key)
|
path := toNibbles(key)
|
||||||
r, bs, err := t.getWithPath(t.root, path)
|
r, bs, err := t.getWithPath(t.root, path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -235,6 +238,9 @@ func (t *Trie) putIntoNode(curr Node, path []byte, val Node) (Node, error) {
|
||||||
// Delete removes key from trie.
|
// Delete removes key from trie.
|
||||||
// It returns no error on missing key.
|
// It returns no error on missing key.
|
||||||
func (t *Trie) Delete(key []byte) error {
|
func (t *Trie) Delete(key []byte) error {
|
||||||
|
if len(key) > MaxKeyLength {
|
||||||
|
return errors.New("key is too big")
|
||||||
|
}
|
||||||
path := toNibbles(key)
|
path := toNibbles(key)
|
||||||
r, err := t.deleteFromNode(t.root, path)
|
r, err := t.deleteFromNode(t.root, path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
Loading…
Reference in a new issue