-
Notifications
You must be signed in to change notification settings - Fork 54
Add support for native kai #49
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
Open
dogecoindev
wants to merge
26
commits into
polynetwork:master
Choose a base branch
from
dogecoindev:kai
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 3 commits
Commits
Show all changes
26 commits
Select commit
Hold shift + click to select a range
6be4410
add support for Neo N3
joeqian10 4cd36cb
fix typo
joeqian10 ca4d9ca
add neo2 back
joeqian10 067ba90
fix neo3 header deserialization, rename structs
joeqian10 9a36e38
fix
joeqian10 4f959cc
fix 2
joeqian10 437aa38
fix neoCrossChainMsg
joeqian10 474879d
add neo3 state validator manager
joeqian10 7c006f5
add support native kai
dogecoindev a187e36
remove db
dogecoindev 6be8177
add kai router
dogecoindev d2d6694
update import go-eth version
dogecoindev 4034bfb
update neo3 state root GetMessage()
joeqian10 4f8d44e
Merge branch 'master' into master
joeqian10 24b1d3d
get neo3 magic from side chain extra info
joeqian10 22bce4f
Merge branch 'master' of https://github.com/joeqian10/poly
joeqian10 c36d24c
update dependency
joeqian10 24ddfe9
remove merkletree.db
dogecoindev 733e4e0
remove unused code
joeqian10 ebead48
discard map for filtering
joeqian10 7079ecb
Merge https://github.com/joeqian10/poly into kai
dogecoindev efaaf7f
Revert "remove merkletree.db"
dogecoindev b1937a3
fix register kai handler
dogecoindev 39aec30
add unitest kai header sync
dogecoindev 9446cd3
update unitest
dogecoindev 48907b9
fix import kai full header
dogecoindev File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Large diffs are not rendered by default.
Oops, something went wrong.
Binary file not shown.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,260 @@ | ||
| /* | ||
| * Copyright (C) 2020 The poly network Authors | ||
| * This file is part of The poly network library. | ||
| * | ||
| * The poly network is free software: you can redistribute it and/or modify | ||
| * it under the terms of the GNU Lesser General Public License as published by | ||
| * the Free Software Foundation, either version 3 of the License, or | ||
| * (at your option) any later version. | ||
| * | ||
| * The poly network is distributed in the hope that it will be useful, | ||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| * GNU Lesser General Public License for more details. | ||
| * You should have received a copy of the GNU Lesser General Public License | ||
| * along with The poly network . If not, see <http://www.gnu.org/licenses/>. | ||
| */ | ||
|
|
||
| package kai | ||
|
|
||
| import ( | ||
| "bytes" | ||
| "encoding/hex" | ||
| "encoding/json" | ||
| "fmt" | ||
| "math/big" | ||
|
|
||
| ecommon "github.com/ethereum/go-ethereum/common" | ||
| "github.com/ethereum/go-ethereum/crypto" | ||
| "github.com/ethereum/go-ethereum/light" | ||
| "github.com/ethereum/go-ethereum/rlp" | ||
| "github.com/ethereum/go-ethereum/trie" | ||
| "github.com/kardiachain/go-kardia/types" | ||
| "github.com/polynetwork/poly/common" | ||
| "github.com/polynetwork/poly/common/log" | ||
| "github.com/polynetwork/poly/native" | ||
| scom "github.com/polynetwork/poly/native/service/cross_chain_manager/common" | ||
| "github.com/polynetwork/poly/native/service/governance/side_chain_manager" | ||
| "github.com/polynetwork/poly/native/service/header_sync/kai" | ||
dogecoindev marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| ) | ||
|
|
||
| // Handler ... | ||
| type Handler struct { | ||
| } | ||
|
|
||
| // NewHandler ... | ||
| func NewHandler() *Handler { | ||
| return &Handler{} | ||
| } | ||
|
|
||
| // MakeDepositProposal ... | ||
| func (h *Handler) MakeDepositProposal(service *native.NativeService) (*scom.MakeTxParam, error) { | ||
| params := new(scom.EntranceParam) | ||
| if err := params.Deserialization(common.NewZeroCopySource(service.GetInput())); err != nil { | ||
| return nil, fmt.Errorf("KAI MakeDepositProposal, contract params deserialize error: %s", err) | ||
| } | ||
| info, err := kai.GetEpochSwitchInfo(service, params.SourceChainID) | ||
| if err != nil { | ||
| return nil, fmt.Errorf("KAI MakeDepositProposal, failed to get epoch switching height: %v", err) | ||
| } | ||
| if info.Height > int64(params.Height) { | ||
| return nil, fmt.Errorf("KAI MakeDepositProposal, the height %d of header is lower than epoch "+ | ||
| "switching height %d", params.Height, info.Height) | ||
| } | ||
|
|
||
| if len(params.HeaderOrCrossChainMsg) == 0 { | ||
| return nil, fmt.Errorf("you must commit the header used to verify transaction's proof and get none") | ||
| } | ||
|
|
||
| var myHeader kai.Header | ||
| if err := json.Unmarshal(params.HeaderOrCrossChainMsg, &myHeader); err != nil { | ||
| return nil, fmt.Errorf("KAI MakeDepositProposal, unmarshal cosmos header failed: %v", err) | ||
| } | ||
| if myHeader.Header.Height != uint64(params.Height) { | ||
| return nil, fmt.Errorf("KAI MakeDepositProposal, "+ | ||
| "height of your header is %d not equal to %d in parameter", myHeader.Header.Height, params.Height) | ||
| } | ||
|
|
||
| if err = kai.VerifyHeader(&myHeader, info); err != nil { | ||
| return nil, fmt.Errorf("KAI MakeDepositProposal, failed to verify KAI header: %v", err) | ||
| } | ||
|
|
||
| sideChain, err := side_chain_manager.GetSideChain(service, params.SourceChainID) | ||
| if err != nil { | ||
| return nil, fmt.Errorf("KAI MakeDepositProposal, side_chain_manager.GetSideChain error: %v", err) | ||
| } | ||
|
|
||
| if !myHeader.Header.ValidatorsHash.Equal(myHeader.Header.NextValidatorsHash) && | ||
| int64(myHeader.Header.Height) > info.Height { | ||
| kai.PutEpochSwitchInfo(service, params.SourceChainID, &kai.EpochSwitchInfo{ | ||
| Height: int64(myHeader.Header.Height), | ||
| BlockHash: myHeader.Header.Hash().Bytes(), | ||
| NextValidatorsHash: myHeader.Header.NextValidatorsHash.Bytes(), | ||
| ChainID: "", | ||
| }) | ||
| } | ||
|
|
||
| value, err := verifyTx(myHeader.Header, service, params.Proof, params.Extra, params.SourceChainID, params.Height, sideChain) | ||
| if err != nil { | ||
| return nil, fmt.Errorf("KAI MakeDepositProposal, verifyFromEthTx error: %s", err) | ||
| } | ||
|
|
||
| if err := scom.CheckDoneTx(service, value.CrossChainID, params.SourceChainID); err != nil { | ||
| return nil, fmt.Errorf("KAI MakeDepositProposal, check done transaction error:%s", err) | ||
| } | ||
| if err := scom.PutDoneTx(service, value.CrossChainID, params.SourceChainID); err != nil { | ||
| return nil, fmt.Errorf("KAI MakeDepositProposal, PutDoneTx error:%s", err) | ||
| } | ||
|
|
||
| return nil, nil | ||
| } | ||
|
|
||
| func verifyTx(header *types.Header, native *native.NativeService, proof, extra []byte, fromChainID uint64, height uint32, sideChain *side_chain_manager.SideChain) (param *scom.MakeTxParam, err error) { | ||
| kaiProof := new(Proof) | ||
| err = json.Unmarshal(proof, kaiProof) | ||
| if err != nil { | ||
| return nil, fmt.Errorf("verifyTx, unmarshal proof error:%s", err) | ||
| } | ||
|
|
||
| if len(kaiProof.StorageProofs) != 1 { | ||
| return nil, fmt.Errorf("verifyTx, incorrect proof format") | ||
| } | ||
|
|
||
| proofResult, err := verifyMerkleProof(kaiProof, header, sideChain.CCMCAddress) | ||
| if err != nil { | ||
| return nil, fmt.Errorf("verifyTx, verifyMerkleProof error:%v", err) | ||
| } | ||
|
|
||
| if proofResult == nil { | ||
| return nil, fmt.Errorf("verifyTx, verifyMerkleProof failed") | ||
| } | ||
|
|
||
| if !checkProofResult(proofResult, extra) { | ||
| return nil, fmt.Errorf("verifyTx, verify proof value hash failed, proof result:%x, extra:%x", proofResult, extra) | ||
| } | ||
|
|
||
| data := common.NewZeroCopySource(extra) | ||
| txParam := new(scom.MakeTxParam) | ||
| if err := txParam.Deserialization(data); err != nil { | ||
| return nil, fmt.Errorf("verifyTx, deserialize merkleValue error:%s", err) | ||
| } | ||
| return txParam, nil | ||
| } | ||
|
|
||
| // Proof ... | ||
| type Proof struct { | ||
| Address string `json:"address"` | ||
| Balance string `json:"balance"` | ||
| CodeHash string `json:"codeHash"` | ||
| Nonce string `json:"nonce"` | ||
| StorageHash string `json:"storageHash"` | ||
| AccountProof []string `json:"accountProof"` | ||
| StorageProofs []StorageProof `json:"storageProof"` | ||
| } | ||
|
|
||
| // StorageProof ... | ||
| type StorageProof struct { | ||
| Key string `json:"key"` | ||
| Value string `json:"value"` | ||
| Proof []string `json:"proof"` | ||
| } | ||
|
|
||
| // ProofAccount ... | ||
| type ProofAccount struct { | ||
| Nounce *big.Int | ||
| Balance *big.Int | ||
| Storage ecommon.Hash | ||
| Codehash ecommon.Hash | ||
| } | ||
|
|
||
| func verifyMerkleProof(kaiProof *Proof, blockData *types.Header, contractAddr []byte) ([]byte, error) { | ||
| //1. prepare verify account | ||
| nodeList := new(light.NodeList) | ||
|
|
||
| for _, s := range kaiProof.AccountProof { | ||
| p := scom.Replace0x(s) | ||
| nodeList.Put(nil, ecommon.Hex2Bytes(p)) | ||
| } | ||
| ns := nodeList.NodeSet() | ||
|
|
||
| addr := ecommon.Hex2Bytes(scom.Replace0x(kaiProof.Address)) | ||
| if !bytes.Equal(addr, contractAddr) { | ||
| return nil, fmt.Errorf("verifyMerkleProof, contract address is error, proof address: %s, side chain address: %s", kaiProof.Address, hex.EncodeToString(contractAddr)) | ||
| } | ||
| acctKey := crypto.Keccak256(addr) | ||
|
|
||
| //2. verify account proof | ||
| acctVal, err := trie.VerifyProof(ecommon.Hash(blockData.AppHash), acctKey, ns) | ||
| if err != nil { | ||
| return nil, fmt.Errorf("verifyMerkleProof, verify account proof error:%s", err) | ||
| } | ||
|
|
||
| nounce := new(big.Int) | ||
| _, ok := nounce.SetString(scom.Replace0x(kaiProof.Nonce), 16) | ||
| if !ok { | ||
| return nil, fmt.Errorf("verifyMerkleProof, invalid format of nounce:%s", kaiProof.Nonce) | ||
| } | ||
|
|
||
| balance := new(big.Int) | ||
| _, ok = balance.SetString(scom.Replace0x(kaiProof.Balance), 16) | ||
| if !ok { | ||
| return nil, fmt.Errorf("verifyMerkleProof, invalid format of balance:%s", kaiProof.Balance) | ||
| } | ||
|
|
||
| storageHash := ecommon.HexToHash(scom.Replace0x(kaiProof.StorageHash)) | ||
| codeHash := ecommon.HexToHash(scom.Replace0x(kaiProof.CodeHash)) | ||
|
|
||
| acct := &ProofAccount{ | ||
| Nounce: nounce, | ||
| Balance: balance, | ||
| Storage: storageHash, | ||
| Codehash: codeHash, | ||
| } | ||
|
|
||
| acctrlp, err := rlp.EncodeToBytes(acct) | ||
| if err != nil { | ||
| return nil, err | ||
| } | ||
|
|
||
| if !bytes.Equal(acctrlp, acctVal) { | ||
| return nil, fmt.Errorf("verifyMerkleProof, verify account proof failed, wanted:%v, get:%v", acctrlp, acctVal) | ||
| } | ||
|
|
||
| //3.verify storage proof | ||
| nodeList = new(light.NodeList) | ||
| if len(kaiProof.StorageProofs) != 1 { | ||
| return nil, fmt.Errorf("verifyMerkleProof, invalid storage proof format") | ||
| } | ||
|
|
||
| sp := kaiProof.StorageProofs[0] | ||
| storageKey := crypto.Keccak256(ecommon.HexToHash(scom.Replace0x(sp.Key)).Bytes()) | ||
|
|
||
| for _, prf := range sp.Proof { | ||
| nodeList.Put(nil, ecommon.Hex2Bytes(scom.Replace0x(prf))) | ||
| } | ||
|
|
||
| ns = nodeList.NodeSet() | ||
| val, err := trie.VerifyProof(storageHash, storageKey, ns) | ||
| if err != nil { | ||
| return nil, fmt.Errorf("verifyMerkleProof, verify storage proof error:%s", err) | ||
| } | ||
|
|
||
| return val, nil | ||
| } | ||
|
|
||
| func checkProofResult(result, value []byte) bool { | ||
| var tempBytes []byte | ||
| err := rlp.DecodeBytes(result, &tempBytes) | ||
| if err != nil { | ||
| log.Errorf("checkProofResult, rlp.DecodeBytes error:%s\n", err) | ||
| return false | ||
| } | ||
| // | ||
| var s []byte | ||
| for i := len(tempBytes); i < 32; i++ { | ||
| s = append(s, 0) | ||
| } | ||
| s = append(s, tempBytes...) | ||
| hash := crypto.Keccak256(value) | ||
| return bytes.Equal(s, hash) | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| package kai |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,75 @@ | ||
| /* | ||
| * Copyright (C) 2020 The poly network Authors | ||
| * This file is part of The poly network library. | ||
| * | ||
| * The poly network is free software: you can redistribute it and/or modify | ||
| * it under the terms of the GNU Lesser General Public License as published by | ||
| * the Free Software Foundation, either version 3 of the License, or | ||
| * (at your option) any later version. | ||
| * | ||
| * The poly network is distributed in the hope that it will be useful, | ||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| * GNU Lesser General Public License for more details. | ||
| * You should have received a copy of the GNU Lesser General Public License | ||
| * along with The poly network . If not, see <http://www.gnu.org/licenses/>. | ||
| */ | ||
| package kai | ||
|
|
||
| import ( | ||
| "encoding/json" | ||
| "fmt" | ||
|
|
||
| "github.com/polynetwork/poly/common" | ||
| "github.com/polynetwork/poly/common/log" | ||
| "github.com/polynetwork/poly/native" | ||
| hscommon "github.com/polynetwork/poly/native/service/header_sync/common" | ||
| ) | ||
|
|
||
| // Handler ... | ||
| type Handler struct { | ||
| } | ||
|
|
||
| // SyncBlockHeader ... | ||
| func (h *Handler) SyncBlockHeader(native *native.NativeService) error { | ||
| params := new(hscommon.SyncBlockHeaderParam) | ||
| if err := params.Deserialization(common.NewZeroCopySource(native.GetInput())); err != nil { | ||
| return fmt.Errorf("SyncBlockHeader, contract params deserialize error: %v", err) | ||
| } | ||
| cnt := 0 | ||
| info, err := GetEpochSwitchInfo(native, params.ChainID) | ||
| if err != nil { | ||
| return fmt.Errorf("SyncBlockHeader, get epoch switching height failed: %v", err) | ||
| } | ||
| for _, v := range params.Headers { | ||
| var myHeader Header | ||
| if err := json.Unmarshal(v, &myHeader); err != nil { | ||
| return fmt.Errorf("SyncBlockHeader failed to unmarshal header: %v", err) | ||
| } | ||
|
|
||
| if myHeader.Header.NextValidatorsHash.Equal(myHeader.Header.ValidatorsHash) { | ||
| continue | ||
| } | ||
| if info.Height >= int64(myHeader.Header.Height) { | ||
| log.Debugf("SyncBlockHeader, height %d is lower or equal than epoch switching height %d", | ||
| myHeader.Header.Height, info.Height) | ||
| continue | ||
| } | ||
| if err = VerifyHeader(&myHeader, info); err != nil { | ||
| return fmt.Errorf("SyncBlockHeader, failed to verify header: %v", err) | ||
| } | ||
| info.NextValidatorsHash = myHeader.Header.NextValidatorsHash.Bytes() | ||
| info.Height = int64(myHeader.Header.Height) | ||
| info.BlockHash = myHeader.Header.Hash().Bytes() | ||
| cnt++ | ||
| } | ||
| if cnt == 0 { | ||
| return fmt.Errorf("no header you commited is useful") | ||
| } | ||
| PutEpochSwitchInfo(native, params.ChainID, info) | ||
| return nil | ||
| } | ||
|
|
||
| func (this *Handler) SyncCrossChainMsg(native *native.NativeService) error { | ||
| return nil | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| package kai |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.