Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BEP-221: implement cometBFT light block validation #1463

Merged
merged 7 commits into from
Apr 18, 2023
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/workflows/unit-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ jobs:

- name: Unit Test
env:
CGO_CFLAGS: "-O -D__BLST_PORTABLE__"
CGO_CFLAGS_ALLOW: "-O -D__BLST_PORTABLE__"
ANDROID_HOME: "" # Skip android test
run: |
go mod download
Expand Down
1 change: 1 addition & 0 deletions core/vm/contracts.go
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,7 @@ var PrecompiledContractsBoneh = map[common.Address]PrecompiledContract{
common.BytesToAddress([]byte{100}): &tmHeaderValidate{},
common.BytesToAddress([]byte{101}): &iavlMerkleProofValidatePlanck{},
common.BytesToAddress([]byte{102}): &blsSignatureVerify{},
common.BytesToAddress([]byte{103}): &cometBFTLightBlockValidate{},
}

// PrecompiledContractsBLS contains the set of pre-compiled Ethereum
Expand Down
66 changes: 51 additions & 15 deletions core/vm/contracts_lightclient.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ import (
"github.com/tendermint/tendermint/crypto/merkle"
cmn "github.com/tendermint/tendermint/libs/common"

"github.com/ethereum/go-ethereum/core/vm/lightclient"
v1 "github.com/ethereum/go-ethereum/core/vm/lightclient/v1"
v2 "github.com/ethereum/go-ethereum/core/vm/lightclient/v2"
"github.com/ethereum/go-ethereum/params"
)

