mirror of
https://github.com/nspcc-dev/neo-go.git
synced 2024-12-23 13:41:37 +00:00
mpt: disallow empty keys
This is not a problem in practice, as all keys are prefixed by a contract ID. However in theory it can lead to a different state root after new portion of changes thus this fix.
This commit is contained in:
parent
5b1f6207de
commit
e833d333fe
3 changed files with 16 additions and 15 deletions
|
@ -70,26 +70,26 @@ func TestTrie_PutBatchLeaf(t *testing.T) {
|
|||
prepareLeaf := func(t *testing.T) (*Trie, *Trie) {
|
||||
tr1 := NewTrie(new(HashNode), false, newTestStore())
|
||||
tr2 := NewTrie(new(HashNode), false, newTestStore())
|
||||
require.NoError(t, tr1.Put([]byte{}, []byte("value")))
|
||||
require.NoError(t, tr2.Put([]byte{}, []byte("value")))
|
||||
require.NoError(t, tr1.Put([]byte{0}, []byte("value")))
|
||||
require.NoError(t, tr2.Put([]byte{0}, []byte("value")))
|
||||
return tr1, tr2
|
||||
}
|
||||
|
||||
t.Run("remove", func(t *testing.T) {
|
||||
tr1, tr2 := prepareLeaf(t)
|
||||
var ps = pairs{{[]byte{}, nil}}
|
||||
var ps = pairs{{[]byte{0}, nil}}
|
||||
testPut(t, ps, tr1, tr2)
|
||||
})
|
||||
t.Run("replace", func(t *testing.T) {
|
||||
tr1, tr2 := prepareLeaf(t)
|
||||
var ps = pairs{{[]byte{}, []byte("replace")}}
|
||||
var ps = pairs{{[]byte{0}, []byte("replace")}}
|
||||
testPut(t, ps, tr1, tr2)
|
||||
})
|
||||
t.Run("remove and replace", func(t *testing.T) {
|
||||
tr1, tr2 := prepareLeaf(t)
|
||||
var ps = pairs{
|
||||
{[]byte{}, nil},
|
||||
{[]byte{2}, []byte("replace2")},
|
||||
{[]byte{0}, nil},
|
||||
{[]byte{0, 2}, []byte("replace2")},
|
||||
}
|
||||
testPut(t, ps, tr1, tr2)
|
||||
})
|
||||
|
@ -122,7 +122,7 @@ func TestTrie_PutBatchExtension(t *testing.T) {
|
|||
t.Run("add to next with leaf", func(t *testing.T) {
|
||||
tr1, tr2 := prepareExtension(t)
|
||||
var ps = pairs{
|
||||
{[]byte{}, []byte("value3")},
|
||||
{[]byte{0}, []byte("value3")},
|
||||
{[]byte{1, 2, 3}, []byte("value2")},
|
||||
}
|
||||
testPut(t, ps, tr1, tr2)
|
||||
|
@ -232,7 +232,7 @@ func TestTrie_PutBatchEmpty(t *testing.T) {
|
|||
tr1 := NewTrie(new(HashNode), false, newTestStore())
|
||||
tr2 := NewTrie(new(HashNode), false, newTestStore())
|
||||
var ps = pairs{
|
||||
{[]byte{}, []byte("value0")},
|
||||
{[]byte{0}, []byte("value0")},
|
||||
{[]byte{1}, []byte("value1")},
|
||||
{[]byte{3}, []byte("value3")},
|
||||
}
|
||||
|
@ -240,7 +240,7 @@ func TestTrie_PutBatchEmpty(t *testing.T) {
|
|||
})
|
||||
t.Run("incomplete", func(t *testing.T) {
|
||||
var ps = pairs{
|
||||
{[]byte{}, []byte("replace0")},
|
||||
{[]byte{0}, []byte("replace0")},
|
||||
{[]byte{1}, []byte("replace1")},
|
||||
{[]byte{2}, nil},
|
||||
{[]byte{3}, []byte("replace3")},
|
||||
|
|
|
@ -97,7 +97,9 @@ func (t *Trie) getWithPath(curr Node, path []byte) (Node, []byte, error) {
|
|||
|
||||
// Put puts key-value pair in t.
|
||||
func (t *Trie) Put(key, value []byte) error {
|
||||
if len(key) > MaxKeyLength {
|
||||
if len(key) == 0 {
|
||||
return errors.New("key is empty")
|
||||
} else if len(key) > MaxKeyLength {
|
||||
return errors.New("key is too big")
|
||||
} else if len(value) > MaxValueLength {
|
||||
return errors.New("value is too big")
|
||||
|
|
|
@ -85,10 +85,6 @@ func TestTrie_PutIntoBranchNode(t *testing.T) {
|
|||
b.Children[0x8] = NewHashNode(random.Uint256())
|
||||
tr := NewTrie(b, false, newTestStore())
|
||||
|
||||
// next
|
||||
require.NoError(t, tr.Put([]byte{}, []byte{0x12, 0x34}))
|
||||
tr.testHas(t, []byte{}, []byte{0x12, 0x34})
|
||||
|
||||
// empty hash node child
|
||||
require.NoError(t, tr.Put([]byte{0x66}, []byte{0x56}))
|
||||
tr.testHas(t, []byte{0x66}, []byte{0x56})
|
||||
|
@ -160,6 +156,9 @@ func TestTrie_PutInvalid(t *testing.T) {
|
|||
tr := NewTrie(nil, false, newTestStore())
|
||||
key, value := []byte("key"), []byte("value")
|
||||
|
||||
// empty key
|
||||
require.Error(t, tr.Put(nil, value))
|
||||
|
||||
// big key
|
||||
require.Error(t, tr.Put(make([]byte, maxPathLength+1), value))
|
||||
|
||||
|
@ -271,7 +270,7 @@ func TestTrie_Get(t *testing.T) {
|
|||
|
||||
func TestTrie_Flush(t *testing.T) {
|
||||
pairs := map[string][]byte{
|
||||
"": []byte("value0"),
|
||||
"x": []byte("value0"),
|
||||
"key1": []byte("value1"),
|
||||
"key2": []byte("value2"),
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue