Skip to content

Commit bb0b2cf

Browse files
committed
core/vm: enforce duplicate bridge validator checks at Pasteur
1 parent ee3f3c6 commit bb0b2cf

6 files changed

Lines changed: 145 additions & 71 deletions

File tree

core/vm/contracts.go

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -350,10 +350,10 @@ var PrecompiledContractsOsaka = PrecompiledContracts{
350350
common.BytesToAddress([]byte{0x1, 0x00}): &p256Verify{eip7951: true},
351351
}
352352

353-
var PrecompiledContractsMendel = func() PrecompiledContracts {
353+
var PrecompiledContractsPasteur = func() PrecompiledContracts {
354354
precompiles := maps.Clone(PrecompiledContractsOsaka)
355-
precompiles[common.BytesToAddress([]byte{0x66})] = &blsSignatureVerifyMendel{}
356-
precompiles[common.BytesToAddress([]byte{0x67})] = &cometBFTLightBlockValidateHertzMendel{}
355+
precompiles[common.BytesToAddress([]byte{0x66})] = &blsSignatureVerifyPasteur{}
356+
precompiles[common.BytesToAddress([]byte{0x67})] = &cometBFTLightBlockValidatePasteur{}
357357
return precompiles
358358
}()
359359

@@ -364,7 +364,7 @@ var PrecompiledContractsP256Verify = PrecompiledContracts{
364364
}
365365

366366
var (
367-
PrecompiledAddressesMendel []common.Address
367+
PrecompiledAddressesPasteur []common.Address
368368
PrecompiledAddressesOsaka []common.Address
369369
PrecompiledAddressesPrague []common.Address
370370
PrecompiledAddressesHaber []common.Address
@@ -425,8 +425,8 @@ func init() {
425425
for k := range PrecompiledContractsPrague {
426426
PrecompiledAddressesPrague = append(PrecompiledAddressesPrague, k)
427427
}
428-
for k := range PrecompiledContractsMendel {
429-
PrecompiledAddressesMendel = append(PrecompiledAddressesMendel, k)
428+
for k := range PrecompiledContractsPasteur {
429+
PrecompiledAddressesPasteur = append(PrecompiledAddressesPasteur, k)
430430
}
431431
for k := range PrecompiledContractsOsaka {
432432
PrecompiledAddressesOsaka = append(PrecompiledAddressesOsaka, k)
@@ -437,8 +437,8 @@ func activePrecompiledContracts(rules params.Rules) PrecompiledContracts {
437437
switch {
438438
case rules.IsVerkle:
439439
return PrecompiledContractsVerkle
440-
case rules.IsMendel:
441-
return PrecompiledContractsMendel
440+
case rules.IsPasteur:
441+
return PrecompiledContractsPasteur
442442
case rules.IsOsaka:
443443
return PrecompiledContractsOsaka
444444
case rules.IsPrague:
@@ -480,8 +480,8 @@ func ActivePrecompiledContracts(rules params.Rules) PrecompiledContracts {
480480
// ActivePrecompiles returns the precompile addresses enabled with the current configuration.
481481
func ActivePrecompiles(rules params.Rules) []common.Address {
482482
switch {
483-
case rules.IsMendel:
484-
return PrecompiledAddressesMendel
483+
case rules.IsPasteur:
484+
return PrecompiledAddressesPasteur
485485
case rules.IsOsaka:
486486
return PrecompiledAddressesOsaka
487487
case rules.IsPrague:
@@ -1617,7 +1617,7 @@ func (c *bls12381MapG2) Name() string {
16171617
// blsSignatureVerify implements bls signature verification precompile.
16181618
type blsSignatureVerify struct{}
16191619

1620-
type blsSignatureVerifyMendel struct {
1620+
type blsSignatureVerifyPasteur struct {
16211621
blsSignatureVerify
16221622
}
16231623

@@ -1718,12 +1718,12 @@ func (c *blsSignatureVerify) Name() string {
17181718
return "BLS_SIGNATURE_VERIFY"
17191719
}
17201720

1721-
func (c *blsSignatureVerifyMendel) Run(input []byte) ([]byte, error) {
1721+
func (c *blsSignatureVerifyPasteur) Run(input []byte) ([]byte, error) {
17221722
return runBlsSignatureVerify(input, true)
17231723
}
17241724

1725-
func (c *blsSignatureVerifyMendel) Name() string {
1726-
return "BLS_SIGNATURE_VERIFY_MENDEL"
1725+
func (c *blsSignatureVerifyPasteur) Name() string {
1726+
return "BLS_SIGNATURE_VERIFY_PASTEUR"
17271727
}
17281728

17291729
// kzgPointEvaluation implements the EIP-4844 point evaluation precompile.

core/vm/contracts_lightclient.go

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -403,11 +403,7 @@ func (c *cometBFTLightBlockValidate) run(input []byte, isHertz bool, requireUniq
403403
cs *v2.ConsensusState
404404
block *types.LightBlock
405405
)
406-
if requireUniqueValidators {
407-
cs, block, err = v2.DecodeLightBlockValidationInputWithValidation(input)
408-
} else {
409-
cs, block, err = v2.DecodeLightBlockValidationInput(input)
410-
}
406+
cs, block, err = v2.DecodeLightBlockValidationInput(input, requireUniqueValidators)
411407
if err != nil {
412408
return nil, err
413409
}
@@ -446,16 +442,16 @@ func (c *cometBFTLightBlockValidateHertz) Name() string {
446442
return "COMET_BFT_LIGHT_BLOCK_VALIDATE_HERTZ"
447443
}
448444

449-
type cometBFTLightBlockValidateHertzMendel struct {
445+
type cometBFTLightBlockValidatePasteur struct {
450446
cometBFTLightBlockValidate
451447
}
452448

453-
func (c *cometBFTLightBlockValidateHertzMendel) Run(input []byte) (result []byte, err error) {
449+
func (c *cometBFTLightBlockValidatePasteur) Run(input []byte) (result []byte, err error) {
454450
return c.run(input, true, true)
455451
}
456452

457-
func (c *cometBFTLightBlockValidateHertzMendel) Name() string {
458-
return "COMET_BFT_LIGHT_BLOCK_VALIDATE_HERTZ_MENDEL"
453+
func (c *cometBFTLightBlockValidatePasteur) Name() string {
454+
return "COMET_BFT_LIGHT_BLOCK_VALIDATE_PASTEUR"
459455
}
460456

461457
// secp256k1SignatureRecover implemented as a native contract.

core/vm/contracts_lightclient_test.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -378,13 +378,13 @@ func TestCometBFTLightBlockValidateHertz(t *testing.T) {
378378
require.Equal(t, expectOutputStr, hex.EncodeToString(res))
379379
}
380380

381-
func TestCometBFTLightBlockValidateRejectsDuplicateTrustedValidatorsAtMendel(t *testing.T) {
381+
func TestCometBFTLightBlockValidateRejectsDuplicateTrustedValidatorsAtPasteur(t *testing.T) {
382382
inputStr := "000000000000000000000000000000000000000000000000000000000000018c677265656e6669656c645f393030302d3132310000000000000000000000000000000000000000013c350cd55b99dc6c2b7da9bef5410fbfb869fede858e7b95bf7ca294e228bb40e33f6e876d63791ebd05ff617a1b4f4ad1aa2ce65e3c3a9cdfb33e0ffa7e8423000000000098968015154514f68ce65a0d9eecc578c0ab12da0a2a28a0805521b5b7ae56eb3fb24555efbfe59e1622bfe9f7be8c9022e9b3f2442739c1ce870b9adee169afe60f674edd7c86451c5363d89052fde8351895eeea166ce5373c36e31b518ed191d0c599aa0f5b0000000000989680432f6c4908a9aa5f3444421f466b11645235c99b831b2a2de9e504d7ea299e52a202ce529808618eb3bfc0addf13d8c5f2df821d81e18f9bc61583510b322d067d46323b0a572635c06a049c0a2a929e3c8184a50cf6a8b95708c25834ade456f399015a0000000000989680864cb9828254d712f8e59b164fc6a9402dc4e6c59065e38cff24f5323c8c5da888a0f97e5ee4ba1e11b0674b0a0d06204c1dfa247c370cd4be3e799fc4f6f48d977ac7ca0aeb060adb030a02080b1213677265656e6669656c645f393030302d3132311802220c08b2d7f3a10610e8d2adb3032a480a20ec6ecb5db4ffb17fabe40c60ca7b8441e9c5d77585d0831186f3c37aa16e9c15122408011220a2ab9e1eb9ea52812f413526e424b326aff2f258a56e00d690db9f805b60fe7e32200f40aeff672e8309b7b0aefbb9a1ae3d4299b5c445b7d54e8ff398488467f0053a20e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b85542203c350cd55b99dc6c2b7da9bef5410fbfb869fede858e7b95bf7ca294e228bb404a203c350cd55b99dc6c2b7da9bef5410fbfb869fede858e7b95bf7ca294e228bb405220294d8fbd0b94b767a7eba9840f299a3586da7fe6b5dead3b7eecba193c400f935a20bc50557c12d7392b0d07d75df0b61232d48f86a74fdea6d1485d9be6317d268c6220e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b8556a20e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b85572146699336aa109d1beab3946198c8e59f3b2cbd92f7a4065e3cd89e315ca39d87dee92835b98f8b8ec0861d6d9bb2c60156df5d375b3ceb1fbe71af6a244907d62548a694165caa660fec7a9b4e7b9198191361c71be0b128a0308021a480a20726abd0fdbfb6f779b0483e6e4b4b6f12241f6ea2bf374233ab1a316692b6415122408011220159f10ff15a8b58fc67a92ffd7f33c8cd407d4ce81b04ca79177dfd00ca19a67226808021214050cff76cc632760ba9db796c046004c900967361a0c08b3d7f3a10610808cadba03224080713027ffb776a702d78fd0406205c629ba473e1f8d6af646190f6eb9262cd67d69be90d10e597b91e06d7298eb6fa4b8f1eb7752ebf352a1f51560294548042268080212146699336aa109d1beab3946198c8e59f3b2cbd92f1a0c08b3d7f3a10610b087c1c00322405e2ddb70acfe4904438be3d9f4206c0ace905ac4fc306a42cfc9e86268950a0fbfd6ec5f526d3e41a3ef52bf9f9f358e3cb4c3feac76c762fa3651c1244fe004226808021214c55765fd2d0570e869f6ac22e7f2916a35ea300d1a0c08b3d7f3a10610f0b3d492032240ca17898bd22232fc9374e1188636ee321a396444a5b1a79f7628e4a11f265734b2ab50caf21e8092c55d701248e82b2f011426cb35ba22043b497a6b4661930612a0050aa8010a14050cff76cc632760ba9db796c046004c9009673612220a20e33f6e876d63791ebd05ff617a1b4f4ad1aa2ce65e3c3a9cdfb33e0ffa7e84231880ade2042080a6bbf6ffffffffff012a30a0805521b5b7ae56eb3fb24555efbfe59e1622bfe9f7be8c9022e9b3f2442739c1ce870b9adee169afe60f674edd7c86321415154514f68ce65a0d9eecc578c0ab12da0a2a283a14ee7a2a6a44d427f6949eeb8f12ea9fbb2501da880aa2010a146699336aa109d1beab3946198c8e59f3b2cbd92f12220a20451c5363d89052fde8351895eeea166ce5373c36e31b518ed191d0c599aa0f5b1880ade2042080ade2042a30831b2a2de9e504d7ea299e52a202ce529808618eb3bfc0addf13d8c5f2df821d81e18f9bc61583510b322d067d46323b3214432f6c4908a9aa5f3444421f466b11645235c99b3a14a0a7769429468054e19059af4867da0a495567e50aa2010a14c55765fd2d0570e869f6ac22e7f2916a35ea300d12220a200a572635c06a049c0a2a929e3c8184a50cf6a8b95708c25834ade456f399015a1880ade2042080ade2042a309065e38cff24f5323c8c5da888a0f97e5ee4ba1e11b0674b0a0d06204c1dfa247c370cd4be3e799fc4f6f48d977ac7ca3214864cb9828254d712f8e59b164fc6a9402dc4e6c53a143139916d97df0c589312b89950b6ab9795f34d1a12a8010a14050cff76cc632760ba9db796c046004c9009673612220a20e33f6e876d63791ebd05ff617a1b4f4ad1aa2ce65e3c3a9cdfb33e0ffa7e84231880ade2042080a6bbf6ffffffffff012a30a0805521b5b7ae56eb3fb24555efbfe59e1622bfe9f7be8c9022e9b3f2442739c1ce870b9adee169afe60f674edd7c86321415154514f68ce65a0d9eecc578c0ab12da0a2a283a14ee7a2a6a44d427f6949eeb8f12ea9fbb2501da88"
383383

384384
input, err := hex.DecodeString(inputStr)
385385
require.NoError(t, err)
386386

387-
cs, block, err := v2.DecodeLightBlockValidationInput(input)
387+
cs, block, err := v2.DecodeLightBlockValidationInput(input, false)
388388
require.NoError(t, err)
389389

390390
duplicate := cs.ValidatorSet.Validators[0].Copy()
@@ -402,8 +402,8 @@ func TestCometBFTLightBlockValidateRejectsDuplicateTrustedValidatorsAtMendel(t *
402402
mutatedInput = append(mutatedInput, csBytes...)
403403
mutatedInput = append(mutatedInput, blockBytes...)
404404

405-
mendelPrecompile := ActivePrecompiledContracts(params.Rules{IsOsaka: true, IsMendel: true})[common.BytesToAddress([]byte{0x67})]
406-
_, err = mendelPrecompile.Run(mutatedInput)
405+
pasteurPrecompile := ActivePrecompiledContracts(params.Rules{IsOsaka: true, IsMendel: true, IsPasteur: true})[common.BytesToAddress([]byte{0x67})]
406+
_, err = pasteurPrecompile.Run(mutatedInput)
407407
require.ErrorContains(t, err, "duplicate validator")
408408

409409
legacyPrecompile := ActivePrecompiledContracts(params.Rules{IsOsaka: true})[common.BytesToAddress([]byte{0x67})]

core/vm/contracts_test.go

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -356,8 +356,8 @@ func TestPrecompiledBLS12381MapG2(t *testing.T) { testJson("blsMapG2", "f10
356356

357357
func TestPrecompiledBlsSignatureVerify(t *testing.T) { testJson("blsSignatureVerify", "66", t) }
358358

359-
func TestActivePrecompiledContractsUsesMendelVariants(t *testing.T) {
360-
rules := params.Rules{IsOsaka: true, IsMendel: true}
359+
func TestActivePrecompiledContractsUsesPasteurVariants(t *testing.T) {
360+
rules := params.Rules{IsOsaka: true, IsMendel: true, IsPasteur: true}
361361
precompiles := ActivePrecompiledContracts(rules)
362362

363363
requirePrecompile := func(addr byte) PrecompiledContract {
@@ -370,15 +370,15 @@ func TestActivePrecompiledContractsUsesMendelVariants(t *testing.T) {
370370
return precompile
371371
}
372372

373-
if got := requirePrecompile(0x66).Name(); got != "BLS_SIGNATURE_VERIFY_MENDEL" {
374-
t.Fatalf("unexpected Mendel 0x66 precompile: %s", got)
373+
if got := requirePrecompile(0x66).Name(); got != "BLS_SIGNATURE_VERIFY_PASTEUR" {
374+
t.Fatalf("unexpected Pasteur 0x66 precompile: %s", got)
375375
}
376-
if got := requirePrecompile(0x67).Name(); got != "COMET_BFT_LIGHT_BLOCK_VALIDATE_HERTZ_MENDEL" {
377-
t.Fatalf("unexpected Mendel 0x67 precompile: %s", got)
376+
if got := requirePrecompile(0x67).Name(); got != "COMET_BFT_LIGHT_BLOCK_VALIDATE_PASTEUR" {
377+
t.Fatalf("unexpected Pasteur 0x67 precompile: %s", got)
378378
}
379379
}
380380

381-
func TestBlsSignatureVerifyRejectsDuplicatePubKeysAtMendel(t *testing.T) {
381+
func TestBlsSignatureVerifyRejectsDuplicatePubKeysAtPasteur(t *testing.T) {
382382
msg := [32]byte{'d', 'u', 'p'}
383383

384384
sk1, err := bls.RandKey()
@@ -395,20 +395,20 @@ func TestBlsSignatureVerifyRejectsDuplicatePubKeysAtMendel(t *testing.T) {
395395
sig1 := sk1.Sign(msg[:])
396396
dupAgg := bls.AggregateSignatures([]blscommon.Signature{sig1, sig1, sig1})
397397

398-
mendelRules := params.Rules{IsOsaka: true, IsMendel: true}
399-
mendelVerify := ActivePrecompiledContracts(mendelRules)[common.BytesToAddress([]byte{0x66})]
398+
pasteurRules := params.Rules{IsOsaka: true, IsMendel: true, IsPasteur: true}
399+
pasteurVerify := ActivePrecompiledContracts(pasteurRules)[common.BytesToAddress([]byte{0x66})]
400400

401401
input := append(msg[:], dupAgg.Marshal()...)
402402
input = append(input, pk1.Marshal()...)
403403
input = append(input, pk1.Marshal()...)
404404
input = append(input, pk1.Marshal()...)
405405

406-
res, err := mendelVerify.Run(input)
406+
res, err := pasteurVerify.Run(input)
407407
if err != nil {
408408
t.Fatalf("unexpected error: %v", err)
409409
}
410410
if len(res) != 0 {
411-
t.Fatalf("expected Mendel duplicate-pubkey verification to fail, got %x", res)
411+
t.Fatalf("expected Pasteur duplicate-pubkey verification to fail, got %x", res)
412412
}
413413

414414
osakaRules := params.Rules{IsOsaka: true}
@@ -418,14 +418,14 @@ func TestBlsSignatureVerifyRejectsDuplicatePubKeysAtMendel(t *testing.T) {
418418
t.Fatalf("unexpected Osaka error: %v", err)
419419
}
420420
if len(legacyRes) == 0 {
421-
t.Fatalf("expected pre-Mendel duplicate-pubkey verification to succeed")
421+
t.Fatalf("expected pre-Pasteur duplicate-pubkey verification to succeed")
422422
}
423423

424424
mixedInput := append(msg[:], dupAgg.Marshal()...)
425425
mixedInput = append(mixedInput, pk1.Marshal()...)
426426
mixedInput = append(mixedInput, pk2.Marshal()...)
427427
mixedInput = append(mixedInput, pk2.Marshal()...)
428-
mixedRes, err := mendelVerify.Run(mixedInput)
428+
mixedRes, err := pasteurVerify.Run(mixedInput)
429429
if err != nil {
430430
t.Fatalf("unexpected mixed-key error: %v", err)
431431
}

core/vm/lightclient/v2/lightclient.go

Lines changed: 34 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -37,18 +37,28 @@ type ConsensusState struct {
3737
}
3838

3939
type validatorDuplicateTracker struct {
40-
field string
41-
seen map[string]int
40+
field string
41+
seen map[string]int
42+
ignoreZero bool
4243
}
4344

44-
func newValidatorDuplicateTracker(field string, size int) validatorDuplicateTracker {
45+
func newValidatorDuplicateTracker(field string, size int, ignoreZero bool) validatorDuplicateTracker {
4546
return validatorDuplicateTracker{
46-
field: field,
47-
seen: make(map[string]int, size),
47+
field: field,
48+
seen: make(map[string]int, size),
49+
ignoreZero: ignoreZero,
4850
}
4951
}
5052

5153
func (t validatorDuplicateTracker) check(idx int, value []byte) error {
54+
if t.ignoreZero {
55+
// Optional bridge fields may be omitted in source validators or zero-filled by
56+
// fixed-width decoding. Both forms mean "unset" and should not count as duplicates.
57+
if len(value) == 0 || isZeroBytes(value) {
58+
return nil
59+
}
60+
}
61+
5262
key := string(value)
5363
if firstIdx, ok := t.seen[key]; ok {
5464
return fmt.Errorf("duplicate validator %s #%d and #%d: %X", t.field, firstIdx, idx, value)
@@ -57,16 +67,28 @@ func (t validatorDuplicateTracker) check(idx int, value []byte) error {
5767
return nil
5868
}
5969

70+
func isZeroBytes(value []byte) bool {
71+
if len(value) == 0 {
72+
return false
73+
}
74+
for _, b := range value {
75+
if b != 0 {
76+
return false
77+
}
78+
}
79+
return true
80+
}
81+
6082
func validateUniqueValidatorSet(validatorSet *types.ValidatorSet) error {
6183
if validatorSet == nil {
6284
return nil
6385
}
6486

6587
size := len(validatorSet.Validators)
66-
addresses := newValidatorDuplicateTracker("address", size)
67-
pubKeys := newValidatorDuplicateTracker("pubkey", size)
68-
blsKeys := newValidatorDuplicateTracker("bls key", size)
69-
relayerAddresses := newValidatorDuplicateTracker("relayer address", size)
88+
addresses := newValidatorDuplicateTracker("address", size, false)
89+
pubKeys := newValidatorDuplicateTracker("pubkey", size, false)
90+
blsKeys := newValidatorDuplicateTracker("bls key", size, true)
91+
relayerAddresses := newValidatorDuplicateTracker("relayer address", size, true)
7092

7193
for idx, validator := range validatorSet.Validators {
7294
if validator == nil || validator.PubKey == nil {
@@ -190,7 +212,7 @@ func (cs *ConsensusState) ApplyLightBlock(block *types.LightBlock, isHertz bool)
190212
// input:
191213
// | chainID | height | nextValidatorSetHash | [{validator pubkey, voting power, relayer address, relayer bls pubkey}] |
192214
// | 32 bytes | 8 bytes | 32 bytes | [{32 bytes, 8 bytes, 20 bytes, 48 bytes}] |
193-
func decodeConsensusState(input []byte, requireUniqueValidators bool) (ConsensusState, error) {
215+
func DecodeConsensusState(input []byte, requireUniqueValidators bool) (ConsensusState, error) {
194216
minimumLength := chainIDLength + heightLength + validatorSetHashLength
195217
inputLen := uint64(len(input))
196218
if inputLen <= minimumLength || (inputLen-minimumLength)%singleValidatorBytesLength != 0 {
@@ -254,18 +276,10 @@ func decodeConsensusState(input []byte, requireUniqueValidators bool) (Consensus
254276
return consensusState, nil
255277
}
256278

257-
func DecodeConsensusState(input []byte) (ConsensusState, error) {
258-
return decodeConsensusState(input, false)
259-
}
260-
261-
func DecodeConsensusStateWithValidation(input []byte) (ConsensusState, error) {
262-
return decodeConsensusState(input, true)
263-
}
264-
265279
// input:
266280
// consensus state length | consensus state | light block |
267281
// 32 bytes | | |
268-
func decodeLightBlockValidationInput(input []byte, requireUniqueValidators bool) (*ConsensusState, *types.LightBlock, error) {
282+
func DecodeLightBlockValidationInput(input []byte, requireUniqueValidators bool) (*ConsensusState, *types.LightBlock, error) {
269283
if uint64(len(input)) <= consensusStateLengthBytesLength {
270284
return nil, nil, errors.New("invalid input")
271285
}
@@ -280,7 +294,7 @@ func decodeLightBlockValidationInput(input []byte, requireUniqueValidators bool)
280294
return nil, nil, fmt.Errorf("expected payload size %d, actual size: %d", consensusStateLengthBytesLength+csLen, len(input))
281295
}
282296

283-
cs, err := decodeConsensusState(input[consensusStateLengthBytesLength:consensusStateLengthBytesLength+csLen], requireUniqueValidators)
297+
cs, err := DecodeConsensusState(input[consensusStateLengthBytesLength:consensusStateLengthBytesLength+csLen], requireUniqueValidators)
284298
if err != nil {
285299
return nil, nil, err
286300
}
@@ -303,14 +317,6 @@ func decodeLightBlockValidationInput(input []byte, requireUniqueValidators bool)
303317
return &cs, block, nil
304318
}
305319

306-
func DecodeLightBlockValidationInput(input []byte) (*ConsensusState, *types.LightBlock, error) {
307-
return decodeLightBlockValidationInput(input, false)
308-
}
309-
310-
func DecodeLightBlockValidationInputWithValidation(input []byte) (*ConsensusState, *types.LightBlock, error) {
311-
return decodeLightBlockValidationInput(input, true)
312-
}
313-
314320
// output:
315321
// | validatorSetChanged | empty | consensusStateBytesLength | new consensusState |
316322
// | 1 byte | 23 bytes | 8 bytes | |

0 commit comments

Comments
 (0)