Skip to content

Commit 78bb4fe

Browse files
authored
Merge branch 'dev' into e2e-duplicate-nodes
2 parents 36567e8 + 8232de0 commit 78bb4fe

File tree

4 files changed

+154
-75
lines changed

4 files changed

+154
-75
lines changed

vms/proposervm/vm.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -399,7 +399,7 @@ func (vm *VM) repair(ctx context.Context) error {
399399
return vm.repairAcceptedChainByIteration(ctx)
400400
}
401401

402-
switch vm.hVM.VerifyHeightIndex(ctx) {
402+
switch err := vm.hVM.VerifyHeightIndex(ctx); err {
403403
case nil:
404404
// InnerVM height index is complete. We can immediately verify
405405
// and repair this VM height index.
@@ -414,7 +414,7 @@ func (vm *VM) repair(ctx context.Context) error {
414414
}
415415
case block.ErrIndexIncomplete:
416416
default:
417-
return nil
417+
return err
418418
}
419419

420420
// innerVM height index is incomplete. Sync vm and innerVM chains first.
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
// Copyright (C) 2019-2023, Ava Labs, Inc. All rights reserved.
2+
// See the file LICENSE for licensing terms.
3+
4+
package proposervm
5+
6+
import (
7+
"context"
8+
"crypto"
9+
"errors"
10+
"testing"
11+
"time"
12+
13+
"github.com/stretchr/testify/require"
14+
15+
"github.com/ava-labs/avalanchego/database/manager"
16+
"github.com/ava-labs/avalanchego/snow"
17+
"github.com/ava-labs/avalanchego/snow/engine/common"
18+
"github.com/ava-labs/avalanchego/snow/engine/snowman/block"
19+
"github.com/ava-labs/avalanchego/version"
20+
)
21+
22+
func TestProposerVMInitializeShouldFailIfInnerVMCantVerifyItsHeightIndex(t *testing.T) {
23+
require := require.New(t)
24+
25+
innerVM := &fullVM{
26+
TestVM: &block.TestVM{
27+
TestVM: common.TestVM{
28+
T: t,
29+
},
30+
},
31+
TestHeightIndexedVM: &block.TestHeightIndexedVM{
32+
T: t,
33+
},
34+
}
35+
36+
// let innerVM fail verifying its height index with
37+
// a non-special error (like block.ErrIndexIncomplete)
38+
customError := errors.New("custom error")
39+
innerVM.VerifyHeightIndexF = func(_ context.Context) error {
40+
return customError
41+
}
42+
43+
innerVM.InitializeF = func(context.Context, *snow.Context, manager.Manager,
44+
[]byte, []byte, []byte, chan<- common.Message,
45+
[]*common.Fx, common.AppSender,
46+
) error {
47+
return nil
48+
}
49+
50+
proVM := New(
51+
innerVM,
52+
time.Time{},
53+
0,
54+
DefaultMinBlockDelay,
55+
pTestCert.PrivateKey.(crypto.Signer),
56+
pTestCert.Leaf,
57+
)
58+
defer func() {
59+
// avoids leaking goroutines
60+
require.NoError(proVM.Shutdown(context.Background()))
61+
}()
62+
63+
ctx := snow.DefaultContextTest()
64+
dummyDBManager := manager.NewMemDB(version.Semantic1_0_0)
65+
dummyDBManager = dummyDBManager.NewPrefixDBManager([]byte{})
66+
initialState := []byte("genesis state")
67+
68+
err := proVM.Initialize(
69+
context.Background(),
70+
ctx,
71+
dummyDBManager,
72+
initialState,
73+
nil,
74+
nil,
75+
nil,
76+
nil,
77+
nil,
78+
)
79+
require.ErrorIs(customError, err)
80+
}

x/merkledb/codec.go

Lines changed: 70 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,14 @@ const (
2525
minByteSliceLen = minVarIntLen
2626
minDBNodeLen = minMaybeByteSliceLen + minVarIntLen
2727
minChildLen = minVarIntLen + minSerializedPathLen + ids.IDLen
28+
29+
estimatedKeyLen = 64
30+
estimatedValueLen = 64
31+
estimatedCompressedPathLen = 8
32+
// Child index, child compressed path, child ID
33+
estimatedNodeChildLen = minVarIntLen + estimatedCompressedPathLen + ids.IDLen
34+
// Child index, child ID
35+
hashValuesChildLen = minVarIntLen + ids.IDLen
2836
)
2937

3038
var (
@@ -33,7 +41,6 @@ var (
3341
trueBytes = []byte{trueByte}
3442
falseBytes = []byte{falseByte}
3543

36-
errDecodeNil = errors.New("can't decode nil")
3744
errNegativeNumChildren = errors.New("number of children is negative")
3845
errTooManyChildren = fmt.Errorf("length of children list is larger than branching factor of %d", NodeBranchFactor)
3946
errChildIndexTooLarge = fmt.Errorf("invalid child index. Must be less than branching factor of %d", NodeBranchFactor)
@@ -61,6 +68,7 @@ type encoder interface {
6168
}
6269

6370
type decoder interface {
71+
// Assumes [n] is non-nil.
6472
decodeDBNode(bytes []byte, n *dbNode) error
6573
}
6674

@@ -81,26 +89,37 @@ type codecImpl struct {
8189
}
8290

8391
func (c *codecImpl) encodeDBNode(n *dbNode) []byte {
84-
buf := &bytes.Buffer{}
92+
var (
93+
numChildren = len(n.children)
94+
// Estimate size of [n] to prevent memory allocations
95+
estimatedLen = estimatedValueLen + minVarIntLen + estimatedNodeChildLen*numChildren
96+
buf = bytes.NewBuffer(make([]byte, 0, estimatedLen))
97+
)
98+
8599
c.encodeMaybeByteSlice(buf, n.value)
86-
childrenLength := len(n.children)
87-
c.encodeInt(buf, childrenLength)
100+
c.encodeInt(buf, numChildren)
101+
// Note we insert children in order of increasing index
102+
// for determinism.
88103
for index := byte(0); index < NodeBranchFactor; index++ {
89104
if entry, ok := n.children[index]; ok {
90105
c.encodeInt(buf, int(index))
91106
path := entry.compressedPath.Serialize()
92-
c.encodeSerializedPath(path, buf)
107+
c.encodeSerializedPath(buf, path)
93108
_, _ = buf.Write(entry.id[:])
94109
}
95110
}
96111
return buf.Bytes()
97112
}
98113

99114
func (c *codecImpl) encodeHashValues(hv *hashValues) []byte {
100-
buf := &bytes.Buffer{}
115+
var (
116+
numChildren = len(hv.Children)
117+
// Estimate size [hv] to prevent memory allocations
118+
estimatedLen = minVarIntLen + numChildren*hashValuesChildLen + estimatedValueLen + estimatedKeyLen
119+
buf = bytes.NewBuffer(make([]byte, 0, estimatedLen))
120+
)
101121

102-
length := len(hv.Children)
103-
c.encodeInt(buf, length)
122+
c.encodeInt(buf, numChildren)
104123

105124
// ensure that the order of entries is consistent
106125
for index := byte(0); index < NodeBranchFactor; index++ {
@@ -110,33 +129,28 @@ func (c *codecImpl) encodeHashValues(hv *hashValues) []byte {
110129
}
111130
}
112131
c.encodeMaybeByteSlice(buf, hv.Value)
113-
c.encodeSerializedPath(hv.Key, buf)
132+
c.encodeSerializedPath(buf, hv.Key)
114133

115134
return buf.Bytes()
116135
}
117136

118137
func (c *codecImpl) decodeDBNode(b []byte, n *dbNode) error {
119-
if n == nil {
120-
return errDecodeNil
121-
}
122138
if minDBNodeLen > len(b) {
123139
return io.ErrUnexpectedEOF
124140
}
125141

126-
var (
127-
src = bytes.NewReader(b)
128-
err error
129-
)
142+
src := bytes.NewReader(b)
130143

131-
if n.value, err = c.decodeMaybeByteSlice(src); err != nil {
144+
value, err := c.decodeMaybeByteSlice(src)
145+
if err != nil {
132146
return err
133147
}
148+
n.value = value
134149

135150
numChildren, err := c.decodeInt(src)
136-
if err != nil {
137-
return err
138-
}
139151
switch {
152+
case err != nil:
153+
return err
140154
case numChildren < 0:
141155
return errNegativeNumChildren
142156
case numChildren > NodeBranchFactor:
@@ -148,21 +162,21 @@ func (c *codecImpl) decodeDBNode(b []byte, n *dbNode) error {
148162
n.children = make(map[byte]child, NodeBranchFactor)
149163
previousChild := -1
150164
for i := 0; i < numChildren; i++ {
151-
var index int
152-
if index, err = c.decodeInt(src); err != nil {
165+
index, err := c.decodeInt(src)
166+
if err != nil {
153167
return err
154168
}
155-
if index <= previousChild || index > NodeBranchFactor-1 {
169+
if index <= previousChild || index >= NodeBranchFactor {
156170
return errChildIndexTooLarge
157171
}
158172
previousChild = index
159173

160-
var compressedPath SerializedPath
161-
if compressedPath, err = c.decodeSerializedPath(src); err != nil {
174+
compressedPath, err := c.decodeSerializedPath(src)
175+
if err != nil {
162176
return err
163177
}
164-
var childID ids.ID
165-
if childID, err = c.decodeID(src); err != nil {
178+
childID, err := c.decodeID(src)
179+
if err != nil {
166180
return err
167181
}
168182
n.children[byte(index)] = child{
@@ -173,7 +187,7 @@ func (c *codecImpl) decodeDBNode(b []byte, n *dbNode) error {
173187
if src.Len() != 0 {
174188
return errExtraSpace
175189
}
176-
return err
190+
return nil
177191
}
178192

179193
func (*codecImpl) encodeBool(dst *bytes.Buffer, value bool) {
@@ -186,16 +200,14 @@ func (*codecImpl) encodeBool(dst *bytes.Buffer, value bool) {
186200

187201
func (*codecImpl) decodeBool(src *bytes.Reader) (bool, error) {
188202
boolByte, err := src.ReadByte()
189-
if err == io.EOF {
203+
switch {
204+
case err == io.EOF:
190205
return false, io.ErrUnexpectedEOF
191-
}
192-
if err != nil {
206+
case err != nil:
193207
return false, err
194-
}
195-
switch boolByte {
196-
case trueByte:
208+
case boolByte == trueByte:
197209
return true, nil
198-
case falseByte:
210+
case boolByte == falseByte:
199211
return false, nil
200212
default:
201213
return false, errInvalidBool
@@ -249,8 +261,9 @@ func (c *codecImpl) encodeInt64(dst *bytes.Buffer, value int64) {
249261
}
250262

251263
func (c *codecImpl) encodeMaybeByteSlice(dst *bytes.Buffer, maybeValue maybe.Maybe[[]byte]) {
252-
c.encodeBool(dst, !maybeValue.IsNothing())
253-
if maybeValue.HasValue() {
264+
hasValue := maybeValue.HasValue()
265+
c.encodeBool(dst, hasValue)
266+
if hasValue {
254267
c.encodeByteSlice(dst, maybeValue.Value())
255268
}
256269
}
@@ -277,19 +290,12 @@ func (c *codecImpl) decodeByteSlice(src *bytes.Reader) ([]byte, error) {
277290
return nil, io.ErrUnexpectedEOF
278291
}
279292

280-
var (
281-
length int
282-
err error
283-
result []byte
284-
)
285-
if length, err = c.decodeInt(src); err != nil {
286-
if err == io.EOF {
287-
return nil, io.ErrUnexpectedEOF
288-
}
289-
return nil, err
290-
}
291-
293+
length, err := c.decodeInt(src)
292294
switch {
295+
case err == io.EOF:
296+
return nil, io.ErrUnexpectedEOF
297+
case err != nil:
298+
return nil, err
293299
case length < 0:
294300
return nil, errNegativeSliceLength
295301
case length == 0:
@@ -298,14 +304,12 @@ func (c *codecImpl) decodeByteSlice(src *bytes.Reader) ([]byte, error) {
298304
return nil, io.ErrUnexpectedEOF
299305
}
300306

301-
result = make([]byte, length)
302-
if _, err := io.ReadFull(src, result); err != nil {
303-
if err == io.EOF {
304-
err = io.ErrUnexpectedEOF
305-
}
306-
return nil, err
307+
result := make([]byte, length)
308+
_, err = io.ReadFull(src, result)
309+
if err == io.EOF {
310+
err = io.ErrUnexpectedEOF
307311
}
308-
return result, nil
312+
return result, err
309313
}
310314

311315
func (c *codecImpl) encodeByteSlice(dst *bytes.Buffer, value []byte) {
@@ -321,16 +325,14 @@ func (*codecImpl) decodeID(src *bytes.Reader) (ids.ID, error) {
321325
}
322326

323327
var id ids.ID
324-
if _, err := io.ReadFull(src, id[:]); err != nil {
325-
if err == io.EOF {
326-
err = io.ErrUnexpectedEOF
327-
}
328-
return id, err
328+
_, err := io.ReadFull(src, id[:])
329+
if err == io.EOF {
330+
err = io.ErrUnexpectedEOF
329331
}
330-
return id, nil
332+
return id, err
331333
}
332334

333-
func (c *codecImpl) encodeSerializedPath(s SerializedPath, dst *bytes.Buffer) {
335+
func (c *codecImpl) encodeSerializedPath(dst *bytes.Buffer, s SerializedPath) {
334336
c.encodeInt(dst, s.NibbleLength)
335337
_, _ = dst.Write(s.Value)
336338
}
@@ -345,30 +347,30 @@ func (c *codecImpl) decodeSerializedPath(src *bytes.Reader) (SerializedPath, err
345347
err error
346348
)
347349
if result.NibbleLength, err = c.decodeInt(src); err != nil {
348-
return result, err
350+
return SerializedPath{}, err
349351
}
350352
if result.NibbleLength < 0 {
351-
return result, errNegativeNibbleLength
353+
return SerializedPath{}, errNegativeNibbleLength
352354
}
353355
pathBytesLen := result.NibbleLength >> 1
354356
hasOddLen := result.hasOddLength()
355357
if hasOddLen {
356358
pathBytesLen++
357359
}
358360
if pathBytesLen > src.Len() {
359-
return result, io.ErrUnexpectedEOF
361+
return SerializedPath{}, io.ErrUnexpectedEOF
360362
}
361363
result.Value = make([]byte, pathBytesLen)
362364
if _, err := io.ReadFull(src, result.Value); err != nil {
363365
if err == io.EOF {
364366
err = io.ErrUnexpectedEOF
365367
}
366-
return result, err
368+
return SerializedPath{}, err
367369
}
368370
if hasOddLen {
369371
paddedNibble := result.Value[pathBytesLen-1] & 0x0F
370372
if paddedNibble != 0 {
371-
return result, errNonZeroNibblePadding
373+
return SerializedPath{}, errNonZeroNibblePadding
372374
}
373375
}
374376
return result, nil

0 commit comments

Comments
 (0)