Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
72 changes: 72 additions & 0 deletions native/service/cross_chain_manager/chainsql/chainsql_handler.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
/*
* 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 chainsql

import (
"fmt"
pcom "github.com/polynetwork/poly/common"
"github.com/polynetwork/poly/native"
"github.com/polynetwork/poly/native/service/cross_chain_manager/common"
"github.com/polynetwork/poly/native/service/header_sync/chainsql"
hcom "github.com/polynetwork/poly/native/service/header_sync/common"
)

type ChainsqlHandler struct{}

func NewChainsqlHandler() *ChainsqlHandler {
return &ChainsqlHandler{}
}

func (this *ChainsqlHandler) MakeDepositProposal(ns *native.NativeService) (*common.MakeTxParam, error) {
params := new(common.EntranceParam)
if err := params.Deserialization(pcom.NewZeroCopySource(ns.GetInput())); err != nil {
return nil, fmt.Errorf("Chainsql MakeDepositProposal, contract params deserialize error: %v", err)
}
val := &common.MakeTxParam{}
if err := val.Deserialization(pcom.NewZeroCopySource(params.Extra)); err != nil {
return nil, fmt.Errorf("Chainsql MakeDepositProposal, failed to deserialize MakeTxParam: %v", err)
}
if err := common.CheckDoneTx(ns, val.CrossChainID, params.SourceChainID); err != nil {
return nil, fmt.Errorf("Chainsql MakeDepositProposal, check done transaction error: %v", err)
}
if err := common.PutDoneTx(ns, val.CrossChainID, params.SourceChainID); err != nil {
return nil, fmt.Errorf("Chainsql MakeDepositProposal, PutDoneTx error: %v", err)
}

root, err := chainsql.GetChainsqlRoot(ns, params.SourceChainID)
if err != nil {
return nil, fmt.Errorf("Chainsql MakeDepositProposal, failed to get the chainsql root cert: %v", err)
}
now := ns.GetBlockTime()
if now.After(root.RootCA.NotAfter) || now.Before(root.RootCA.NotBefore) {
return nil, fmt.Errorf("Chainsql MakeDepositProposal, Chainsql root CA need to update for chain %d: (start: %d, end: %d, block_time: %d)",
params.SourceChainID, root.RootCA.NotBefore.Unix(), root.RootCA.NotAfter.Unix(), now.Unix())
}
certs := &hcom.CertTrustChain{}
if err := certs.Deserialization(pcom.NewZeroCopySource(params.HeaderOrCrossChainMsg)); err != nil {
return nil, fmt.Errorf("Chainsql MakeDepositProposal, failed to deserialize CertTrustChain: %v", err)
}
if err := certs.Validate(ns); err != nil {
return nil, fmt.Errorf("Chainsql MakeDepositProposal, validate not pass: %v", err)
}
if err := certs.CheckSigWithRootCert(root.RootCA, params.Extra, params.Proof); err != nil {
return nil, fmt.Errorf("Chainsql MakeDepositProposal, failed to check sig: %v", err)
}
PutChainsqlLatestHeightInProcessing(ns, params.SourceChainID, val.FromContractAddress, params.Height)

return val, nil
}
189 changes: 189 additions & 0 deletions native/service/cross_chain_manager/chainsql/chainsql_handler_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
/*
* 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 chainsql

import (
"crypto/ecdsa"
"crypto/rand"
"encoding/pem"
"github.com/ontio/ontology-crypto/keypair"
"github.com/polynetwork/poly/account"
"github.com/polynetwork/poly/common"
"github.com/polynetwork/poly/consensus/vbft/config"
"github.com/polynetwork/poly/core/states"
"github.com/polynetwork/poly/core/store/leveldbstore"
"github.com/polynetwork/poly/core/store/overlaydb"
"github.com/polynetwork/poly/core/types"
"github.com/polynetwork/poly/native"
common2 "github.com/polynetwork/poly/native/service/cross_chain_manager/common"
"github.com/polynetwork/poly/native/service/governance/node_manager"
chainsql2 "github.com/polynetwork/poly/native/service/header_sync/chainsql"
common3 "github.com/polynetwork/poly/native/service/header_sync/common"
"github.com/polynetwork/poly/native/service/utils"
"github.com/polynetwork/poly/native/storage"
"github.com/tjfoc/gmsm/pkcs12"
"github.com/tjfoc/gmsm/sm2"
"gotest.tools/assert"
"testing"
"time"
)

var (
acct = account.NewAccount("")

getNativeFunc = func(args []byte, db *storage.CacheDB, cert string) *native.NativeService {
if db == nil {
store, _ := leveldbstore.NewMemLevelDBStore()
db = storage.NewCacheDB(overlaydb.NewOverlayDB(store))
sink := common.NewZeroCopySink(nil)
view := &node_manager.GovernanceView{
TxHash: common.UINT256_EMPTY,
Height: 0,
View: 0,
}
view.Serialization(sink)
db.Put(utils.ConcatKey(utils.NodeManagerContractAddress, []byte(node_manager.GOVERNANCE_VIEW)), states.GenRawStorageItem(sink.Bytes()))

peerPoolMap := &node_manager.PeerPoolMap{
PeerPoolMap: map[string]*node_manager.PeerPoolItem{
vconfig.PubkeyID(acct.PublicKey): {
Address: acct.Address,
Status: node_manager.ConsensusStatus,
PeerPubkey: vconfig.PubkeyID(acct.PublicKey),
Index: 0,
},
},
}
sink.Reset()
peerPoolMap.Serialization(sink)
db.Put(utils.ConcatKey(utils.NodeManagerContractAddress,
[]byte(node_manager.PEER_POOL), utils.GetUint32Bytes(0)), states.GenRawStorageItem(sink.Bytes()))

blk, _ := pem.Decode([]byte(cert))
cert, _ := sm2.ParseCertificate(blk.Bytes)
root := &chainsql2.ChainsqlRoot{
RootCA: cert,
}
sink = common.NewZeroCopySink(nil)
root.Serialization(sink)
db.Put(utils.ConcatKey(utils.HeaderSyncContractAddress, []byte(common3.ROOT_CERT), utils.GetUint64Bytes(6)),
states.GenRawStorageItem(sink.Bytes()))
}
signAddr, _ := types.AddressFromBookkeepers([]keypair.PublicKey{acct.PublicKey})
ns, _ := native.NewNativeService(db, &types.Transaction{SignedAddr: []common.Address{signAddr}}, uint32(time.Now().Unix()), 0, common.Uint256{0}, 0, args, false)
return ns
}

// secp256k1 for pubkey
rootCA = `-----BEGIN CERTIFICATE-----
MIIBYDCCAQUCCQDG5aP//Iy2ITAKBggqhkjOPQQDAjA5MRwwGgYDVQQDDBN3d3cu
cGVlcnNhZmUuY25DPVVTMRkwFwYDVQQHDBBCZWlqaW5nIENIQU9ZQU5HMB4XDTIy
MDcxMjExMTUxM1oXDTIzMDcxMjExMTUxM1owOTEcMBoGA1UEAwwTd3d3LnBlZXJz
YWZlLmNuQz1VUzEZMBcGA1UEBwwQQmVpamluZyBDSEFPWUFORzBWMBAGByqGSM49
AgEGBSuBBAAKA0IABOqcH14jODlTr/y2ji3U0Z8ENzF4I77Uc5wY8jKZ1+rgQKZ7
0XXEoc7YUKkh6DRrsC66TSbHKlOKePISpJ3xa2MwCgYIKoZIzj0EAwIDSQAwRgIh
AOJoC9uSfOGl/x2wnwW5xUpRTJoQA+zIwBih63HvvdyBAiEAqF3IlgFHPBAShWGk
2A7kpLBW2/MnT12QyC26hvth2gM=
-----END CERTIFICATE-----`

agencyCA = `-----BEGIN CERTIFICATE-----
MIIBYDCCAQUCCQDG5aP//Iy2ITAKBggqhkjOPQQDAjA5MRwwGgYDVQQDDBN3d3cu
cGVlcnNhZmUuY25DPVVTMRkwFwYDVQQHDBBCZWlqaW5nIENIQU9ZQU5HMB4XDTIy
MDcxMjExMTUxM1oXDTIzMDcxMjExMTUxM1owOTEcMBoGA1UEAwwTd3d3LnBlZXJz
YWZlLmNuQz1VUzEZMBcGA1UEBwwQQmVpamluZyBDSEFPWUFORzBWMBAGByqGSM49
AgEGBSuBBAAKA0IABOqcH14jODlTr/y2ji3U0Z8ENzF4I77Uc5wY8jKZ1+rgQKZ7
0XXEoc7YUKkh6DRrsC66TSbHKlOKePISpJ3xa2MwCgYIKoZIzj0EAwIDSQAwRgIh
AOJoC9uSfOGl/x2wnwW5xUpRTJoQA+zIwBih63HvvdyBAiEAqF3IlgFHPBAShWGk
2A7kpLBW2/MnT12QyC26hvth2gM=
-----END CERTIFICATE-----`

nodeCA = `-----BEGIN CERTIFICATE-----
MIICOjCCAeGgAwIBAgIJAK29Ojq6GKR/MAoGCCqGSM49BAMCMDkxHDAaBgNVBAMM
E3d3dy5wZWVyc2FmZS5jbkM9VVMxGTAXBgNVBAcMEEJlaWppbmcgQ0hBT1lBTkcw
HhcNMjIwNzEzMDIxNzI0WhcNMjMwNzEzMDIxNzI0WjCBgDELMAkGA1UEBhMCVVMx
EzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcMDVNhbiBGcmFuc2lzY28xETAP
BgNVBAoMCE1Mb3BzSHViMRUwEwYDVQQLDAxNbG9wc0h1YiBEZXYxGjAYBgNVBAMM
EWRlbW8ubWxvcHNodWIuY29tMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAEqzH+rlXB
v0H3f2WsTeU0p679KzPu+7qSRnorTrXjjJo9srNgNPiaa/9C/tX/up4TsWZvpAtz
QXoRfFUJ9eWBe6OBjDCBiTBTBgNVHSMETDBKoT2kOzA5MRwwGgYDVQQDDBN3d3cu
cGVlcnNhZmUuY25DPVVTMRkwFwYDVQQHDBBCZWlqaW5nIENIQU9ZQU5HggkAxuWj
//yMtiEwCQYDVR0TBAIwADALBgNVHQ8EBAMCBPAwGgYDVR0RBBMwEYIPd3d3LnBl
ZXJzYWZlLmNuMAoGCCqGSM49BAMCA0cAMEQCIANla2bAh2xbtY8e3MnVLXWBhSss
OWRHBAXdwwh8oJxGAiB2VzALkw3au6buj0M6yIRzRaPuY0z4jfM2klrpG23jmA==
-----END CERTIFICATE-----`

nodeK = `-----BEGIN PRIVATE KEY-----
MIGEAgEAMBAGByqGSM49AgEGBSuBBAAKBG0wawIBAQQgZ/BF7dM6KiTq6Xvf1OM7
Are3ZZ38mMxTICL6k0hgRLShRANCAASrMf6uVcG/Qfd/ZaxN5TSnrv0rM+77upJG
eitOteOMmj2ys2A0+Jpr/0L+1f+6nhOxZm+kC3NBehF8VQn15YF7
-----END PRIVATE KEY-----`
)

func TestChainsqlHandler_MakeDepositProposal(t *testing.T) {
param := common2.MakeTxParam{}
param.TxHash = common.UINT256_EMPTY.ToArray()
param.Method = "test"
sink := common.NewZeroCopySink(nil)
param.Serialization(sink)

blk, _ := pem.Decode([]byte(nodeK))
key, err := pkcs12.ParsePKCS8PrivateKey(blk.Bytes)
if err != nil {
t.Fatal(err)
}
priv := key.(*ecdsa.PrivateKey)

// the choise of hash according to the algo for signing
// here is SHA256
hasher := sm2.SHA256.New()
val := sink.Bytes()
hasher.Write(val)
raw := hasher.Sum(nil)
sig, err := priv.Sign(rand.Reader, raw, nil)
if err != nil {
t.Fatal(err)
}

caSet := &common3.CertTrustChain{
Certs: make([]*sm2.Certificate, 2),
}
blk, _ = pem.Decode([]byte(agencyCA))
caSet.Certs[0], err = sm2.ParseCertificate(blk.Bytes)
if err != nil {
t.Fatal(err)
}
blk, _ = pem.Decode([]byte(nodeCA))
caSet.Certs[1], _ = sm2.ParseCertificate(blk.Bytes)
sink = common.NewZeroCopySink(nil)
caSet.Serialization(sink)

params := new(common2.EntranceParam)
params.Proof = sig
params.Extra = val
params.SourceChainID = 6
params.HeaderOrCrossChainMsg = sink.Bytes()
sink = common.NewZeroCopySink(nil)
params.Serialization(sink)

ns := getNativeFunc(sink.Bytes(), nil, rootCA)
h := NewChainsqlHandler()
p, err := h.MakeDepositProposal(ns)
if err != nil {
t.Fatal(err)
}
assert.Equal(t, p.Method, "test")
}
49 changes: 49 additions & 0 deletions native/service/cross_chain_manager/chainsql/utils.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/*
* 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 chainsql

import (
"fmt"
"github.com/polynetwork/poly/core/states"
"github.com/polynetwork/poly/native"
"github.com/polynetwork/poly/native/service/header_sync/common"
"github.com/polynetwork/poly/native/service/utils"
)

func PutChainsqlLatestHeightInProcessing(ns *native.NativeService, chainID uint64, fromContract []byte, height uint32) {
last, _ := GetChainsqlLatestHeightInProcessing(ns, chainID, fromContract)
if height <= last {
return
}
ns.GetCacheDB().Put(utils.ConcatKey(utils.CrossChainManagerContractAddress, []byte(common.LATEST_HEIGHT_IN_PROCESSING), utils.GetUint64Bytes(chainID), fromContract),
utils.GetUint32Bytes(height))
}

func GetChainsqlLatestHeightInProcessing(ns *native.NativeService, chainID uint64, fromContract []byte) (uint32, error) {
store, err := ns.GetCacheDB().Get(utils.ConcatKey(utils.CrossChainManagerContractAddress, []byte(common.LATEST_HEIGHT_IN_PROCESSING), utils.GetUint64Bytes(chainID), fromContract))
if err != nil {
return 0, fmt.Errorf("GetChainsqlRoot, get root error: %v", err)
}
if store == nil {
return 0, fmt.Errorf("GetChainsqlRoot, can not find any records")
}
raw, err := states.GetValueFromRawStorageItem(store)
if err != nil {
return 0, fmt.Errorf("GetChainsqlRoot, deserialize from raw storage item err: %v", err)
}
return utils.GetBytesUint32(raw), nil
}
3 changes: 3 additions & 0 deletions native/service/cross_chain_manager/entrance.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ package cross_chain_manager
import (
"encoding/hex"
"fmt"
"github.com/polynetwork/poly/native/service/cross_chain_manager/chainsql"

"github.com/polynetwork/poly/native/service/cross_chain_manager/fabric"
"github.com/polynetwork/poly/native/service/cross_chain_manager/fisco"
Expand Down Expand Up @@ -72,6 +73,8 @@ func GetChainHandler(router uint64) (scom.ChainHandler, error) {
return fisco.NewFiscoHandler(), nil
case utils.FABRIC_ROUTER:
return fabric.NewFabricHandler(), nil
case utils.CHAINSQL_ROUTER:
return chainsql.NewChainsqlHandler(),nil
default:
return nil, fmt.Errorf("not a supported router:%d", router)
}
Expand Down
Loading