Skip to content

Commit c42d85b

Browse files
author
Darioush Jalali
authored
warp: use bitset in predicate results to encode indexes of failures instead of success (#942)
* warp: use 1 in result bitset for fails * t.Fatal -> require.NoError
1 parent e2874b0 commit c42d85b

File tree

4 files changed

+92
-57
lines changed

4 files changed

+92
-57
lines changed

x/warp/config.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -197,12 +197,13 @@ func (c *Config) verifyPredicate(predicateContext *precompileconfig.PredicateCon
197197
return c.verifyWarpMessage(predicateContext, warpMessage)
198198
}
199199

200-
// VerifyPredicate verifies the predicate represents a valid signed and properly formatted Avalanche Warp Message.
200+
// VerifyPredicate computes indices of predicates that failed verification as a bitset then returns the result
201+
// as a byte slice.
201202
func (c *Config) VerifyPredicate(predicateContext *precompileconfig.PredicateContext, predicates [][]byte) []byte {
202203
resultBitSet := set.NewBits()
203204

204205
for predicateIndex, predicateBytes := range predicates {
205-
if c.verifyPredicate(predicateContext, predicateBytes) {
206+
if !c.verifyPredicate(predicateContext, predicateBytes) {
206207
resultBitSet.Add(predicateIndex)
207208
}
208209
}

x/warp/contract_test.go

Lines changed: 78 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,8 @@ func TestGetVerifiedWarpMessage(t *testing.T) {
167167
warpMessagePredicateBytes := predicate.PackPredicate(warpMessage.Bytes())
168168
getVerifiedWarpMsg, err := PackGetVerifiedWarpMessage(0)
169169
require.NoError(t, err)
170+
noFailures := set.NewBits().Bytes()
171+
require.Len(t, noFailures, 0)
170172

171173
tests := map[string]testutils.PrecompileTest{
172174
"get message success": {
@@ -176,7 +178,7 @@ func TestGetVerifiedWarpMessage(t *testing.T) {
176178
state.SetPredicateStorageSlots(ContractAddress, [][]byte{warpMessagePredicateBytes})
177179
},
178180
SetupBlockContext: func(mbc *contract.MockBlockContext) {
179-
mbc.EXPECT().GetPredicateResults(common.Hash{}, ContractAddress).Return(set.NewBits(0).Bytes())
181+
mbc.EXPECT().GetPredicateResults(common.Hash{}, ContractAddress).Return(noFailures)
180182
},
181183
SuppliedGas: GetVerifiedWarpMessageBaseCost + GasCostPerWarpMessageBytes*uint64(len(warpMessagePredicateBytes)),
182184
ReadOnly: false,
@@ -199,16 +201,14 @@ func TestGetVerifiedWarpMessage(t *testing.T) {
199201
Caller: callerAddr,
200202
InputFn: func(t testing.TB) []byte {
201203
input, err := PackGetVerifiedWarpMessage(1)
202-
if err != nil {
203-
t.Fatal(err)
204-
}
204+
require.NoError(t, err)
205205
return input
206206
},
207207
BeforeHook: func(t testing.TB, state contract.StateDB) {
208208
state.SetPredicateStorageSlots(ContractAddress, [][]byte{warpMessagePredicateBytes})
209209
},
210210
SetupBlockContext: func(mbc *contract.MockBlockContext) {
211-
mbc.EXPECT().GetPredicateResults(common.Hash{}, ContractAddress).Return(set.NewBits().Bytes())
211+
mbc.EXPECT().GetPredicateResults(common.Hash{}, ContractAddress).Return(noFailures)
212212
},
213213
SuppliedGas: GetVerifiedWarpMessageBaseCost,
214214
ReadOnly: false,
@@ -224,16 +224,14 @@ func TestGetVerifiedWarpMessage(t *testing.T) {
224224
Caller: callerAddr,
225225
InputFn: func(t testing.TB) []byte {
226226
input, err := PackGetVerifiedWarpMessage(1)
227-
if err != nil {
228-
t.Fatal(err)
229-
}
227+
require.NoError(t, err)
230228
return input
231229
},
232230
BeforeHook: func(t testing.TB, state contract.StateDB) {
233231
state.SetPredicateStorageSlots(ContractAddress, [][]byte{{}, warpMessagePredicateBytes})
234232
},
235233
SetupBlockContext: func(mbc *contract.MockBlockContext) {
236-
mbc.EXPECT().GetPredicateResults(common.Hash{}, ContractAddress).Return(set.NewBits(1).Bytes())
234+
mbc.EXPECT().GetPredicateResults(common.Hash{}, ContractAddress).Return(set.NewBits(0).Bytes())
237235
},
238236
SuppliedGas: GetVerifiedWarpMessageBaseCost + GasCostPerWarpMessageBytes*uint64(len(warpMessagePredicateBytes)),
239237
ReadOnly: false,
@@ -252,11 +250,34 @@ func TestGetVerifiedWarpMessage(t *testing.T) {
252250
return res
253251
}(),
254252
},
253+
"get message failure non-zero index": {
254+
Caller: callerAddr,
255+
InputFn: func(t testing.TB) []byte {
256+
input, err := PackGetVerifiedWarpMessage(1)
257+
require.NoError(t, err)
258+
return input
259+
},
260+
BeforeHook: func(t testing.TB, state contract.StateDB) {
261+
state.SetPredicateStorageSlots(ContractAddress, [][]byte{{}, warpMessagePredicateBytes})
262+
},
263+
SetupBlockContext: func(mbc *contract.MockBlockContext) {
264+
mbc.EXPECT().GetPredicateResults(common.Hash{}, ContractAddress).Return(set.NewBits(0, 1).Bytes())
265+
},
266+
SuppliedGas: GetVerifiedWarpMessageBaseCost,
267+
ReadOnly: false,
268+
ExpectedRes: func() []byte {
269+
res, err := PackGetVerifiedWarpMessageOutput(GetVerifiedWarpMessageOutput{Valid: false})
270+
if err != nil {
271+
panic(err)
272+
}
273+
return res
274+
}(),
275+
},
255276
"get non-existent message": {
256277
Caller: callerAddr,
257278
InputFn: func(t testing.TB) []byte { return getVerifiedWarpMsg },
258279
SetupBlockContext: func(mbc *contract.MockBlockContext) {
259-
mbc.EXPECT().GetPredicateResults(common.Hash{}, ContractAddress).Return(set.NewBits().Bytes())
280+
mbc.EXPECT().GetPredicateResults(common.Hash{}, ContractAddress).Return(noFailures)
260281
},
261282
SuppliedGas: GetVerifiedWarpMessageBaseCost,
262283
ReadOnly: false,
@@ -275,7 +296,7 @@ func TestGetVerifiedWarpMessage(t *testing.T) {
275296
state.SetPredicateStorageSlots(ContractAddress, [][]byte{warpMessagePredicateBytes})
276297
},
277298
SetupBlockContext: func(mbc *contract.MockBlockContext) {
278-
mbc.EXPECT().GetPredicateResults(common.Hash{}, ContractAddress).Return(set.NewBits(0).Bytes())
299+
mbc.EXPECT().GetPredicateResults(common.Hash{}, ContractAddress).Return(noFailures)
279300
},
280301
SuppliedGas: GetVerifiedWarpMessageBaseCost + GasCostPerWarpMessageBytes*uint64(len(warpMessagePredicateBytes)),
281302
ReadOnly: true,
@@ -298,7 +319,7 @@ func TestGetVerifiedWarpMessage(t *testing.T) {
298319
Caller: callerAddr,
299320
InputFn: func(t testing.TB) []byte { return getVerifiedWarpMsg },
300321
SetupBlockContext: func(mbc *contract.MockBlockContext) {
301-
mbc.EXPECT().GetPredicateResults(common.Hash{}, ContractAddress).Return(set.NewBits().Bytes())
322+
mbc.EXPECT().GetPredicateResults(common.Hash{}, ContractAddress).Return(noFailures)
302323
},
303324
SuppliedGas: GetVerifiedWarpMessageBaseCost,
304325
ReadOnly: true,
@@ -327,7 +348,7 @@ func TestGetVerifiedWarpMessage(t *testing.T) {
327348
state.SetPredicateStorageSlots(ContractAddress, [][]byte{warpMessagePredicateBytes})
328349
},
329350
SetupBlockContext: func(mbc *contract.MockBlockContext) {
330-
mbc.EXPECT().GetPredicateResults(common.Hash{}, ContractAddress).Return(set.NewBits(0).Bytes())
351+
mbc.EXPECT().GetPredicateResults(common.Hash{}, ContractAddress).Return(noFailures)
331352
},
332353
SuppliedGas: GetVerifiedWarpMessageBaseCost + GasCostPerWarpMessageBytes*uint64(len(warpMessagePredicateBytes)) - 1,
333354
ReadOnly: false,
@@ -340,7 +361,7 @@ func TestGetVerifiedWarpMessage(t *testing.T) {
340361
state.SetPredicateStorageSlots(ContractAddress, [][]byte{warpMessage.Bytes()})
341362
},
342363
SetupBlockContext: func(mbc *contract.MockBlockContext) {
343-
mbc.EXPECT().GetPredicateResults(common.Hash{}, ContractAddress).Return(set.NewBits(0).Bytes())
364+
mbc.EXPECT().GetPredicateResults(common.Hash{}, ContractAddress).Return(noFailures)
344365
},
345366
SuppliedGas: GetVerifiedWarpMessageBaseCost + GasCostPerWarpMessageBytes*uint64(len(warpMessage.Bytes())),
346367
ReadOnly: false,
@@ -353,7 +374,7 @@ func TestGetVerifiedWarpMessage(t *testing.T) {
353374
state.SetPredicateStorageSlots(ContractAddress, [][]byte{predicate.PackPredicate([]byte{1, 2, 3})})
354375
},
355376
SetupBlockContext: func(mbc *contract.MockBlockContext) {
356-
mbc.EXPECT().GetPredicateResults(common.Hash{}, ContractAddress).Return(set.NewBits(0).Bytes())
377+
mbc.EXPECT().GetPredicateResults(common.Hash{}, ContractAddress).Return(noFailures)
357378
},
358379
SuppliedGas: GetVerifiedWarpMessageBaseCost + GasCostPerWarpMessageBytes*uint64(32),
359380
ReadOnly: false,
@@ -371,7 +392,7 @@ func TestGetVerifiedWarpMessage(t *testing.T) {
371392
state.SetPredicateStorageSlots(ContractAddress, [][]byte{predicate.PackPredicate(warpMessage.Bytes())})
372393
},
373394
SetupBlockContext: func(mbc *contract.MockBlockContext) {
374-
mbc.EXPECT().GetPredicateResults(common.Hash{}, ContractAddress).Return(set.NewBits(0).Bytes())
395+
mbc.EXPECT().GetPredicateResults(common.Hash{}, ContractAddress).Return(noFailures)
375396
},
376397
SuppliedGas: GetVerifiedWarpMessageBaseCost + GasCostPerWarpMessageBytes*uint64(160),
377398
ReadOnly: false,
@@ -390,9 +411,7 @@ func TestGetVerifiedWarpMessage(t *testing.T) {
390411
Caller: callerAddr,
391412
InputFn: func(t testing.TB) []byte {
392413
res, err := PackGetVerifiedWarpMessage(math.MaxInt32 + 1)
393-
if err != nil {
394-
t.Fatal(err)
395-
}
414+
require.NoError(t, err)
396415
return res
397416
},
398417
SuppliedGas: GetVerifiedWarpMessageBaseCost,
@@ -403,9 +422,7 @@ func TestGetVerifiedWarpMessage(t *testing.T) {
403422
Caller: callerAddr,
404423
InputFn: func(t testing.TB) []byte {
405424
res, err := PackGetVerifiedWarpMessage(1)
406-
if err != nil {
407-
t.Fatal(err)
408-
}
425+
require.NoError(t, err)
409426
return res[:len(res)-2]
410427
},
411428
SuppliedGas: GetVerifiedWarpMessageBaseCost,
@@ -431,6 +448,8 @@ func TestGetVerifiedWarpBlockHash(t *testing.T) {
431448
warpMessagePredicateBytes := predicate.PackPredicate(warpMessage.Bytes())
432449
getVerifiedWarpBlockHash, err := PackGetVerifiedWarpBlockHash(0)
433450
require.NoError(t, err)
451+
noFailures := set.NewBits().Bytes()
452+
require.Len(t, noFailures, 0)
434453

435454
tests := map[string]testutils.PrecompileTest{
436455
"get message success": {
@@ -440,7 +459,7 @@ func TestGetVerifiedWarpBlockHash(t *testing.T) {
440459
state.SetPredicateStorageSlots(ContractAddress, [][]byte{warpMessagePredicateBytes})
441460
},
442461
SetupBlockContext: func(mbc *contract.MockBlockContext) {
443-
mbc.EXPECT().GetPredicateResults(common.Hash{}, ContractAddress).Return(set.NewBits(0).Bytes())
462+
mbc.EXPECT().GetPredicateResults(common.Hash{}, ContractAddress).Return(noFailures)
444463
},
445464
SuppliedGas: GetVerifiedWarpMessageBaseCost + GasCostPerWarpMessageBytes*uint64(len(warpMessagePredicateBytes)),
446465
ReadOnly: false,
@@ -462,16 +481,14 @@ func TestGetVerifiedWarpBlockHash(t *testing.T) {
462481
Caller: callerAddr,
463482
InputFn: func(t testing.TB) []byte {
464483
input, err := PackGetVerifiedWarpBlockHash(1)
465-
if err != nil {
466-
t.Fatal(err)
467-
}
484+
require.NoError(t, err)
468485
return input
469486
},
470487
BeforeHook: func(t testing.TB, state contract.StateDB) {
471488
state.SetPredicateStorageSlots(ContractAddress, [][]byte{warpMessagePredicateBytes})
472489
},
473490
SetupBlockContext: func(mbc *contract.MockBlockContext) {
474-
mbc.EXPECT().GetPredicateResults(common.Hash{}, ContractAddress).Return(set.NewBits().Bytes())
491+
mbc.EXPECT().GetPredicateResults(common.Hash{}, ContractAddress).Return(noFailures)
475492
},
476493
SuppliedGas: GetVerifiedWarpMessageBaseCost,
477494
ReadOnly: false,
@@ -487,16 +504,14 @@ func TestGetVerifiedWarpBlockHash(t *testing.T) {
487504
Caller: callerAddr,
488505
InputFn: func(t testing.TB) []byte {
489506
input, err := PackGetVerifiedWarpBlockHash(1)
490-
if err != nil {
491-
t.Fatal(err)
492-
}
507+
require.NoError(t, err)
493508
return input
494509
},
495510
BeforeHook: func(t testing.TB, state contract.StateDB) {
496511
state.SetPredicateStorageSlots(ContractAddress, [][]byte{{}, warpMessagePredicateBytes})
497512
},
498513
SetupBlockContext: func(mbc *contract.MockBlockContext) {
499-
mbc.EXPECT().GetPredicateResults(common.Hash{}, ContractAddress).Return(set.NewBits(1).Bytes())
514+
mbc.EXPECT().GetPredicateResults(common.Hash{}, ContractAddress).Return(set.NewBits(0).Bytes())
500515
},
501516
SuppliedGas: GetVerifiedWarpMessageBaseCost + GasCostPerWarpMessageBytes*uint64(len(warpMessagePredicateBytes)),
502517
ReadOnly: false,
@@ -514,11 +529,34 @@ func TestGetVerifiedWarpBlockHash(t *testing.T) {
514529
return res
515530
}(),
516531
},
532+
"get message failure non-zero index": {
533+
Caller: callerAddr,
534+
InputFn: func(t testing.TB) []byte {
535+
input, err := PackGetVerifiedWarpBlockHash(1)
536+
require.NoError(t, err)
537+
return input
538+
},
539+
BeforeHook: func(t testing.TB, state contract.StateDB) {
540+
state.SetPredicateStorageSlots(ContractAddress, [][]byte{{}, warpMessagePredicateBytes})
541+
},
542+
SetupBlockContext: func(mbc *contract.MockBlockContext) {
543+
mbc.EXPECT().GetPredicateResults(common.Hash{}, ContractAddress).Return(set.NewBits(0, 1).Bytes())
544+
},
545+
SuppliedGas: GetVerifiedWarpMessageBaseCost,
546+
ReadOnly: false,
547+
ExpectedRes: func() []byte {
548+
res, err := PackGetVerifiedWarpBlockHashOutput(GetVerifiedWarpBlockHashOutput{Valid: false})
549+
if err != nil {
550+
panic(err)
551+
}
552+
return res
553+
}(),
554+
},
517555
"get non-existent message": {
518556
Caller: callerAddr,
519557
InputFn: func(t testing.TB) []byte { return getVerifiedWarpBlockHash },
520558
SetupBlockContext: func(mbc *contract.MockBlockContext) {
521-
mbc.EXPECT().GetPredicateResults(common.Hash{}, ContractAddress).Return(set.NewBits().Bytes())
559+
mbc.EXPECT().GetPredicateResults(common.Hash{}, ContractAddress).Return(noFailures)
522560
},
523561
SuppliedGas: GetVerifiedWarpMessageBaseCost,
524562
ReadOnly: false,
@@ -537,7 +575,7 @@ func TestGetVerifiedWarpBlockHash(t *testing.T) {
537575
state.SetPredicateStorageSlots(ContractAddress, [][]byte{warpMessagePredicateBytes})
538576
},
539577
SetupBlockContext: func(mbc *contract.MockBlockContext) {
540-
mbc.EXPECT().GetPredicateResults(common.Hash{}, ContractAddress).Return(set.NewBits(0).Bytes())
578+
mbc.EXPECT().GetPredicateResults(common.Hash{}, ContractAddress).Return(noFailures)
541579
},
542580
SuppliedGas: GetVerifiedWarpMessageBaseCost + GasCostPerWarpMessageBytes*uint64(len(warpMessagePredicateBytes)),
543581
ReadOnly: true,
@@ -559,7 +597,7 @@ func TestGetVerifiedWarpBlockHash(t *testing.T) {
559597
Caller: callerAddr,
560598
InputFn: func(t testing.TB) []byte { return getVerifiedWarpBlockHash },
561599
SetupBlockContext: func(mbc *contract.MockBlockContext) {
562-
mbc.EXPECT().GetPredicateResults(common.Hash{}, ContractAddress).Return(set.NewBits().Bytes())
600+
mbc.EXPECT().GetPredicateResults(common.Hash{}, ContractAddress).Return(noFailures)
563601
},
564602
SuppliedGas: GetVerifiedWarpMessageBaseCost,
565603
ReadOnly: true,
@@ -588,7 +626,7 @@ func TestGetVerifiedWarpBlockHash(t *testing.T) {
588626
state.SetPredicateStorageSlots(ContractAddress, [][]byte{warpMessagePredicateBytes})
589627
},
590628
SetupBlockContext: func(mbc *contract.MockBlockContext) {
591-
mbc.EXPECT().GetPredicateResults(common.Hash{}, ContractAddress).Return(set.NewBits(0).Bytes())
629+
mbc.EXPECT().GetPredicateResults(common.Hash{}, ContractAddress).Return(noFailures)
592630
},
593631
SuppliedGas: GetVerifiedWarpMessageBaseCost + GasCostPerWarpMessageBytes*uint64(len(warpMessagePredicateBytes)) - 1,
594632
ReadOnly: false,
@@ -601,7 +639,7 @@ func TestGetVerifiedWarpBlockHash(t *testing.T) {
601639
state.SetPredicateStorageSlots(ContractAddress, [][]byte{warpMessage.Bytes()})
602640
},
603641
SetupBlockContext: func(mbc *contract.MockBlockContext) {
604-
mbc.EXPECT().GetPredicateResults(common.Hash{}, ContractAddress).Return(set.NewBits(0).Bytes())
642+
mbc.EXPECT().GetPredicateResults(common.Hash{}, ContractAddress).Return(noFailures)
605643
},
606644
SuppliedGas: GetVerifiedWarpMessageBaseCost + GasCostPerWarpMessageBytes*uint64(len(warpMessage.Bytes())),
607645
ReadOnly: false,
@@ -614,7 +652,7 @@ func TestGetVerifiedWarpBlockHash(t *testing.T) {
614652
state.SetPredicateStorageSlots(ContractAddress, [][]byte{predicate.PackPredicate([]byte{1, 2, 3})})
615653
},
616654
SetupBlockContext: func(mbc *contract.MockBlockContext) {
617-
mbc.EXPECT().GetPredicateResults(common.Hash{}, ContractAddress).Return(set.NewBits(0).Bytes())
655+
mbc.EXPECT().GetPredicateResults(common.Hash{}, ContractAddress).Return(noFailures)
618656
},
619657
SuppliedGas: GetVerifiedWarpMessageBaseCost + GasCostPerWarpMessageBytes*uint64(32),
620658
ReadOnly: false,
@@ -632,7 +670,7 @@ func TestGetVerifiedWarpBlockHash(t *testing.T) {
632670
state.SetPredicateStorageSlots(ContractAddress, [][]byte{predicate.PackPredicate(warpMessage.Bytes())})
633671
},
634672
SetupBlockContext: func(mbc *contract.MockBlockContext) {
635-
mbc.EXPECT().GetPredicateResults(common.Hash{}, ContractAddress).Return(set.NewBits(0).Bytes())
673+
mbc.EXPECT().GetPredicateResults(common.Hash{}, ContractAddress).Return(noFailures)
636674
},
637675
SuppliedGas: GetVerifiedWarpMessageBaseCost + GasCostPerWarpMessageBytes*uint64(160),
638676
ReadOnly: false,
@@ -651,9 +689,7 @@ func TestGetVerifiedWarpBlockHash(t *testing.T) {
651689
Caller: callerAddr,
652690
InputFn: func(t testing.TB) []byte {
653691
res, err := PackGetVerifiedWarpBlockHash(math.MaxInt32 + 1)
654-
if err != nil {
655-
t.Fatal(err)
656-
}
692+
require.NoError(t, err)
657693
return res
658694
},
659695
SuppliedGas: GetVerifiedWarpMessageBaseCost,
@@ -664,9 +700,7 @@ func TestGetVerifiedWarpBlockHash(t *testing.T) {
664700
Caller: callerAddr,
665701
InputFn: func(t testing.TB) []byte {
666702
res, err := PackGetVerifiedWarpBlockHash(1)
667-
if err != nil {
668-
t.Fatal(err)
669-
}
703+
require.NoError(t, err)
670704
return res[:len(res)-2]
671705
},
672706
SuppliedGas: GetVerifiedWarpMessageBaseCost,

x/warp/contract_warp_handler.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ func handleWarpMessage(accessibleState contract.AccessibleState, input []byte, s
6262
state := accessibleState.GetStateDB()
6363
predicateBytes, exists := state.GetPredicateStorageSlots(ContractAddress, warpIndex)
6464
predicateResults := accessibleState.GetBlockContext().GetPredicateResults(state.GetTxHash(), ContractAddress)
65-
valid := exists && set.BitsFromBytes(predicateResults).Contains(warpIndex)
65+
valid := exists && !set.BitsFromBytes(predicateResults).Contains(warpIndex)
6666
if !valid {
6767
return handler.packFailed(), remainingGas, nil
6868
}

0 commit comments

Comments
 (0)