diff --git a/native/service/cross_chain_manager/chainsql/chainsql_handler.go b/native/service/cross_chain_manager/chainsql/chainsql_handler.go
new file mode 100644
index 00000000..e02b36e1
--- /dev/null
+++ b/native/service/cross_chain_manager/chainsql/chainsql_handler.go
@@ -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 .
+ */
+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
+}
diff --git a/native/service/cross_chain_manager/chainsql/chainsql_handler_test.go b/native/service/cross_chain_manager/chainsql/chainsql_handler_test.go
new file mode 100644
index 00000000..a4792a85
--- /dev/null
+++ b/native/service/cross_chain_manager/chainsql/chainsql_handler_test.go
@@ -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 .
+ */
+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")
+}
diff --git a/native/service/cross_chain_manager/chainsql/utils.go b/native/service/cross_chain_manager/chainsql/utils.go
new file mode 100644
index 00000000..a39f2566
--- /dev/null
+++ b/native/service/cross_chain_manager/chainsql/utils.go
@@ -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 .
+ */
+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
+}
diff --git a/native/service/cross_chain_manager/entrance.go b/native/service/cross_chain_manager/entrance.go
index 85cb17a6..31366396 100644
--- a/native/service/cross_chain_manager/entrance.go
+++ b/native/service/cross_chain_manager/entrance.go
@@ -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"
@@ -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)
}
diff --git a/native/service/header_sync/chainsql/root_ca_sync.go b/native/service/header_sync/chainsql/root_ca_sync.go
new file mode 100644
index 00000000..4f902eae
--- /dev/null
+++ b/native/service/header_sync/chainsql/root_ca_sync.go
@@ -0,0 +1,89 @@
+/*
+ * 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 .
+ */
+package chainsql
+
+import (
+ "encoding/pem"
+ "fmt"
+ "github.com/polynetwork/poly/common"
+ "github.com/polynetwork/poly/native"
+ "github.com/polynetwork/poly/native/service/governance/node_manager"
+ scom "github.com/polynetwork/poly/native/service/header_sync/common"
+ "github.com/polynetwork/poly/native/service/utils"
+ "github.com/tjfoc/gmsm/sm2"
+)
+
+type ChainsqlHandler struct{}
+
+func NewChainsqlHandler() *ChainsqlHandler {
+ return &ChainsqlHandler{}
+}
+
+func (this *ChainsqlHandler) SyncGenesisHeader(ns *native.NativeService) error {
+ params := new(scom.SyncGenesisHeaderParam)
+ if err := params.Deserialization(common.NewZeroCopySource(ns.GetInput())); err != nil {
+ return fmt.Errorf("ChainsqlHandler SyncGenesisHeader, contract params deserialize error: %v", err)
+ }
+
+ // Get current epoch operator
+ operatorAddress, err := node_manager.GetCurConOperator(ns)
+ if err != nil {
+ return fmt.Errorf("ChainsqlHandler SyncGenesisHeader, get current consensus operator address error: %v", err)
+ }
+ // check witness
+ err = utils.ValidateOwner(ns, operatorAddress)
+ if err != nil {
+ return fmt.Errorf("ChainsqlHandler SyncGenesisHeader, checkWitness error: %v", err)
+ }
+
+ blk, _ := pem.Decode(params.GenesisHeader)
+ if blk == nil {
+ return fmt.Errorf("ChainsqlHandler SyncGenesisHeader, failed to decode PEM formatted block")
+ }
+ if blk.Type != "CERTIFICATE" {
+ return fmt.Errorf("ChainsqlHandler SyncGenesisHeader, wrong block type: %s", blk.Type)
+ }
+ cert, err := sm2.ParseCertificate(blk.Bytes)
+ if err != nil {
+ return fmt.Errorf("ChainsqlHandler SyncGenesisHeader, failed to parse certificate: %v", err)
+ }
+
+ now := ns.GetBlockTime()
+ if now.After(cert.NotAfter) || now.Before(cert.NotBefore) {
+ return fmt.Errorf("ChainsqlHandler SyncGenesisHeader, wrong time for new CA: "+
+ "(start: %d, end: %d, block_time: %d)",
+ cert.NotBefore.Unix(), cert.NotAfter.Unix(), now.Unix())
+ }
+
+ root := &ChainsqlRoot{
+ RootCA: cert,
+ }
+
+ if err = PutChainsqlRoot(ns, root, params.ChainID); err != nil {
+ return fmt.Errorf("ChainsqlHandler SyncGenesisHeader, failed to put new Chainsql root CA into storage: %v", err)
+ }
+
+ return nil
+}
+
+func (this *ChainsqlHandler) SyncBlockHeader(ns *native.NativeService) error {
+ return nil
+}
+
+func (this *ChainsqlHandler) SyncCrossChainMsg(ns *native.NativeService) error {
+ return nil
+}
diff --git a/native/service/header_sync/chainsql/root_ca_sync_test.go b/native/service/header_sync/chainsql/root_ca_sync_test.go
new file mode 100644
index 00000000..3756a26c
--- /dev/null
+++ b/native/service/header_sync/chainsql/root_ca_sync_test.go
@@ -0,0 +1,124 @@
+/*
+ * 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 .
+ */
+package chainsql
+
+import (
+ "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"
+ "github.com/polynetwork/poly/native/service/governance/node_manager"
+ common2 "github.com/polynetwork/poly/native/service/header_sync/common"
+ "github.com/polynetwork/poly/native/service/utils"
+ "github.com/polynetwork/poly/native/storage"
+ "github.com/stretchr/testify/assert"
+ "testing"
+)
+
+var (
+ acct = account.NewAccount("")
+
+ getNativeFunc = func(args []byte, db *storage.CacheDB) *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()))
+ }
+ signAddr, _ := types.AddressFromBookkeepers([]keypair.PublicKey{acct.PublicKey})
+ ns, _ := native.NewNativeService(db, &types.Transaction{SignedAddr: []common.Address{signAddr}}, 1600945402, 0, common.Uint256{0}, 0, args, false)
+ return ns
+ }
+
+ rootCA = `-----BEGIN CERTIFICATE-----
+MIIBxDCCAWqgAwIBAgIJAL0TiHo7dsqWMAoGCCqBHM9VAYN1MDcxEDAOBgNVBAMM
+B2dtY2hhaW4xEzARBgNVBAoMCmZpc2NvLWJjb3MxDjAMBgNVBAsMBWNoYWluMCAX
+DTIwMDkyNDExMDMyMVoYDzIxMjAwODMxMTEwMzIxWjA3MRAwDgYDVQQDDAdnbWNo
+YWluMRMwEQYDVQQKDApmaXNjby1iY29zMQ4wDAYDVQQLDAVjaGFpbjBZMBMGByqG
+SM49AgEGCCqBHM9VAYItA0IABEIf/hJjT6DAGYWCyP99sBoTF2cCqpbLsrOf+NwY
+KY0zdXUA9BwYCs+HyoSLRtZBlfa5hO5S6wDbU1l9472aYFijXTBbMB0GA1UdDgQW
+BBQILjttksRAgGbi4KMNrLHlwPhxkTAfBgNVHSMEGDAWgBQILjttksRAgGbi4KMN
+rLHlwPhxkTAMBgNVHRMEBTADAQH/MAsGA1UdDwQEAwIBBjAKBggqgRzPVQGDdQNI
+ADBFAiBKFFaclfd0IKplJgLXDdAxS1Cvwhl/ZOFwPq28V2wi8gIhAPaAT8qf1hUv
+9FGgtdQbPr/lerRDGOETv5Zi5GEJBOpA
+-----END CERTIFICATE-----`
+)
+
+func TestChainsqlHandler_SyncGenesisHeader(t *testing.T) {
+ params := new(common2.SyncGenesisHeaderParam)
+ params.ChainID = 6
+
+ params.GenesisHeader = []byte(rootCA)
+ sink := common.NewZeroCopySink(nil)
+ params.Serialization(sink)
+ ns := getNativeFunc(sink.Bytes(), nil)
+
+ h := NewChainsqlHandler()
+
+ // sync ca
+ if err := h.SyncGenesisHeader(ns); err != nil {
+ t.Fatal(err)
+ }
+
+ root, err := GetChainsqlRoot(ns, 6)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ blk, _ := pem.Decode([]byte(rootCA))
+ if blk == nil {
+ t.Fatal("failed to decode pem")
+ }
+ assert.Equal(t, blk.Bytes, root.RootCA.Raw, "wrong base64-encoded bytes")
+
+ // next successful to update
+ params.GenesisHeader = []byte(rootCA)
+ sink.Reset()
+ params.Serialization(sink)
+ ns = getNativeFunc(sink.Bytes(), ns.GetCacheDB())
+ err = h.SyncGenesisHeader(ns)
+ if err != nil {
+ t.Fatal(err)
+ }
+}
diff --git a/native/service/header_sync/chainsql/states.go b/native/service/header_sync/chainsql/states.go
new file mode 100644
index 00000000..1780f94a
--- /dev/null
+++ b/native/service/header_sync/chainsql/states.go
@@ -0,0 +1,47 @@
+/*
+ * 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 .
+ */
+package chainsql
+
+import (
+ "fmt"
+ pcom "github.com/polynetwork/poly/common"
+ "github.com/tjfoc/gmsm/sm2"
+)
+
+type ChainsqlRoot struct {
+ RootCA *sm2.Certificate
+}
+
+func (root *ChainsqlRoot) Serialization(sink *pcom.ZeroCopySink) {
+ sink.WriteVarBytes(root.RootCA.Raw)
+}
+
+func (root *ChainsqlRoot) Deserialization(source *pcom.ZeroCopySource) error {
+ var (
+ err error
+ )
+ raw, eof := source.NextVarBytes()
+ if eof {
+ return fmt.Errorf("failed to deserialize RootCA")
+ }
+ root.RootCA, err = sm2.ParseCertificate(raw)
+ if err != nil {
+ return fmt.Errorf("failed to parse cert: %v", err)
+ }
+
+ return nil
+}
diff --git a/native/service/header_sync/chainsql/utils.go b/native/service/header_sync/chainsql/utils.go
new file mode 100644
index 00000000..71f3c42a
--- /dev/null
+++ b/native/service/header_sync/chainsql/utils.go
@@ -0,0 +1,57 @@
+/*
+ * 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 .
+ */
+package chainsql
+
+import (
+ "fmt"
+ pcom "github.com/polynetwork/poly/common"
+ "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 PutChainsqlRoot(native *native.NativeService, root *ChainsqlRoot, chainID uint64) error {
+ contract := utils.HeaderSyncContractAddress
+ sink := pcom.NewZeroCopySink(nil)
+ root.Serialization(sink)
+ native.GetCacheDB().Put(utils.ConcatKey(contract, []byte(common.ROOT_CERT), utils.GetUint64Bytes(chainID)),
+ states.GenRawStorageItem(sink.Bytes()))
+
+ common.NotifyPutCertificate(native, chainID, root.RootCA.Raw)
+ return nil
+}
+
+func GetChainsqlRoot(native *native.NativeService, chainID uint64) (*ChainsqlRoot, error) {
+ store, err := native.GetCacheDB().Get(utils.ConcatKey(utils.HeaderSyncContractAddress,
+ []byte(common.ROOT_CERT), utils.GetUint64Bytes(chainID)))
+ if err != nil {
+ return nil, fmt.Errorf("GetChainsqlRoot, get root error: %v", err)
+ }
+ if store == nil {
+ return nil, fmt.Errorf("GetChainsqlRoot, can not find any records")
+ }
+ raw, err := states.GetValueFromRawStorageItem(store)
+ if err != nil {
+ return nil, fmt.Errorf("GetChainsqlRoot, deserialize from raw storage item err: %v", err)
+ }
+ root := &ChainsqlRoot{}
+ if err = root.Deserialization(pcom.NewZeroCopySource(raw)); err != nil {
+ return nil, fmt.Errorf("GetChainsqlRoot, failed to deserialize ChainsqlRoot: %v", err)
+ }
+ return root, nil
+}
diff --git a/native/service/header_sync/entrance.go b/native/service/header_sync/entrance.go
index fae503c0..e1b27e93 100644
--- a/native/service/header_sync/entrance.go
+++ b/native/service/header_sync/entrance.go
@@ -19,6 +19,7 @@ package header_sync
import (
"fmt"
+ "github.com/polynetwork/poly/native/service/header_sync/chainsql"
"github.com/polynetwork/poly/native/service/header_sync/fabric"
"github.com/polynetwork/poly/native/service/header_sync/fisco"
@@ -67,6 +68,8 @@ func GetChainHandler(router uint64) (hscommon.HeaderSyncHandler, 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)
}
diff --git a/native/service/utils/params.go b/native/service/utils/params.go
index f144fd5c..8cf4e5d3 100644
--- a/native/service/utils/params.go
+++ b/native/service/utils/params.go
@@ -46,4 +46,5 @@ var (
FISCO_ROUTER = uint64(6)
FABRIC_ROUTER = uint64(7)
QUORUM_ROUTER = uint64(8)
+ CHAINSQL_ROUTER = uint64(9)
)