Expand All @@ -26,7 +27,7 @@ const (
// input:
// consensus state length | consensus state | tendermint header |
// 32 bytes | | |
func decodeTendermintHeaderValidationInput(input []byte) (*lightclient.ConsensusState, *lightclient.Header, error) {
func decodeTendermintHeaderValidationInput(input []byte) (*v1.ConsensusState, *v1.Header, error) {
csLen := binary.BigEndian.Uint64(input[consensusStateLengthBytesLength-uint64TypeLength : consensusStateLengthBytesLength])

if consensusStateLengthBytesLength+csLen < consensusStateLengthBytesLength {
Expand All @@ -37,19 +38,20 @@ func decodeTendermintHeaderValidationInput(input []byte) (*lightclient.Consensus
return nil, nil, fmt.Errorf("expected payload size %d, actual size: %d", consensusStateLengthBytesLength+csLen, len(input))
}

cs, err := lightclient.DecodeConsensusState(input[consensusStateLengthBytesLength : consensusStateLengthBytesLength+csLen])
cs, err := v1.DecodeConsensusState(input[consensusStateLengthBytesLength : consensusStateLengthBytesLength+csLen])
if err != nil {
return nil, nil, err
}
header, err := lightclient.DecodeHeader(input[consensusStateLengthBytesLength+csLen:])
header, err := v1.DecodeHeader(input[consensusStateLengthBytesLength+csLen:])
if err != nil {
return nil, nil, err
}

return &cs, header, nil
}

// tmHeaderValidate implemented as a native contract.
// tmHeaderValidate implemented as a native contract. Used to validate the light
// client's new header for tendermint v0.31.12 and its compatible version.
type tmHeaderValidate struct{}

func (c *tmHeaderValidate) RequiredGas(input []byte) uint64 {
Expand Down Expand Up @@ -169,7 +171,7 @@ func (c *iavlMerkleProofValidatePlanck) RequiredGas(_ []byte) uint64 {
}

func (c *iavlMerkleProofValidatePlanck) Run(input []byte) (result []byte, err error) {
c.basicIavlMerkleProofValidate.proofRuntime = lightclient.Ics23CompatibleProofRuntime()
c.basicIavlMerkleProofValidate.proofRuntime = v1.Ics23CompatibleProofRuntime()
c.basicIavlMerkleProofValidate.verifiers = []merkle.ProofOpVerifier{
forbiddenAbsenceOpVerifier,
singleValueOpVerifier,
Expand All @@ -188,7 +190,7 @@ func successfulMerkleResult() []byte {
}

type basicIavlMerkleProofValidate struct {
keyVerifier lightclient.KeyVerifier
keyVerifier v1.KeyVerifier
opsVerifier merkle.ProofOpsVerifier
verifiers []merkle.ProofOpVerifier
proofRuntime *merkle.ProofRuntime
Expand All @@ -210,12 +212,12 @@ func (c *basicIavlMerkleProofValidate) Run(input []byte) (result []byte, err err
return nil, fmt.Errorf("invalid input: input size should be %d, actual the size is %d", payloadLength+precompileContractInputMetaDataLength, len(input))
}

kvmp, err := lightclient.DecodeKeyValueMerkleProof(input[precompileContractInputMetaDataLength:])
kvmp, err := v1.DecodeKeyValueMerkleProof(input[precompileContractInputMetaDataLength:])
if err != nil {
return nil, err
}
if c.proofRuntime == nil {
kvmp.SetProofRuntime(lightclient.DefaultProofRuntime())
kvmp.SetProofRuntime(v1.DefaultProofRuntime())
} else {
kvmp.SetProofRuntime(c.proofRuntime)
}
Expand Down Expand Up @@ -255,7 +257,7 @@ func multiStoreOpVerifier(op merkle.ProofOperator) error {
if op == nil {
return nil
}
if mop, ok := op.(lightclient.MultiStoreProofOp); ok {
if mop, ok := op.(v1.MultiStoreProofOp); ok {
storeNames := make(map[string]bool, len(mop.Proof.StoreInfos))
for _, store := range mop.Proof.StoreInfos {
if exist := storeNames[store.Name]; exist {
Expand Down Expand Up @@ -291,25 +293,25 @@ func proofOpsVerifier(poz merkle.ProofOperators) error {
}

// for legacy proof type
if _, ok := poz[1].(lightclient.MultiStoreProofOp); ok {
if _, ok := poz[1].(v1.MultiStoreProofOp); ok {
if _, ok := poz[0].(iavl.IAVLValueOp); !ok {
return cmn.NewError("invalid proof op")
}
return nil
}

// for ics23 proof type
if op2, ok := poz[1].(lightclient.CommitmentOp); ok {
if op2.Type != lightclient.ProofOpSimpleMerkleCommitment {
if op2, ok := poz[1].(v1.CommitmentOp); ok {
if op2.Type != v1.ProofOpSimpleMerkleCommitment {
return cmn.NewError("invalid proof op")
}

op1, ok := poz[0].(lightclient.CommitmentOp)
op1, ok := poz[0].(v1.CommitmentOp)
if !ok {
return cmn.NewError("invalid proof op")
}

if op1.Type != lightclient.ProofOpIAVLCommitment {
if op1.Type != v1.ProofOpIAVLCommitment {
return cmn.NewError("invalid proof op")
}
return nil
Expand All @@ -327,3 +329,37 @@ func keyVerifier(key string) error {
}
return nil
}

// cometBFTLightBlockValidate implemented as a native contract. Used to validate the light
// blocks for CometBFT and its compatible version.
j75689 marked this conversation as resolved.
Show resolved Hide resolved
type cometBFTLightBlockValidate struct{}

func (c *cometBFTLightBlockValidate) RequiredGas(input []byte) uint64 {
return params.CometBFTLightBlockValidateGas
}

func (c *cometBFTLightBlockValidate) Run(input []byte) (result []byte, err error) {
defer func() {
if r := recover(); r != nil {
err = fmt.Errorf("internal error: %v\n", r)
}
}()

cs, block, err := v2.DecodeLightBlockValidationInput(input)
if err != nil {
return nil, err
}

validatorSetChanged, err := cs.ApplyLightBlock(block)
if err != nil {
return nil, err
}

consensusStateBytes, err := cs.EncodeConsensusState()
if err != nil {
return nil, err
}

result = v2.EncodeLightBlockValidationResult(validatorSetChanged, consensusStateBytes)
return result, nil
}
60 changes: 36 additions & 24 deletions core/vm/contracts_lightclient_test.go

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package lightclient
package v1

import (
"fmt"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package lightclient
package v1

import (
"bytes"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package lightclient
package v1

import (
"fmt"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package lightclient
package v1

import (
"bytes"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package lightclient
package v1

import (
"fmt"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package lightclient
package v1

import (
"github.com/tendermint/go-amino"
Expand Down
Loading