Commit 2aa47b88 authored by madengji's avatar madengji Committed by 33cn

bls sign commit part

parent 9bc6a7df
...@@ -91,6 +91,7 @@ type subConfig struct { ...@@ -91,6 +91,7 @@ type subConfig struct {
MultiDownServerRspTime uint32 `json:"multiDownServerRspTime,omitempty"` MultiDownServerRspTime uint32 `json:"multiDownServerRspTime,omitempty"`
RmCommitParamMainHeight int64 `json:"rmCommitParamMainHeight,omitempty"` RmCommitParamMainHeight int64 `json:"rmCommitParamMainHeight,omitempty"`
JumpDownloadClose bool `json:"jumpDownloadClose,omitempty"` JumpDownloadClose bool `json:"jumpDownloadClose,omitempty"`
BlsSignOff bool `json:"blsSignOff,omitempty"`
} }
// New function to init paracross env // New function to init paracross env
......
...@@ -19,11 +19,14 @@ import ( ...@@ -19,11 +19,14 @@ import (
"bytes" "bytes"
"math/big"
"github.com/33cn/chain33/common" "github.com/33cn/chain33/common"
"github.com/33cn/chain33/common/crypto" "github.com/33cn/chain33/common/crypto"
"github.com/33cn/chain33/types" "github.com/33cn/chain33/types"
paracross "github.com/33cn/plugin/plugin/dapp/paracross/types" paracross "github.com/33cn/plugin/plugin/dapp/paracross/types"
pt "github.com/33cn/plugin/plugin/dapp/paracross/types" pt "github.com/33cn/plugin/plugin/dapp/paracross/types"
"github.com/phoreproject/bls/g2pubs"
"github.com/pkg/errors" "github.com/pkg/errors"
) )
...@@ -60,6 +63,8 @@ type commitMsgClient struct { ...@@ -60,6 +63,8 @@ type commitMsgClient struct {
txFeeRate int64 txFeeRate int64
selfConsEnableList []*paraSelfConsEnable //适配在自共识合约配置前有自共识的平行链项目,fork之后,采用合约配置 selfConsEnableList []*paraSelfConsEnable //适配在自共识合约配置前有自共识的平行链项目,fork之后,采用合约配置
privateKey crypto.PrivKey privateKey crypto.PrivKey
blsPriKey *g2pubs.SecretKey
blsPubKey *g2pubs.PublicKey
quit chan struct{} quit chan struct{}
mutex sync.Mutex mutex sync.Mutex
} }
...@@ -360,7 +365,19 @@ func (client *commitMsgClient) getSendingTx(startHeight, endHeight int64) (*type ...@@ -360,7 +365,19 @@ func (client *commitMsgClient) getSendingTx(startHeight, endHeight int64) (*type
return nil, 0 return nil, 0
} }
signTx, count, err := client.calcCommitMsgTxs(status, atomic.LoadInt64(&client.txFeeRate)) var commits []*pt.ParacrossCommitAction
for _, stat := range status {
commits = append(commits, &pt.ParacrossCommitAction{Status: stat})
}
if !client.paraClient.subCfg.BlsSignOff {
err = client.blsSign(commits)
if err != nil {
return nil, 0
}
}
signTx, count, err := client.calcCommitMsgTxs(commits, atomic.LoadInt64(&client.txFeeRate))
if err != nil || signTx == nil { if err != nil || signTx == nil {
return nil, 0 return nil, 0
} }
...@@ -376,12 +393,12 @@ func (client *commitMsgClient) getSendingTx(startHeight, endHeight int64) (*type ...@@ -376,12 +393,12 @@ func (client *commitMsgClient) getSendingTx(startHeight, endHeight int64) (*type
return signTx, count return signTx, count
} }
func (client *commitMsgClient) calcCommitMsgTxs(notifications []*pt.ParacrossNodeStatus, feeRate int64) (*types.Transaction, int64, error) { func (client *commitMsgClient) calcCommitMsgTxs(notifications []*pt.ParacrossCommitAction, feeRate int64) (*types.Transaction, int64, error) {
txs, count, err := client.batchCalcTxGroup(notifications, feeRate) txs, count, err := client.batchCalcTxGroup(notifications, feeRate)
if err != nil { if err != nil {
txs, err = client.singleCalcTx((notifications)[0], feeRate) txs, err = client.singleCalcTx((notifications)[0], feeRate)
if err != nil { if err != nil {
plog.Error("single calc tx", "height", notifications[0].Height) plog.Error("single calc tx", "height", notifications[0].Status.Height)
return nil, 0, err return nil, 0, err
} }
...@@ -429,14 +446,14 @@ func (client *commitMsgClient) getExecName(commitHeight int64) string { ...@@ -429,14 +446,14 @@ func (client *commitMsgClient) getExecName(commitHeight int64) string {
} }
func (client *commitMsgClient) batchCalcTxGroup(notifications []*pt.ParacrossNodeStatus, feeRate int64) (*types.Transaction, int, error) { func (client *commitMsgClient) batchCalcTxGroup(notifications []*pt.ParacrossCommitAction, feeRate int64) (*types.Transaction, int, error) {
var rawTxs types.Transactions var rawTxs types.Transactions
cfg := client.paraClient.GetAPI().GetConfig() cfg := client.paraClient.GetAPI().GetConfig()
for _, status := range notifications { for _, notify := range notifications {
execName := client.getExecName(status.Height) execName := client.getExecName(notify.Status.Height)
tx, err := paracross.CreateRawCommitTx4MainChain(cfg, status, execName, feeRate) tx, err := paracross.CreateRawCommitTx4MainChain(cfg, notify, execName, feeRate)
if err != nil { if err != nil {
plog.Error("para get commit tx", "block height", status.Height) plog.Error("para get commit tx", "block height", notify.Status.Height)
return nil, 0, err return nil, 0, err
} }
rawTxs.Txs = append(rawTxs.Txs, tx) rawTxs.Txs = append(rawTxs.Txs, tx)
...@@ -449,12 +466,12 @@ func (client *commitMsgClient) batchCalcTxGroup(notifications []*pt.ParacrossNod ...@@ -449,12 +466,12 @@ func (client *commitMsgClient) batchCalcTxGroup(notifications []*pt.ParacrossNod
return txs, len(notifications), nil return txs, len(notifications), nil
} }
func (client *commitMsgClient) singleCalcTx(status *pt.ParacrossNodeStatus, feeRate int64) (*types.Transaction, error) { func (client *commitMsgClient) singleCalcTx(notify *pt.ParacrossCommitAction, feeRate int64) (*types.Transaction, error) {
cfg := client.paraClient.GetAPI().GetConfig() cfg := client.paraClient.GetAPI().GetConfig()
execName := client.getExecName(status.Height) execName := client.getExecName(notify.Status.Height)
tx, err := paracross.CreateRawCommitTx4MainChain(cfg, status, execName, feeRate) tx, err := paracross.CreateRawCommitTx4MainChain(cfg, notify, execName, feeRate)
if err != nil { if err != nil {
plog.Error("para get commit tx", "block height", status.Height) plog.Error("para get commit tx", "block height", notify.Status.Height)
return nil, err return nil, err
} }
tx.Sign(types.SECP256K1, client.privateKey) tx.Sign(types.SECP256K1, client.privateKey)
...@@ -902,6 +919,10 @@ func (client *commitMsgClient) fetchPriKey() error { ...@@ -902,6 +919,10 @@ func (client *commitMsgClient) fetchPriKey() error {
} }
client.privateKey = priKey client.privateKey = priKey
client.blsPriKey = getBlsPriKey(priKey.Bytes())
client.blsPubKey = g2pubs.PrivToPub(client.blsPriKey)
serial := client.blsPubKey.Serialize()
plog.Info("para commit get pub bls", "final keys", common.ToHex(serial[:]))
plog.Info("para commit fetchPriKey success") plog.Info("para commit fetchPriKey success")
return nil return nil
} }
...@@ -958,3 +979,62 @@ func (client *commitMsgClient) isSelfConsEnable(height int64) bool { ...@@ -958,3 +979,62 @@ func (client *commitMsgClient) isSelfConsEnable(height int64) bool {
} }
return false return false
} }
//to repeat get prikey's hash until in range of bls's private key
func getBlsPriKey(key []byte) *g2pubs.SecretKey {
var newKey [common.Sha256Len]byte
copy(newKey[:], key[:])
for {
plog.Info("para commit getBlsPriKey", "keys", common.ToHex(newKey[:]))
secret := g2pubs.DeserializeSecretKey(newKey)
if nil != secret.GetFRElement() {
serial := secret.Serialize()
plog.Info("para commit getBlsPriKey", "final keys", common.ToHex(serial[:]), "string", secret.String())
return secret
}
copy(newKey[:], common.Sha256(newKey[:]))
}
}
func (client *commitMsgClient) blsSign(commits []*pt.ParacrossCommitAction) error {
nodeStr, err := client.getNodeGroupAddrs()
if err != nil || len(nodeStr) <= 0 {
plog.Info("bls sign", "nodestr", nodeStr, "err", err)
return types.ErrInvalidParam
}
nodes := strings.Split(nodeStr, ",")
bitMap, remains := setAddrsBitMap(nodes, []string{client.authAccount})
if len(remains) > 0 {
plog.Error("bls sign addrs remains", "remains", remains, "nodestr", nodeStr, "bitmap", bitMap, "nodes", nodes)
}
if remains[client.authAccount] {
plog.Error("bls sign addrs miss setmap", "auth", client.authAccount, "remains", remains)
return types.ErrInvalidParam
}
for _, cmt := range commits {
data := types.Encode(cmt.Status)
plog.Debug("blsign msg", "data", common.ToHex(data), "height", cmt.Status.Height, "map", bitMap)
sign := g2pubs.Sign(data, client.blsPriKey).Serialize()
cmt.Bls = &pt.ParacrossCommitBlsInfo{Sign: sign[:], Addrs: bitMap}
}
return nil
}
//设置nodes范围内的bitmap,如果addrs在node不存在,也不设置,返回未命中的addrs
func setAddrsBitMap(nodes, addrs []string) ([]byte, map[string]bool) {
rst := big.NewInt(0)
addrsMap := make(map[string]bool)
for _, n := range addrs {
addrsMap[n] = true
}
for i, a := range nodes {
if _, exist := addrsMap[a]; exist {
rst.SetBit(rst, i, 1)
delete(addrsMap, a)
}
}
return rst.Bytes(), addrsMap
}
...@@ -7,6 +7,8 @@ package para ...@@ -7,6 +7,8 @@ package para
import ( import (
"testing" "testing"
"encoding/hex"
"github.com/33cn/chain33/queue" "github.com/33cn/chain33/queue"
_ "github.com/33cn/chain33/system" _ "github.com/33cn/chain33/system"
drivers "github.com/33cn/chain33/system/consensus" drivers "github.com/33cn/chain33/system/consensus"
...@@ -71,3 +73,10 @@ func TestSetSelfConsEnable(t *testing.T) { ...@@ -71,3 +73,10 @@ func TestSetSelfConsEnable(t *testing.T) {
assert.Equal(t, ep1, para.commitMsgClient.selfConsEnableList) assert.Equal(t, ep1, para.commitMsgClient.selfConsEnableList)
} }
func TestSetAddrsBitMap(t *testing.T) {
nodes := []string{"1KSBd17H7ZK8iT37aJztFB22XGwsPTdwE4", "1JRNjdEqp4LJ5fqycUBm9ayCKSeeskgMKR", "1NLHPEcbTWWxxU3dGUZBhayjrCHD3psX7k", "1MCftFynyvG2F4ED5mdHYgziDxx6vDrScs"}
addrs := []string{"1KSBd17H7ZK8iT37aJztFB22XGwsPTdwE4"}
val, remain := setAddrsBitMap(nodes, addrs)
t.Log("val", hex.EncodeToString(val), "remain", remain)
}
...@@ -64,19 +64,21 @@ func TestCalcCommitMsgTxs(t *testing.T) { ...@@ -64,19 +64,21 @@ func TestCalcCommitMsgTxs(t *testing.T) {
Height: 2, Height: 2,
Title: "user.p.para", Title: "user.p.para",
} }
notify := []*pt.ParacrossNodeStatus{nt1} commit1 := &pt.ParacrossCommitAction{Status: nt1}
notify := []*pt.ParacrossCommitAction{commit1}
tx, count, err := client.calcCommitMsgTxs(notify, 0) tx, count, err := client.calcCommitMsgTxs(notify, 0)
assert.Nil(t, err) assert.Nil(t, err)
assert.Equal(t, int64(1), count) assert.Equal(t, int64(1), count)
assert.NotNil(t, tx) assert.NotNil(t, tx)
notify = append(notify, nt2) commit1 = &pt.ParacrossCommitAction{Status: nt2}
notify = append(notify, commit1)
tx, count, err = client.calcCommitMsgTxs(notify, 0) tx, count, err = client.calcCommitMsgTxs(notify, 0)
assert.Nil(t, err) assert.Nil(t, err)
assert.Equal(t, int64(2), count) assert.Equal(t, int64(2), count)
assert.NotNil(t, tx) assert.NotNil(t, tx)
tx, err = client.singleCalcTx(nt2, 0) tx, err = client.singleCalcTx(commit1, 0)
assert.Nil(t, err) assert.Nil(t, err)
assert.NotNil(t, tx) assert.NotNil(t, tx)
......
...@@ -496,7 +496,8 @@ function para_cross_transfer_withdraw_for_token() { ...@@ -496,7 +496,8 @@ function para_cross_transfer_withdraw_for_token() {
function para_create_nodegroup_gamechain() { function para_create_nodegroup_gamechain() {
echo "=========== # game para chain create node group test =============" echo "=========== # game para chain create node group test ============="
##apply ##apply
txhash=$(${CLI} --paraName user.p.game. send para nodegroup apply -a "1KSBd17H7ZK8iT37aJztFB22XGwsPTdwE4" -c 5 -k 0xd165c84ed37c2a427fea487470ee671b7a0495d68d82607cafbc6348bf23bec5) local KS="0x8293f1e8eab2919910c2d347348d1d344a86e0dd10610ff06211f85c8cd3dfc99d81c36ef0f6ad6ba1db931d1ffbe7321411d80ce76269463301af5cce4128b196e48abced00c536f7be557fd5940ef5a0740c85a871fe81fe940aca9ed329e7"
txhash=$(${CLI} --paraName user.p.game. send para nodegroup apply -a "1KSBd17H7ZK8iT37aJztFB22XGwsPTdwE4" -p "$KS" -c 5 -k 0xd165c84ed37c2a427fea487470ee671b7a0495d68d82607cafbc6348bf23bec5)
echo "tx=$txhash" echo "tx=$txhash"
query_tx "${PARA_CLI5}" "${txhash}" query_tx "${PARA_CLI5}" "${txhash}"
id=$txhash id=$txhash
...@@ -653,7 +654,13 @@ function para_create_nodegroup() { ...@@ -653,7 +654,13 @@ function para_create_nodegroup() {
echo "=========== # para chain create node group again =============" echo "=========== # para chain create node group again ============="
##apply ##apply
txhash=$(${PARA_CLI} send para nodegroup apply -a "1E5saiXVb9mW8wcWUUZjsHJPZs5GmdzuSY,1KSBd17H7ZK8iT37aJztFB22XGwsPTdwE4,1JRNjdEqp4LJ5fqycUBm9ayCKSeeskgMKR,1NLHPEcbTWWxxU3dGUZBhayjrCHD3psX7k,1MCftFynyvG2F4ED5mdHYgziDxx6vDrScs" -c 6 -k 0xd165c84ed37c2a427fea487470ee671b7a0495d68d82607cafbc6348bf23bec5) local E5="0x9293f1e8eab2919910c2d347348d1d344a86e0dd10610ff06211f85c8cd3dfc99d81c36ef0f6ad6ba1db931d1ffbe7321411d80ce76269463301af5cce4128b196e48abced00c536f7be557fd5940ef5a0740c85a871fe81fe940aca9ed329e7"
local KS="0x8293f1e8eab2919910c2d347348d1d344a86e0dd10610ff06211f85c8cd3dfc99d81c36ef0f6ad6ba1db931d1ffbe7321411d80ce76269463301af5cce4128b196e48abced00c536f7be557fd5940ef5a0740c85a871fe81fe940aca9ed329e7"
local JR="0x8ed5ba075c27015e2c6da399b42da4cd272d4082b55f05c85d84b1308ec87bdb4aeea70dbef3e754eae99a6be0c0e49512d7e9197712f8538ce3d57c1b2d88e17b37f0e419f55333f6e841261a8d3151552fd7d4fd8e19f4f38a413395aab26e"
local NL="0x872e3ac07998deb12045ee48c52a8ba5d2538dc85123866fb330112eb0b805ce23f31bfde3a485cd89fac48eab48560005d12f714ca3786c7f47fe3b5edb1dc7838677c041c89cee4caf9225c1d68346bfcde3365ada0a627fbd77bc72e9b356"
local MC="0x87c58bb6cce41842462a0030335bb95948dcfba77e47e2d8ee893c0b2c34ac20d08c9e98a883ef2a6492d0ad808ace9a1730e8bae5d3b0861aaf743449df5de510073e2991c7274cab47f327e48d7eacf300e4b24174dae2e8603d1904b8a015"
local blspubs=$E5","$KS","$JR","$NL","$MC
txhash=$(${PARA_CLI} send para nodegroup apply -a "1E5saiXVb9mW8wcWUUZjsHJPZs5GmdzuSY,1KSBd17H7ZK8iT37aJztFB22XGwsPTdwE4,1JRNjdEqp4LJ5fqycUBm9ayCKSeeskgMKR,1NLHPEcbTWWxxU3dGUZBhayjrCHD3psX7k,1MCftFynyvG2F4ED5mdHYgziDxx6vDrScs" -p "$blspubs" -c 6 -k 0xd165c84ed37c2a427fea487470ee671b7a0495d68d82607cafbc6348bf23bec5)
echo "tx=$txhash" echo "tx=$txhash"
query_tx "${PARA_CLI}" "${txhash}" query_tx "${PARA_CLI}" "${txhash}"
id=$txhash id=$txhash
......
...@@ -327,6 +327,16 @@ func superNodeCmd() *cobra.Command { ...@@ -327,6 +327,16 @@ func superNodeCmd() *cobra.Command {
return cmd return cmd
} }
func nodeJoinCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "join",
Short: "super node apply for join nodegroup cmd",
Run: createNodeJoinTx,
}
addNodeJoinFlags(cmd)
return cmd
}
func addNodeJoinFlags(cmd *cobra.Command) { func addNodeJoinFlags(cmd *cobra.Command) {
cmd.Flags().StringP("addr", "a", "", "target join addr") cmd.Flags().StringP("addr", "a", "", "target join addr")
cmd.MarkFlagRequired("addr") cmd.MarkFlagRequired("addr")
...@@ -356,13 +366,13 @@ func createNodeJoinTx(cmd *cobra.Command, args []string) { ...@@ -356,13 +366,13 @@ func createNodeJoinTx(cmd *cobra.Command, args []string) {
ctx.RunWithoutMarshal() ctx.RunWithoutMarshal()
} }
func nodeJoinCmd() *cobra.Command { func nodeVoteCmd() *cobra.Command {
cmd := &cobra.Command{ cmd := &cobra.Command{
Use: "join", Use: "vote",
Short: "super node apply for join nodegroup cmd", Short: "nodegroup nodes vote for new join node cmd",
Run: createNodeJoinTx, Run: createNodeVoteTx,
} }
addNodeJoinFlags(cmd) addNodeVoteFlags(cmd)
return cmd return cmd
} }
...@@ -395,13 +405,13 @@ func createNodeVoteTx(cmd *cobra.Command, args []string) { ...@@ -395,13 +405,13 @@ func createNodeVoteTx(cmd *cobra.Command, args []string) {
} }
func nodeVoteCmd() *cobra.Command { func nodeQuitCmd() *cobra.Command {
cmd := &cobra.Command{ cmd := &cobra.Command{
Use: "vote", Use: "quit",
Short: "nodegroup nodes vote for new join node cmd", Short: "super node apply for quit nodegroup cmd",
Run: createNodeVoteTx, Run: createNodeQuitTx,
} }
addNodeVoteFlags(cmd) addNodeQuitFlags(cmd)
return cmd return cmd
} }
...@@ -431,13 +441,13 @@ func createNodeQuitTx(cmd *cobra.Command, args []string) { ...@@ -431,13 +441,13 @@ func createNodeQuitTx(cmd *cobra.Command, args []string) {
} }
func nodeQuitCmd() *cobra.Command { func nodeCancelCmd() *cobra.Command {
cmd := &cobra.Command{ cmd := &cobra.Command{
Use: "quit", Use: "cancel",
Short: "super node apply for quit nodegroup cmd", Short: "super node cancel join or quit action by id cmd",
Run: createNodeQuitTx, Run: createNodeCancelTx,
} }
addNodeQuitFlags(cmd) addNodeCancelFlags(cmd)
return cmd return cmd
} }
...@@ -467,16 +477,45 @@ func createNodeCancelTx(cmd *cobra.Command, args []string) { ...@@ -467,16 +477,45 @@ func createNodeCancelTx(cmd *cobra.Command, args []string) {
} }
func nodeCancelCmd() *cobra.Command { func nodeModifyCmd() *cobra.Command {
cmd := &cobra.Command{ cmd := &cobra.Command{
Use: "cancel", Use: "modify",
Short: "super node cancel join or quit action by id cmd", Short: "super node modify parameters",
Run: createNodeCancelTx, Run: createNodeModifyTx,
} }
addNodeCancelFlags(cmd) addNodeCancelFlags(cmd)
return cmd return cmd
} }
func addNodeModifyFlags(cmd *cobra.Command) {
cmd.Flags().StringP("addr", "a", "", "operating target apply id")
cmd.MarkFlagRequired("addr")
cmd.Flags().StringP("pubkey", "p", "", "operating target apply id")
cmd.MarkFlagRequired("pubkey")
}
func createNodeModifyTx(cmd *cobra.Command, args []string) {
paraName, _ := cmd.Flags().GetString("paraName")
addr, _ := cmd.Flags().GetString("addr")
pubkey, _ := cmd.Flags().GetString("pubkey")
if !strings.HasPrefix(paraName, "user.p") {
fmt.Fprintln(os.Stderr, "paraName is not right, paraName format like `user.p.guodun.`")
return
}
payload := &pt.ParaNodeAddrConfig{Title: paraName, Op: pt.ParaOpModify, Addr: addr, BlsPubKey: pubkey}
params := &rpctypes.CreateTxIn{
Execer: getRealExecName(paraName, pt.ParaX),
ActionName: "NodeConfig",
Payload: types.MustPBToJSON(payload),
}
rpcLaddr, _ := cmd.Flags().GetString("rpc_laddr")
ctx := jsonclient.NewRPCCtx(rpcLaddr, "Chain33.CreateTransaction", params, nil)
ctx.RunWithoutMarshal()
}
// getNodeInfoCmd get node current status // getNodeInfoCmd get node current status
func getNodeInfoCmd() *cobra.Command { func getNodeInfoCmd() *cobra.Command {
cmd := &cobra.Command{ cmd := &cobra.Command{
...@@ -739,10 +778,22 @@ func nodeGroupCmd() *cobra.Command { ...@@ -739,10 +778,22 @@ func nodeGroupCmd() *cobra.Command {
return cmd return cmd
} }
func nodeGroupApplyCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "apply",
Short: "apply for para chain's super node group",
Run: nodeGroupApply,
}
addNodeGroupApplyCmdFlags(cmd)
return cmd
}
func addNodeGroupApplyCmdFlags(cmd *cobra.Command) { func addNodeGroupApplyCmdFlags(cmd *cobra.Command) {
cmd.Flags().StringP("addrs", "a", "", "addrs apply for super node,split by ',' ") cmd.Flags().StringP("addrs", "a", "", "addrs apply for super node,split by ',' ")
cmd.MarkFlagRequired("addrs") cmd.MarkFlagRequired("addrs")
cmd.Flags().StringP("blspubs", "p", "", "bls sign pub key for addr's private key,split by ',' (optional)")
cmd.Flags().Float64P("coins", "c", 0, "coins amount to frozen, not less config") cmd.Flags().Float64P("coins", "c", 0, "coins amount to frozen, not less config")
cmd.MarkFlagRequired("coins") cmd.MarkFlagRequired("coins")
...@@ -751,6 +802,7 @@ func addNodeGroupApplyCmdFlags(cmd *cobra.Command) { ...@@ -751,6 +802,7 @@ func addNodeGroupApplyCmdFlags(cmd *cobra.Command) {
func nodeGroupApply(cmd *cobra.Command, args []string) { func nodeGroupApply(cmd *cobra.Command, args []string) {
paraName, _ := cmd.Flags().GetString("paraName") paraName, _ := cmd.Flags().GetString("paraName")
addrs, _ := cmd.Flags().GetString("addrs") addrs, _ := cmd.Flags().GetString("addrs")
blspubs, _ := cmd.Flags().GetString("blspubs")
coins, _ := cmd.Flags().GetFloat64("coins") coins, _ := cmd.Flags().GetFloat64("coins")
if !strings.HasPrefix(paraName, "user.p") { if !strings.HasPrefix(paraName, "user.p") {
...@@ -758,7 +810,7 @@ func nodeGroupApply(cmd *cobra.Command, args []string) { ...@@ -758,7 +810,7 @@ func nodeGroupApply(cmd *cobra.Command, args []string) {
return return
} }
payload := &pt.ParaNodeGroupConfig{Title: paraName, Op: 1, Addrs: addrs, CoinsFrozen: int64(math.Trunc((coins+0.0000001)*1e4)) * 1e4} payload := &pt.ParaNodeGroupConfig{Title: paraName, Op: 1, Addrs: addrs, BlsPubKeys: blspubs, CoinsFrozen: int64(math.Trunc((coins+0.0000001)*1e4)) * 1e4}
params := &rpctypes.CreateTxIn{ params := &rpctypes.CreateTxIn{
Execer: getRealExecName(paraName, pt.ParaX), Execer: getRealExecName(paraName, pt.ParaX),
ActionName: "NodeGroupConfig", ActionName: "NodeGroupConfig",
...@@ -770,16 +822,6 @@ func nodeGroupApply(cmd *cobra.Command, args []string) { ...@@ -770,16 +822,6 @@ func nodeGroupApply(cmd *cobra.Command, args []string) {
ctx.RunWithoutMarshal() ctx.RunWithoutMarshal()
} }
func nodeGroupApplyCmd() *cobra.Command {
cmd := &cobra.Command{
Use: "apply",
Short: "apply for para chain's super node group",
Run: nodeGroupApply,
}
addNodeGroupApplyCmdFlags(cmd)
return cmd
}
func addNodeGroupApproveCmdFlags(cmd *cobra.Command) { func addNodeGroupApproveCmdFlags(cmd *cobra.Command) {
cmd.Flags().StringP("id", "i", "", "apply id for nodegroup ") cmd.Flags().StringP("id", "i", "", "apply id for nodegroup ")
cmd.MarkFlagRequired("id") cmd.MarkFlagRequired("id")
......
...@@ -17,6 +17,7 @@ import ( ...@@ -17,6 +17,7 @@ import (
"github.com/33cn/chain33/util" "github.com/33cn/chain33/util"
pt "github.com/33cn/plugin/plugin/dapp/paracross/types" pt "github.com/33cn/plugin/plugin/dapp/paracross/types"
"github.com/golang/protobuf/proto" "github.com/golang/protobuf/proto"
"github.com/phoreproject/bls/g2pubs"
"github.com/pkg/errors" "github.com/pkg/errors"
) )
...@@ -97,34 +98,37 @@ func validNode(addr string, nodes map[string]struct{}) bool { ...@@ -97,34 +98,37 @@ func validNode(addr string, nodes map[string]struct{}) bool {
return false return false
} }
func checkCommitInfo(cfg *types.Chain33Config, commit *pt.ParacrossCommitAction) error { func checkCommitInfo(cfg *types.Chain33Config, commit *pt.ParacrossNodeStatus) error {
if commit.Status == nil { if commit == nil {
return types.ErrInvalidParam return types.ErrInvalidParam
} }
clog.Debug("paracross.Commit check input", "height", commit.Status.Height, "mainHeight", commit.Status.MainBlockHeight, clog.Debug("paracross.Commit check input", "height", commit.Height, "mainHeight", commit.MainBlockHeight,
"mainHash", common.ToHex(commit.Status.MainBlockHash), "blockHash", common.ToHex(commit.Status.BlockHash)) "mainHash", common.ToHex(commit.MainBlockHash), "blockHash", common.ToHex(commit.BlockHash))
if commit.Status.Height == 0 { if commit.Height == 0 {
if len(commit.Status.Title) == 0 || len(commit.Status.BlockHash) == 0 { if len(commit.Title) == 0 || len(commit.BlockHash) == 0 {
return types.ErrInvalidParam return types.ErrInvalidParam
} }
return nil return nil
} }
if !pt.IsParaForkHeight(cfg, commit.Status.MainBlockHeight, pt.ForkLoopCheckCommitTxDone) { if !pt.IsParaForkHeight(cfg, commit.MainBlockHeight, pt.ForkLoopCheckCommitTxDone) {
if len(commit.Status.MainBlockHash) == 0 || len(commit.Status.Title) == 0 || commit.Status.Height < 0 || if len(commit.MainBlockHash) == 0 || len(commit.Title) == 0 || commit.Height < 0 ||
len(commit.Status.PreBlockHash) == 0 || len(commit.Status.BlockHash) == 0 || len(commit.PreBlockHash) == 0 || len(commit.BlockHash) == 0 ||
len(commit.Status.StateHash) == 0 || len(commit.Status.PreStateHash) == 0 { len(commit.StateHash) == 0 || len(commit.PreStateHash) == 0 {
return types.ErrInvalidParam return types.ErrInvalidParam
} }
return nil return nil
} }
if len(commit.Status.MainBlockHash) == 0 || len(commit.Status.BlockHash) == 0 || if len(commit.MainBlockHash) == 0 || len(commit.BlockHash) == 0 ||
commit.Status.MainBlockHeight < 0 || commit.Status.Height < 0 { commit.MainBlockHeight < 0 || commit.Height < 0 {
return types.ErrInvalidParam return types.ErrInvalidParam
} }
if !validTitle(cfg, commit.Title) {
return pt.ErrInvalidTitle
}
return nil return nil
} }
...@@ -133,11 +137,11 @@ func isCommitDone(nodes map[string]struct{}, mostSame int) bool { ...@@ -133,11 +137,11 @@ func isCommitDone(nodes map[string]struct{}, mostSame int) bool {
return 3*mostSame > 2*len(nodes) return 3*mostSame > 2*len(nodes)
} }
func makeCommitReceipt(addr string, commit *pt.ParacrossCommitAction, prev, current *pt.ParacrossHeightStatus) *types.Receipt { func makeCommitReceipt(addr string, commit *pt.ParacrossNodeStatus, prev, current *pt.ParacrossHeightStatus) *types.Receipt {
key := calcTitleHeightKey(commit.Status.Title, commit.Status.Height) key := calcTitleHeightKey(commit.Title, commit.Height)
log := &pt.ReceiptParacrossCommit{ log := &pt.ReceiptParacrossCommit{
Addr: addr, Addr: addr,
Status: commit.Status, Status: commit,
Prev: prev, Prev: prev,
Current: current, Current: current,
} }
...@@ -166,10 +170,10 @@ func makeCommitStatReceipt(current *pt.ParacrossHeightStatus) *types.Receipt { ...@@ -166,10 +170,10 @@ func makeCommitStatReceipt(current *pt.ParacrossHeightStatus) *types.Receipt {
} }
} }
func makeRecordReceipt(addr string, commit *pt.ParacrossCommitAction) *types.Receipt { func makeRecordReceipt(addr string, commit *pt.ParacrossNodeStatus) *types.Receipt {
log := &pt.ReceiptParacrossRecord{ log := &pt.ReceiptParacrossRecord{
Addr: addr, Addr: addr,
Status: commit.Status, Status: commit,
} }
return &types.Receipt{ return &types.Receipt{
Ty: types.ExecOk, Ty: types.ExecOk,
...@@ -262,35 +266,35 @@ func hasCommited(addrs []string, addr string) (bool, int) { ...@@ -262,35 +266,35 @@ func hasCommited(addrs []string, addr string) (bool, int) {
return false, 0 return false, 0
} }
func getConfigNodes(db dbm.KV, title string) (map[string]struct{}, []byte, error) { func getConfigNodes(db dbm.KV, title string) (map[string]struct{}, []string, []byte, error) {
key := calcParaNodeGroupAddrsKey(title) key := calcParaNodeGroupAddrsKey(title)
nodes, _, err := getNodes(db, key) nodes, nodesArray, err := getNodes(db, key)
if err != nil { if err != nil {
if errors.Cause(err) != pt.ErrTitleNotExist { if errors.Cause(err) != pt.ErrTitleNotExist {
return nil, nil, errors.Wrapf(err, "getNodes para for title:%s", title) return nil, nil, nil, errors.Wrapf(err, "getNodes para for title:%s", title)
} }
key = calcManageConfigNodesKey(title) key = calcManageConfigNodesKey(title)
nodes, _, err = getNodes(db, key) nodes, nodesArray, err = getNodes(db, key)
if err != nil { if err != nil {
return nil, nil, errors.Wrapf(err, "getNodes manager for title:%s", title) return nil, nil, nil, errors.Wrapf(err, "getNodes manager for title:%s", title)
} }
} }
return nodes, key, nil return nodes, nodesArray, key, nil
} }
func (a *action) getNodesGroup(title string) (map[string]struct{}, error) { func (a *action) getNodesGroup(title string) (map[string]struct{}, []string, error) {
cfg := a.api.GetConfig() cfg := a.api.GetConfig()
if a.exec.GetMainHeight() < pt.GetDappForkHeight(cfg, pt.ForkCommitTx) { if a.exec.GetMainHeight() < pt.GetDappForkHeight(cfg, pt.ForkCommitTx) {
nodes, _, err := getConfigManageNodes(a.db, title) nodes, nodesArray, err := getConfigManageNodes(a.db, title)
if err != nil { if err != nil {
return nil, errors.Wrapf(err, "getNodes for title:%s", title) return nil, nil, errors.Wrapf(err, "getNodes for title:%s", title)
} }
return nodes, nil return nodes, nodesArray, nil
} }
nodes, _, err := getConfigNodes(a.db, title) nodes, nodesArray, _, err := getConfigNodes(a.db, title)
return nodes, err return nodes, nodesArray, err
} }
...@@ -319,47 +323,50 @@ func updateCommitAddrs(stat *pt.ParacrossHeightStatus, nodes map[string]struct{} ...@@ -319,47 +323,50 @@ func updateCommitAddrs(stat *pt.ParacrossHeightStatus, nodes map[string]struct{}
} }
func (a *action) Commit(commit *pt.ParacrossCommitAction) (*types.Receipt, error) { //自共识分阶段使能,综合考虑挖矿奖励和共识分配奖励,判断是否自共识使能需要采用共识的高度,而不能采用当前区块高度a.height
cfg := a.api.GetConfig() //考虑自共识使能区块高度100,如果采用区块高度判断,则在100高度可能收到80~99的20条共识交易,这20条交易在100高度参与共识,则无奖励可分配,而且共识高度将是80而不是100
if cfg.IsPara() && cfg.IsDappFork(commit.Status.Height, pt.ParaX, pt.ForkParaSelfConsStages) { //采用共识高度commit.Status.Height判断,则严格执行了产生奖励和分配奖励,且共识高度从100开始
//分叉之后,key不存在,自共识没配置也认为不支持自共识 func paraCheckSelfConsOn(cfg *types.Chain33Config, db dbm.KV, commit *pt.ParacrossNodeStatus) (bool, *types.Receipt, error) {
isSelfConsOn, err := isSelfConsOn(a.db, commit.Status.Height) if !cfg.IsDappFork(commit.Height, pt.ParaX, pt.ForkParaSelfConsStages) {
if err != nil && errors.Cause(err) != pt.ErrKeyNotExist { return true, nil, nil
return nil, err
}
if !isSelfConsOn {
clog.Debug("paracross.Commit self consens off", "height", commit.Status.Height)
return &types.Receipt{Ty: types.ExecOk}, nil
}
} }
err := checkCommitInfo(cfg, commit)
if err != nil { //分叉之后,key不存在,自共识没配置也认为不支持自共识
return nil, err isSelfConsOn, err := isSelfConsOn(db, commit.Height)
if err != nil && errors.Cause(err) != pt.ErrKeyNotExist {
return false, nil, err
} }
if !validTitle(cfg, commit.Status.Title) { if !isSelfConsOn {
return nil, pt.ErrInvalidTitle clog.Debug("paracross.Commit self consens off", "height", commit.Height)
return false, &types.Receipt{Ty: types.ExecOk}, nil
} }
return true, nil, nil
}
nodes, err := a.getNodesGroup(commit.Status.Title) func (a *action) preCheckCommitInfo(commit *pt.ParacrossNodeStatus) error {
cfg := a.api.GetConfig()
err := checkCommitInfo(cfg, commit)
if err != nil { if err != nil {
return nil, err return err
} }
if !validNode(a.fromaddr, nodes) { nodesMap, _, err := a.getNodesGroup(commit.Title)
return nil, errors.Wrapf(pt.ErrNodeNotForTheTitle, "not validNode:%s", a.fromaddr) if err != nil {
return err
}
if !validNode(a.fromaddr, nodesMap) {
return errors.Wrapf(pt.ErrNodeNotForTheTitle, "not validNode:%s", a.fromaddr)
} }
titleStatus, err := getTitle(a.db, calcTitleKey(commit.Status.Title)) titleStatus, err := getTitle(a.db, calcTitleKey(commit.Title))
if err != nil { if err != nil {
return nil, errors.Wrapf(err, "getTitle:%s", a.fromaddr) return errors.Wrapf(err, "getTitle:%s", a.fromaddr)
} }
if titleStatus.Height+1 == commit.Height && commit.Height > 0 && !pt.IsParaForkHeight(cfg, commit.MainBlockHeight, pt.ForkLoopCheckCommitTxDone) {
if titleStatus.Height+1 == commit.Status.Height && commit.Status.Height > 0 && !pt.IsParaForkHeight(cfg, commit.Status.MainBlockHeight, pt.ForkLoopCheckCommitTxDone) { if !bytes.Equal(titleStatus.BlockHash, commit.PreBlockHash) {
if !bytes.Equal(titleStatus.BlockHash, commit.Status.PreBlockHash) {
clog.Error("paracross.Commit", "check PreBlockHash", common.ToHex(titleStatus.BlockHash), clog.Error("paracross.Commit", "check PreBlockHash", common.ToHex(titleStatus.BlockHash),
"commit tx", common.ToHex(commit.Status.PreBlockHash), "commitheit", commit.Status.Height, "commit tx", common.ToHex(commit.PreBlockHash), "commitheit", commit.Height, "from", a.fromaddr)
"from", a.fromaddr) return pt.ErrParaBlockHashNoMatch
return nil, pt.ErrParaBlockHashNoMatch
} }
} }
...@@ -369,41 +376,98 @@ func (a *action) Commit(commit *pt.ParacrossCommitAction) (*types.Receipt, error ...@@ -369,41 +376,98 @@ func (a *action) Commit(commit *pt.ParacrossCommitAction) (*types.Receipt, error
// 所以有必要做这个检测 // 所以有必要做这个检测
var dbMainHash []byte var dbMainHash []byte
if !cfg.IsPara() { if !cfg.IsPara() {
blockHash, err := getBlockHash(a.api, commit.Status.MainBlockHeight) blockHash, err := getBlockHash(a.api, commit.MainBlockHeight)
if err != nil { if err != nil {
clog.Error("paracross.Commit getBlockHash", "err", err, clog.Error("paracross.Commit getBlockHash", "err", err, "commit tx height", commit.MainBlockHeight, "from", a.fromaddr)
"commit tx height", commit.Status.MainBlockHeight, "from", a.fromaddr) return err
return nil, err
} }
dbMainHash = blockHash.Hash dbMainHash = blockHash.Hash
} else { } else {
block, err := getBlockInfo(a.api, commit.Status.Height) block, err := getBlockInfo(a.api, commit.Height)
if err != nil { if err != nil {
clog.Error("paracross.Commit getBlockInfo", "err", err, "height", commit.Status.Height, "from", a.fromaddr) clog.Error("paracross.Commit getBlockInfo", "err", err, "height", commit.Height, "from", a.fromaddr)
return nil, err return err
} }
dbMainHash = block.MainHash dbMainHash = block.MainHash
} }
//对于主链,校验的是主链高度对应的blockhash是否和commit的一致 //对于主链,校验的是主链高度对应的blockhash是否和commit的一致
//对于平行链, 校验的是commit信息的平行链height block对应的mainHash是否和本地相同高度对应的mainHash一致, 在主链hash一致的时候看平行链共识blockhash是否一致 //对于平行链, 校验的是commit信息的平行链height block对应的mainHash是否和本地相同高度对应的mainHash一致, 在主链hash一致的时候看平行链共识blockhash是否一致
if !bytes.Equal(dbMainHash, commit.Status.MainBlockHash) && commit.Status.Height > 0 { if !bytes.Equal(dbMainHash, commit.MainBlockHash) && commit.Height > 0 {
clog.Error("paracross.Commit blockHash not match", "isMain", !cfg.IsPara(), "db", common.ToHex(dbMainHash), clog.Error("paracross.Commit blockHash not match", "isMain", !cfg.IsPara(), "db", common.ToHex(dbMainHash),
"commit", common.ToHex(commit.Status.MainBlockHash), "commitHeight", commit.Status.Height, "commit", common.ToHex(commit.MainBlockHash), "commitHeight", commit.Height,
"commitMainHeight", commit.Status.MainBlockHeight, "from", a.fromaddr) "commitMainHeight", commit.MainBlockHeight, "from", a.fromaddr)
return nil, types.ErrBlockHashNoMatch return types.ErrBlockHashNoMatch
}
return nil
}
//共识commit msg 处理
func (a *action) Commit(commit *pt.ParacrossCommitAction) (*types.Receipt, error) {
cfg := a.api.GetConfig()
//平行链侧,自共识未使能则不处理
if cfg.IsPara() {
isSelfConsOn, receipt, err := paraCheckSelfConsOn(cfg, a.db, commit.Status)
if !isSelfConsOn {
return receipt, err
}
}
err := a.preCheckCommitInfo(commit.Status)
if err != nil {
return nil, err
}
if commit.Bls != nil {
return a.commitBls(commit)
}
return a.proCommitMsg(commit.Status, a.fromaddr)
}
//bls签名共识交易处理
func (a *action) commitBls(commit *pt.ParacrossCommitAction) (*types.Receipt, error) {
commitAddrs, err := a.verifyBlsSign(commit)
if err != nil {
clog.Error("paracross.Commit verifyBlsSign failed", "err", err)
return nil, err
}
receipt := &types.Receipt{Ty: types.ExecOk}
for _, addr := range commitAddrs {
r, err := a.proCommitMsg(commit.Status, addr)
if err != nil {
clog.Error("paracross.CommitBls proCommitMsg failed", "err", err)
return nil, err
}
receipt = mergeReceipt(receipt, r)
}
return receipt, nil
}
func (a *action) proCommitMsg(commit *pt.ParacrossNodeStatus, commitAddr string) (*types.Receipt, error) {
cfg := a.api.GetConfig()
nodes, _, err := a.getNodesGroup(commit.Title)
if err != nil {
return nil, err
}
titleStatus, err := getTitle(a.db, calcTitleKey(commit.Title))
if err != nil {
return nil, errors.Wrapf(err, "getTitle:%s", a.fromaddr)
} }
clog.Debug("paracross.Commit check input done")
// 在完成共识之后来的, 增加 record log, 只记录不修改已经达成的共识 // 在完成共识之后来的, 增加 record log, 只记录不修改已经达成的共识
if commit.Status.Height <= titleStatus.Height { if commit.Height <= titleStatus.Height {
clog.Debug("paracross.Commit record", "node", a.fromaddr, "titile", commit.Status.Title, "height", commit.Status.Height) clog.Debug("paracross.Commit record", "node", commitAddr, "titile", commit.Title, "height", commit.Height)
return makeRecordReceipt(a.fromaddr, commit), nil return makeRecordReceipt(commitAddr, commit), nil
} }
// 未共识处理, 接受当前高度以及后续高度 // 未共识处理, 接受当前高度以及后续高度
stat, err := getTitleHeight(a.db, calcTitleHeightKey(commit.Status.Title, commit.Status.Height)) stat, err := getTitleHeight(a.db, calcTitleHeightKey(commit.Title, commit.Height))
if err != nil && !isNotFound(err) { if err != nil && !isNotFound(err) {
clog.Error("paracross.Commit getTitleHeight failed", "err", err) clog.Error("paracross.Commit getTitleHeight failed", "err", err)
return nil, err return nil, err
...@@ -413,46 +477,46 @@ func (a *action) Commit(commit *pt.ParacrossCommitAction) (*types.Receipt, error ...@@ -413,46 +477,46 @@ func (a *action) Commit(commit *pt.ParacrossCommitAction) (*types.Receipt, error
if isNotFound(err) { if isNotFound(err) {
stat = &pt.ParacrossHeightStatus{ stat = &pt.ParacrossHeightStatus{
Status: pt.ParacrossStatusCommiting, Status: pt.ParacrossStatusCommiting,
Title: commit.Status.Title, Title: commit.Title,
Height: commit.Status.Height, Height: commit.Height,
Details: &pt.ParacrossStatusDetails{ Details: &pt.ParacrossStatusDetails{
Addrs: []string{a.fromaddr}, Addrs: []string{commitAddr},
BlockHash: [][]byte{commit.Status.BlockHash}, BlockHash: [][]byte{commit.BlockHash},
}, },
} }
if pt.IsParaForkHeight(cfg, a.exec.GetMainHeight(), pt.ForkCommitTx) { if pt.IsParaForkHeight(cfg, a.exec.GetMainHeight(), pt.ForkCommitTx) {
stat.MainHeight = commit.Status.MainBlockHeight stat.MainHeight = commit.MainBlockHeight
stat.MainHash = commit.Status.MainBlockHash stat.MainHash = commit.MainBlockHash
} }
//用commit.MainBlockHeight 判断更准确,如果用a.exec.MainHeight也可以,但是可能收到MainHeight之前的高度共识tx, //用commit.MainBlockHeight 判断更准确,如果用a.exec.MainHeight也可以,但是可能收到MainHeight之前的高度共识tx,
// 后面loopCommitTxDone时候也是用当前共识高度大于分叉高度判断 // 后面loopCommitTxDone时候也是用当前共识高度大于分叉高度判断
if pt.IsParaForkHeight(cfg, commit.Status.MainBlockHeight, pt.ForkLoopCheckCommitTxDone) { if pt.IsParaForkHeight(cfg, commit.MainBlockHeight, pt.ForkLoopCheckCommitTxDone) {
stat.BlockDetails = &pt.ParacrossStatusBlockDetails{} stat.BlockDetails = &pt.ParacrossStatusBlockDetails{}
updateCommitBlockHashs(stat, commit.Status) updateCommitBlockHashs(stat, commit)
} }
receipt = makeCommitReceipt(a.fromaddr, commit, nil, stat) receipt = makeCommitReceipt(commitAddr, commit, nil, stat)
} else { } else {
copyStat := proto.Clone(stat).(*pt.ParacrossHeightStatus) copyStat := proto.Clone(stat).(*pt.ParacrossHeightStatus)
// 如有分叉, 同一个节点可能再次提交commit交易 // 如有分叉, 同一个节点可能再次提交commit交易
found, index := hasCommited(stat.Details.Addrs, a.fromaddr) found, index := hasCommited(stat.Details.Addrs, commitAddr)
if found { if found {
stat.Details.BlockHash[index] = commit.Status.BlockHash stat.Details.BlockHash[index] = commit.BlockHash
if pt.IsParaForkHeight(cfg, commit.Status.MainBlockHeight, pt.ForkLoopCheckCommitTxDone) { if pt.IsParaForkHeight(cfg, commit.MainBlockHeight, pt.ForkLoopCheckCommitTxDone) {
updateCommitBlockHashs(stat, commit.Status) updateCommitBlockHashs(stat, commit)
} }
} else { } else {
stat.Details.Addrs = append(stat.Details.Addrs, a.fromaddr) stat.Details.Addrs = append(stat.Details.Addrs, commitAddr)
stat.Details.BlockHash = append(stat.Details.BlockHash, commit.Status.BlockHash) stat.Details.BlockHash = append(stat.Details.BlockHash, commit.BlockHash)
if pt.IsParaForkHeight(cfg, commit.Status.MainBlockHeight, pt.ForkLoopCheckCommitTxDone) { if pt.IsParaForkHeight(cfg, commit.MainBlockHeight, pt.ForkLoopCheckCommitTxDone) {
updateCommitBlockHashs(stat, commit.Status) updateCommitBlockHashs(stat, commit)
} }
} }
receipt = makeCommitReceipt(a.fromaddr, commit, copyStat, stat) receipt = makeCommitReceipt(commitAddr, commit, copyStat, stat)
} }
//平行链fork pt.ForkCommitTx=0,主链在ForkCommitTx后支持nodegroup,这里平行链dappFork一定为true //平行链fork pt.ForkCommitTx=0,主链在ForkCommitTx后支持nodegroup,这里平行链dappFork一定为true
if cfg.IsDappFork(commit.Status.MainBlockHeight, pt.ParaX, pt.ForkCommitTx) { if cfg.IsDappFork(commit.MainBlockHeight, pt.ParaX, pt.ForkCommitTx) {
updateCommitAddrs(stat, nodes) updateCommitAddrs(stat, nodes)
} }
saveTitleHeight(a.db, calcTitleHeightKey(stat.Title, stat.Height), stat) saveTitleHeight(a.db, calcTitleHeightKey(stat.Title, stat.Height), stat)
...@@ -462,8 +526,8 @@ func (a *action) Commit(commit *pt.ParacrossCommitAction) (*types.Receipt, error ...@@ -462,8 +526,8 @@ func (a *action) Commit(commit *pt.ParacrossCommitAction) (*types.Receipt, error
receipt = mergeReceipt(receipt, r) receipt = mergeReceipt(receipt, r)
} }
if commit.Status.Height > titleStatus.Height+1 { if commit.Height > titleStatus.Height+1 {
saveTitleHeight(a.db, calcTitleHeightKey(commit.Status.Title, commit.Status.Height), stat) saveTitleHeight(a.db, calcTitleHeightKey(commit.Title, commit.Height), stat)
//平行链由主链共识无缝切换,即接收第一个收到的高度,可以不从0开始 //平行链由主链共识无缝切换,即接收第一个收到的高度,可以不从0开始
allow, err := a.isAllowConsensJump(commit, titleStatus) allow, err := a.isAllowConsensJump(commit, titleStatus)
if err != nil { if err != nil {
...@@ -474,7 +538,7 @@ func (a *action) Commit(commit *pt.ParacrossCommitAction) (*types.Receipt, error ...@@ -474,7 +538,7 @@ func (a *action) Commit(commit *pt.ParacrossCommitAction) (*types.Receipt, error
return receipt, nil return receipt, nil
} }
} }
r, err := a.commitTxDone(commit.Status, stat, titleStatus, nodes) r, err := a.commitTxDone(commit, stat, titleStatus, nodes)
if err != nil { if err != nil {
return nil, err return nil, err
} }
...@@ -482,6 +546,64 @@ func (a *action) Commit(commit *pt.ParacrossCommitAction) (*types.Receipt, error ...@@ -482,6 +546,64 @@ func (a *action) Commit(commit *pt.ParacrossCommitAction) (*types.Receipt, error
return receipt, nil return receipt, nil
} }
func (a *action) verifyBlsSign(commit *pt.ParacrossCommitAction) ([]string, error) {
_, nodesArry, err := a.getNodesGroup(commit.Status.Title)
if err != nil {
return nil, err
}
//1. 获取addr对应的bls 公钥
signAddrs := getAddrsByBitMap(nodesArry, commit.Bls.Addrs)
var pubs []string
for _, addr := range signAddrs {
pub, err := getAddrBlsPubKey(a.db, commit.Status.Title, addr)
if err != nil {
clog.Error("verifyBlsSign pub key not exist", "addr", addr)
return nil, err
}
pubs = append(pubs, pub)
}
pubKeys := make([]*g2pubs.PublicKey, 0)
for _, p := range pubs {
k := [96]byte{}
val, err := common.FromHex(p)
if err != nil {
clog.Error("verifyBlsSign.fromhex", "p", p)
return nil, err
}
copy(k[:], val)
key, err := g2pubs.DeserializePublicKey(k)
if err != nil {
clog.Error("verifyBlsSign.DeserializePublicKey", "key", p)
return nil, err
}
pubKeys = append(pubKeys, key)
}
//2. 聚合公钥
aPub := g2pubs.AggregatePublicKeys(pubKeys)
//3. 获取聚合的签名
signkey := [48]byte{}
copy(signkey[:], commit.Bls.Sign)
sign, err := g2pubs.DeserializeSignature(signkey)
if err != nil {
clog.Error("verifyBlsSign.DeserializeSignature", "key", common.ToHex(commit.Bls.Sign))
return nil, err
}
//4. 获取签名前原始msg
msg := types.Encode(commit.Status)
if !g2pubs.Verify(msg, aPub, sign) {
clog.Error("paracross.Commit bls sign verify", "title", commit.Status.Title, "height", commit.Status.Height,
"addrsMap", common.ToHex(commit.Bls.Addrs), "sign", common.ToHex(commit.Bls.Sign), "addr", signAddrs, "nodes", nodesArry)
clog.Error("paracross.commit bls sign verify", "data", common.ToHex(msg), "height", commit.Status.Height)
return nil, pt.ErrBlsSignVerify
}
return signAddrs, nil
}
//分叉以前stat里面只记录了blockhash的信息,没有crossTxHash等信息,无法通过stat直接重构出mostCommitStatus //分叉以前stat里面只记录了blockhash的信息,没有crossTxHash等信息,无法通过stat直接重构出mostCommitStatus
func (a *action) commitTxDone(nodeStatus *pt.ParacrossNodeStatus, stat *pt.ParacrossHeightStatus, titleStatus *pt.ParacrossStatus, func (a *action) commitTxDone(nodeStatus *pt.ParacrossNodeStatus, stat *pt.ParacrossHeightStatus, titleStatus *pt.ParacrossStatus,
nodes map[string]struct{}) (*types.Receipt, error) { nodes map[string]struct{}) (*types.Receipt, error) {
...@@ -706,7 +828,7 @@ func (a *action) commitTxDoneByStat(stat *pt.ParacrossHeightStatus, titleStatus ...@@ -706,7 +828,7 @@ func (a *action) commitTxDoneByStat(stat *pt.ParacrossHeightStatus, titleStatus
} }
//主链共识跳跃条件: 仅支持主链共识初始高度为-1,也就是没有共识过,共识过不允许再跳跃 //主链共识跳跃条件: 仅支持主链共识初始高度为-1,也就是没有共识过,共识过不允许再跳跃
func (a *action) isAllowMainConsensJump(commit *pt.ParacrossCommitAction, titleStatus *pt.ParacrossStatus) bool { func (a *action) isAllowMainConsensJump(commit *pt.ParacrossNodeStatus, titleStatus *pt.ParacrossStatus) bool {
cfg := a.api.GetConfig() cfg := a.api.GetConfig()
if cfg.IsDappFork(a.exec.GetMainHeight(), pt.ParaX, pt.ForkLoopCheckCommitTxDone) { if cfg.IsDappFork(a.exec.GetMainHeight(), pt.ParaX, pt.ForkLoopCheckCommitTxDone) {
if titleStatus.Height == -1 { if titleStatus.Height == -1 {
...@@ -720,24 +842,24 @@ func (a *action) isAllowMainConsensJump(commit *pt.ParacrossCommitAction, titleS ...@@ -720,24 +842,24 @@ func (a *action) isAllowMainConsensJump(commit *pt.ParacrossCommitAction, titleS
//平行链自共识无缝切换条件:1,平行链没有共识过,2:commit高度是大于自共识分叉高度且上一次共识的主链高度小于自共识分叉高度,保证只运行一次, //平行链自共识无缝切换条件:1,平行链没有共识过,2:commit高度是大于自共识分叉高度且上一次共识的主链高度小于自共识分叉高度,保证只运行一次,
// 1. 分叉之前,开启过共识的平行链需要从1跳跃,没开启过的将使用新版本,从0开始发送,不用考虑从1跳跃的问题 // 1. 分叉之前,开启过共识的平行链需要从1跳跃,没开启过的将使用新版本,从0开始发送,不用考虑从1跳跃的问题
// 2. 分叉之后,只有stage.blockHeight== commit.height,也就是stage起始高度时候允许跳跃 // 2. 分叉之后,只有stage.blockHeight== commit.height,也就是stage起始高度时候允许跳跃
func (a *action) isAllowParaConsensJump(commit *pt.ParacrossCommitAction, titleStatus *pt.ParacrossStatus) (bool, error) { func (a *action) isAllowParaConsensJump(commit *pt.ParacrossNodeStatus, titleStatus *pt.ParacrossStatus) (bool, error) {
cfg := a.api.GetConfig() cfg := a.api.GetConfig()
if cfg.IsDappFork(a.height, pt.ParaX, pt.ForkParaSelfConsStages) { if cfg.IsDappFork(a.height, pt.ParaX, pt.ForkParaSelfConsStages) {
stage, err := getSelfConsOneStage(a.db, commit.Status.Height) stage, err := getSelfConsOneStage(a.db, commit.Height)
if err != nil && errors.Cause(err) != pt.ErrKeyNotExist { if err != nil && errors.Cause(err) != pt.ErrKeyNotExist {
return false, err return false, err
} }
if stage == nil { if stage == nil {
return false, nil return false, nil
} }
return stage.StartHeight == commit.Status.Height, nil return stage.StartHeight == commit.Height, nil
} }
//兼容分叉之前从1跳跃场景 //兼容分叉之前从1跳跃场景
return titleStatus.Height == -1, nil return titleStatus.Height == -1, nil
} }
func (a *action) isAllowConsensJump(commit *pt.ParacrossCommitAction, titleStatus *pt.ParacrossStatus) (bool, error) { func (a *action) isAllowConsensJump(commit *pt.ParacrossNodeStatus, titleStatus *pt.ParacrossStatus) (bool, error) {
cfg := a.api.GetConfig() cfg := a.api.GetConfig()
if cfg.IsPara() { if cfg.IsPara() {
return a.isAllowParaConsensJump(commit, titleStatus) return a.isAllowParaConsensJump(commit, titleStatus)
...@@ -1145,6 +1267,9 @@ func (a *action) Miner(miner *pt.ParacrossMinerAction) (*types.Receipt, error) { ...@@ -1145,6 +1267,9 @@ func (a *action) Miner(miner *pt.ParacrossMinerAction) (*types.Receipt, error) {
logs = append(logs, log) logs = append(logs, log)
minerReceipt := &types.Receipt{Ty: types.ExecOk, KV: nil, Logs: logs} minerReceipt := &types.Receipt{Ty: types.ExecOk, KV: nil, Logs: logs}
//自共识分阶段使能,综合考虑挖矿奖励和共识分配奖励,判断是否自共识使能需要采用共识的高度,而不能采用当前区块高度a.height
//考虑自共识使能区块高度100,如果采用区块高度判断,则在100高度可能收到80~99的20条共识交易,这20条交易在100高度参与共识,则无奖励可分配,而且共识高度将是80而不是100
//采用共识高度miner.Status.Height判断,则严格执行了产生奖励和分配奖励,且共识高度从100开始
isSelfConsensOn := miner.IsSelfConsensus isSelfConsensOn := miner.IsSelfConsensus
if cfg.IsDappFork(a.height, pt.ParaX, pt.ForkParaSelfConsStages) { if cfg.IsDappFork(a.height, pt.ParaX, pt.ForkParaSelfConsStages) {
var err error var err error
...@@ -1200,7 +1325,7 @@ func (a *action) isAllowTransfer() error { ...@@ -1200,7 +1325,7 @@ func (a *action) isAllowTransfer() error {
if err != nil { if err != nil {
return errors.Wrapf(types.ErrInvalidParam, "not para chain exec=%s", string(a.tx.Execer)) return errors.Wrapf(types.ErrInvalidParam, "not para chain exec=%s", string(a.tx.Execer))
} }
nodes, err := a.getNodesGroup(string(tempTitle)) nodes, _, err := a.getNodesGroup(string(tempTitle))
if err != nil { if err != nil {
return errors.Wrapf(err, "nodegroup not config,title=%s", tempTitle) return errors.Wrapf(err, "nodegroup not config,title=%s", tempTitle)
} }
......
...@@ -122,14 +122,14 @@ func (a *action) crossAssetTransfer(transfer *pt.CrossAssetTransfer, act int64, ...@@ -122,14 +122,14 @@ func (a *action) crossAssetTransfer(transfer *pt.CrossAssetTransfer, act int64,
return nil, err return nil, err
} }
clog.Info("paracross.crossAssetTransfer", "action", act, "newExec", newTransfer.AssetExec, "newSymbol", newTransfer.AssetSymbol, clog.Info("paracross.crossAssetTransfer", "action", act, "newExec", newTransfer.AssetExec, "newSymbol", newTransfer.AssetSymbol,
"ori.exec", transfer.AssetExec, "ori.symbol", transfer.AssetSymbol, "txHash", common.ToHex(a.tx.Hash())) "ori.exec", transfer.AssetExec, "ori.symbol", transfer.AssetSymbol, "txHash", common.ToHex(actTx.Hash()))
switch act { switch act {
case pt.ParacrossMainAssetTransfer: case pt.ParacrossMainAssetTransfer:
return a.mainAssetTransfer(newTransfer) return a.mainAssetTransfer(newTransfer, actTx)
case pt.ParacrossMainAssetWithdraw: case pt.ParacrossMainAssetWithdraw:
return a.mainAssetWithdraw(newTransfer, actTx) return a.mainAssetWithdraw(newTransfer, actTx)
case pt.ParacrossParaAssetTransfer: case pt.ParacrossParaAssetTransfer:
return a.paraAssetTransfer(newTransfer) return a.paraAssetTransfer(newTransfer, actTx)
case pt.ParacrossParaAssetWithdraw: case pt.ParacrossParaAssetWithdraw:
return a.paraAssetWithdraw(newTransfer, actTx) return a.paraAssetWithdraw(newTransfer, actTx)
default: default:
...@@ -138,14 +138,14 @@ func (a *action) crossAssetTransfer(transfer *pt.CrossAssetTransfer, act int64, ...@@ -138,14 +138,14 @@ func (a *action) crossAssetTransfer(transfer *pt.CrossAssetTransfer, act int64,
} }
//主链先transfer, 然后平行链create asset, 如果平行链失败,主链再rollback //主链先transfer, 然后平行链create asset, 如果平行链失败,主链再rollback
func (a *action) mainAssetTransfer(transfer *pt.CrossAssetTransfer) (*types.Receipt, error) { func (a *action) mainAssetTransfer(transfer *pt.CrossAssetTransfer, transferTx *types.Transaction) (*types.Receipt, error) {
cfg := a.api.GetConfig() cfg := a.api.GetConfig()
isPara := cfg.IsPara() isPara := cfg.IsPara()
//主链处理分支, 先处理 //主链处理分支, 先处理
if !isPara { if !isPara {
return a.execTransfer(transfer) return a.execTransfer(transfer, transferTx)
} }
return a.execCreateAsset(transfer) return a.execCreateAsset(transfer, transferTx)
} }
//平行链先销毁, 共识后主链再withdraw //平行链先销毁, 共识后主链再withdraw
...@@ -156,19 +156,19 @@ func (a *action) mainAssetWithdraw(withdraw *pt.CrossAssetTransfer, withdrawTx * ...@@ -156,19 +156,19 @@ func (a *action) mainAssetWithdraw(withdraw *pt.CrossAssetTransfer, withdrawTx *
if !isPara { if !isPara {
return a.execWithdraw(withdraw, withdrawTx) return a.execWithdraw(withdraw, withdrawTx)
} }
return a.execDestroyAsset(withdraw) return a.execDestroyAsset(withdraw, withdrawTx)
} }
//平行链先转移, 共识后主链create asset //平行链先转移, 共识后主链create asset
func (a *action) paraAssetTransfer(transfer *pt.CrossAssetTransfer) (*types.Receipt, error) { func (a *action) paraAssetTransfer(transfer *pt.CrossAssetTransfer, transferTx *types.Transaction) (*types.Receipt, error) {
cfg := a.api.GetConfig() cfg := a.api.GetConfig()
isPara := cfg.IsPara() isPara := cfg.IsPara()
//平行链链处理分支,先处理 //平行链链处理分支,先处理
if isPara { if isPara {
return a.execTransfer(transfer) return a.execTransfer(transfer, transferTx)
} }
//主链共识后处理 //主链共识后处理
return a.execCreateAsset(transfer) return a.execCreateAsset(transfer, transferTx)
} }
//平行链从主链提回, 先在主链处理,然后在平行链处理, 如果平行链执行失败,共识后主链再回滚 //平行链从主链提回, 先在主链处理,然后在平行链处理, 如果平行链执行失败,共识后主链再回滚
...@@ -179,10 +179,10 @@ func (a *action) paraAssetWithdraw(withdraw *pt.CrossAssetTransfer, withdrawTx * ...@@ -179,10 +179,10 @@ func (a *action) paraAssetWithdraw(withdraw *pt.CrossAssetTransfer, withdrawTx *
if isPara { if isPara {
return a.execWithdraw(withdraw, withdrawTx) return a.execWithdraw(withdraw, withdrawTx)
} }
return a.execDestroyAsset(withdraw) return a.execDestroyAsset(withdraw, withdrawTx)
} }
func (a *action) execTransfer(transfer *pt.CrossAssetTransfer) (*types.Receipt, error) { func (a *action) execTransfer(transfer *pt.CrossAssetTransfer, transferTx *types.Transaction) (*types.Receipt, error) {
cfg := a.api.GetConfig() cfg := a.api.GetConfig()
accDB, err := a.createAccount(cfg, a.db, transfer.AssetExec, transfer.AssetSymbol) accDB, err := a.createAccount(cfg, a.db, transfer.AssetExec, transfer.AssetSymbol)
if err != nil { if err != nil {
...@@ -191,30 +191,30 @@ func (a *action) execTransfer(transfer *pt.CrossAssetTransfer) (*types.Receipt, ...@@ -191,30 +191,30 @@ func (a *action) execTransfer(transfer *pt.CrossAssetTransfer) (*types.Receipt,
//主链上存入toAddr为user.p.xx.paracross地址 //主链上存入toAddr为user.p.xx.paracross地址
execAddr := address.ExecAddress(pt.ParaX) execAddr := address.ExecAddress(pt.ParaX)
toAddr := address.ExecAddress(string(a.tx.Execer)) toAddr := address.ExecAddress(string(transferTx.Execer))
//在平行链上存入toAddr为paracross地址 //在平行链上存入toAddr为paracross地址
if cfg.IsPara() { if cfg.IsPara() {
execAddr = address.ExecAddress(string(a.tx.Execer)) execAddr = address.ExecAddress(string(transferTx.Execer))
toAddr = address.ExecAddress(pt.ParaX) toAddr = address.ExecAddress(pt.ParaX)
} }
clog.Debug("paracross.execTransfer", "execer", string(a.tx.Execer), "assetexec", transfer.AssetExec, "symbol", transfer.AssetSymbol, clog.Debug("paracross.execTransfer", "execer", string(transferTx.Execer), "assetexec", transfer.AssetExec, "symbol", transfer.AssetSymbol,
"txHash", common.ToHex(a.tx.Hash())) "txHash", common.ToHex(transferTx.Hash()))
//对于paracross合约下的资产直接转账,不需要通过存到paracross合约下再转账,这里只有主链的A平行链资产转移到另一个B平行链场景 //对于paracross合约下的资产直接转账,不需要通过存到paracross合约下再转账,这里只有主链的A平行链资产转移到另一个B平行链场景
if transfer.AssetExec == pt.ParaX { if transfer.AssetExec == pt.ParaX {
r, err := accDB.Transfer(a.fromaddr, toAddr, transfer.Amount) r, err := accDB.Transfer(transferTx.From(), toAddr, transfer.Amount)
if err != nil { if err != nil {
return nil, errors.Wrapf(err, "assetTransfer,assetExec=%s,assetSym=%s", transfer.AssetExec, transfer.AssetSymbol) return nil, errors.Wrapf(err, "assetTransfer,assetExec=%s,assetSym=%s", transfer.AssetExec, transfer.AssetSymbol)
} }
return r, nil return r, nil
} }
fromAcc := accDB.LoadExecAccount(a.fromaddr, execAddr) fromAcc := accDB.LoadExecAccount(transferTx.From(), execAddr)
if fromAcc.Balance < transfer.Amount { if fromAcc.Balance < transfer.Amount {
return nil, errors.Wrapf(types.ErrNoBalance, "execTransfer,acctBalance=%d,assetExec=%s,assetSym=%s", fromAcc.Balance, transfer.AssetExec, transfer.AssetSymbol) return nil, errors.Wrapf(types.ErrNoBalance, "execTransfer,acctBalance=%d,assetExec=%s,assetSym=%s", fromAcc.Balance, transfer.AssetExec, transfer.AssetSymbol)
} }
r, err := accDB.ExecTransfer(a.fromaddr, toAddr, execAddr, transfer.Amount) r, err := accDB.ExecTransfer(transferTx.From(), toAddr, execAddr, transfer.Amount)
if err != nil { if err != nil {
return nil, errors.Wrapf(err, "assetTransfer,assetExec=%s,assetSym=%s", transfer.AssetExec, transfer.AssetSymbol) return nil, errors.Wrapf(err, "assetTransfer,assetExec=%s,assetSym=%s", transfer.AssetExec, transfer.AssetSymbol)
} }
...@@ -236,7 +236,7 @@ func (a *action) execWithdraw(withdraw *pt.CrossAssetTransfer, withdrawTx *types ...@@ -236,7 +236,7 @@ func (a *action) execWithdraw(withdraw *pt.CrossAssetTransfer, withdrawTx *types
} }
clog.Debug("Paracross.execWithdraw", "amount", withdraw.Amount, "from", fromAddr, clog.Debug("Paracross.execWithdraw", "amount", withdraw.Amount, "from", fromAddr,
"assetExec", withdraw.AssetExec, "symbol", withdraw.AssetSymbol, "execAddr", execAddr, "txHash", common.ToHex(a.tx.Hash())) "assetExec", withdraw.AssetExec, "symbol", withdraw.AssetSymbol, "execAddr", execAddr, "txHash", common.ToHex(withdrawTx.Hash()))
//对于paracross合约下的资产直接转账,不需要通过存到paracross合约下再转账,这里只有主链的A平行链资产转移到另一个B平行链场景 //对于paracross合约下的资产直接转账,不需要通过存到paracross合约下再转账,这里只有主链的A平行链资产转移到另一个B平行链场景
if withdraw.AssetExec == pt.ParaX { if withdraw.AssetExec == pt.ParaX {
...@@ -257,11 +257,11 @@ func (a *action) execWithdraw(withdraw *pt.CrossAssetTransfer, withdrawTx *types ...@@ -257,11 +257,11 @@ func (a *action) execWithdraw(withdraw *pt.CrossAssetTransfer, withdrawTx *types
//主链Alice的token转移到user.p.bb.平行链,在平行链上表示为mavl-paracross-token.symbol-Addr(Alice),这里并没有放在Addr(user.p.bb.paracross)子账号下 //主链Alice的token转移到user.p.bb.平行链,在平行链上表示为mavl-paracross-token.symbol-Addr(Alice),这里并没有放在Addr(user.p.bb.paracross)子账号下
//平行链转移到主链的token在主链表示为mavl-paracross-user.p.aa.token.symbol-exec-Addr(Alice),再转移到另一个user.p.bb.平行链,需要先transfer到paracross执行器下 //平行链转移到主链的token在主链表示为mavl-paracross-user.p.aa.token.symbol-exec-Addr(Alice),再转移到另一个user.p.bb.平行链,需要先transfer到paracross执行器下
//在平行链bb上铸造新币,表示为mavl-paracross-paracross.user.p.aa.token.symbol-exec-Addr(Alice),第二个paracross代表在主链原生执行器为paracross //在平行链bb上铸造新币,表示为mavl-paracross-paracross.user.p.aa.token.symbol-exec-Addr(Alice),第二个paracross代表在主链原生执行器为paracross
func (a *action) createParaAccount(cross *pt.CrossAssetTransfer) (*account.DB, error) { func (a *action) createParaAccount(cross *pt.CrossAssetTransfer, crossTx *types.Transaction) (*account.DB, error) {
cfg := a.api.GetConfig() cfg := a.api.GetConfig()
paraTitle, err := getTitleFrom(a.tx.Execer) paraTitle, err := getTitleFrom(crossTx.Execer)
if err != nil { if err != nil {
return nil, errors.Wrapf(err, "createParaAccount call getTitleFrom failed,exec=%s", string(a.tx.Execer)) return nil, errors.Wrapf(err, "createParaAccount call getTitleFrom failed,exec=%s", string(crossTx.Execer))
} }
assetExec := cross.AssetExec assetExec := cross.AssetExec
...@@ -270,20 +270,20 @@ func (a *action) createParaAccount(cross *pt.CrossAssetTransfer) (*account.DB, e ...@@ -270,20 +270,20 @@ func (a *action) createParaAccount(cross *pt.CrossAssetTransfer) (*account.DB, e
assetExec = string(paraTitle) + assetExec assetExec = string(paraTitle) + assetExec
} }
paraAcc, err := NewParaAccount(cfg, string(paraTitle), assetExec, assetSymbol, a.db) paraAcc, err := NewParaAccount(cfg, string(paraTitle), assetExec, assetSymbol, a.db)
clog.Debug("createParaAccount", "assetExec", assetExec, "symbol", assetSymbol, "txHash", common.ToHex(a.tx.Hash())) clog.Debug("createParaAccount", "assetExec", assetExec, "symbol", assetSymbol, "txHash", common.ToHex(crossTx.Hash()))
if err != nil { if err != nil {
return nil, errors.Wrapf(err, "createParaAccount,exec=%s,symbol=%s,title=%s", assetExec, assetSymbol, paraTitle) return nil, errors.Wrapf(err, "createParaAccount,exec=%s,symbol=%s,title=%s", assetExec, assetSymbol, paraTitle)
} }
return paraAcc, nil return paraAcc, nil
} }
func (a *action) execCreateAsset(transfer *pt.CrossAssetTransfer) (*types.Receipt, error) { func (a *action) execCreateAsset(transfer *pt.CrossAssetTransfer, transferTx *types.Transaction) (*types.Receipt, error) {
paraAcc, err := a.createParaAccount(transfer) paraAcc, err := a.createParaAccount(transfer, transferTx)
if err != nil { if err != nil {
return nil, errors.Wrapf(err, "createAsset") return nil, errors.Wrapf(err, "createAsset")
} }
clog.Debug("paracross.execCreateAsset", "assetExec", transfer.AssetExec, "symbol", transfer.AssetSymbol, clog.Debug("paracross.execCreateAsset", "assetExec", transfer.AssetExec, "symbol", transfer.AssetSymbol,
"txHash", common.ToHex(a.tx.Hash())) "txHash", common.ToHex(transferTx.Hash()))
r, err := assetDepositBalance(paraAcc, transfer.ToAddr, transfer.Amount) r, err := assetDepositBalance(paraAcc, transfer.ToAddr, transfer.Amount)
if err != nil { if err != nil {
...@@ -292,14 +292,14 @@ func (a *action) execCreateAsset(transfer *pt.CrossAssetTransfer) (*types.Receip ...@@ -292,14 +292,14 @@ func (a *action) execCreateAsset(transfer *pt.CrossAssetTransfer) (*types.Receip
return r, nil return r, nil
} }
func (a *action) execDestroyAsset(withdraw *pt.CrossAssetTransfer) (*types.Receipt, error) { func (a *action) execDestroyAsset(withdraw *pt.CrossAssetTransfer, withdrawTx *types.Transaction) (*types.Receipt, error) {
paraAcc, err := a.createParaAccount(withdraw) paraAcc, err := a.createParaAccount(withdraw, withdrawTx)
if err != nil { if err != nil {
return nil, errors.Wrapf(err, "destroyAsset") return nil, errors.Wrapf(err, "destroyAsset")
} }
clog.Debug("paracross.execDestroyAsset", "assetExec", withdraw.AssetExec, "symbol", withdraw.AssetSymbol, clog.Debug("paracross.execDestroyAsset", "assetExec", withdraw.AssetExec, "symbol", withdraw.AssetSymbol,
"txHash", common.ToHex(a.tx.Hash()), "from", a.fromaddr, "amount", withdraw.Amount) "txHash", common.ToHex(withdrawTx.Hash()), "from", withdrawTx.From(), "amount", withdraw.Amount)
r, err := assetWithdrawBalance(paraAcc, a.fromaddr, withdraw.Amount) r, err := assetWithdrawBalance(paraAcc, withdrawTx.From(), withdraw.Amount)
if err != nil { if err != nil {
return nil, errors.Wrapf(err, "destroyAsset,assetExec=%s,assetSym=%s", withdraw.AssetExec, withdraw.AssetSymbol) return nil, errors.Wrapf(err, "destroyAsset,assetExec=%s,assetSym=%s", withdraw.AssetExec, withdraw.AssetSymbol)
} }
...@@ -315,7 +315,7 @@ func (a *action) assetTransfer(transfer *types.AssetsTransfer) (*types.Receipt, ...@@ -315,7 +315,7 @@ func (a *action) assetTransfer(transfer *types.AssetsTransfer) (*types.Receipt,
ToAddr: transfer.To, ToAddr: transfer.To,
} }
adaptNullAssetExec(tr) adaptNullAssetExec(tr)
return a.mainAssetTransfer(tr) return a.mainAssetTransfer(tr, a.tx)
} }
//旧的接口,只有主链从平行链转移 //旧的接口,只有主链从平行链转移
...@@ -363,7 +363,7 @@ func (a *action) paraAssetWithdrawRollback(wtw *pt.CrossAssetTransfer, withdrawT ...@@ -363,7 +363,7 @@ func (a *action) paraAssetWithdrawRollback(wtw *pt.CrossAssetTransfer, withdrawT
if err != nil { if err != nil {
return nil, errors.Wrapf(err, "paraAssetWithdrawRollback amend param") return nil, errors.Wrapf(err, "paraAssetWithdrawRollback amend param")
} }
paraAcc, err := a.createParaAccount(withdraw) paraAcc, err := a.createParaAccount(withdraw, withdrawTx)
if err != nil { if err != nil {
return nil, errors.Wrapf(err, "createAsset") return nil, errors.Wrapf(err, "createAsset")
} }
......
...@@ -6,7 +6,6 @@ package executor ...@@ -6,7 +6,6 @@ package executor
import ( import (
"encoding/hex" "encoding/hex"
"fmt"
"github.com/33cn/chain33/common" "github.com/33cn/chain33/common"
dbm "github.com/33cn/chain33/common/db" dbm "github.com/33cn/chain33/common/db"
...@@ -78,17 +77,21 @@ func (p *Paracross) Query_GetNodeGroupAddrs(in *pt.ReqParacrossNodeInfo) (types. ...@@ -78,17 +77,21 @@ func (p *Paracross) Query_GetNodeGroupAddrs(in *pt.ReqParacrossNodeInfo) (types.
return nil, errors.Wrap(types.ErrInvalidParam, "title is null") return nil, errors.Wrap(types.ErrInvalidParam, "title is null")
} }
ret, key, err := getConfigNodes(p.GetStateDB(), in.GetTitle()) _, nodesArry, key, err := getConfigNodes(p.GetStateDB(), in.GetTitle())
if err != nil { if err != nil {
return nil, err return nil, err
} }
var nodes []string var nodes string
for k := range ret { for _, k := range nodesArry {
nodes = append(nodes, k) if len(nodes) == 0 {
nodes = k
continue
}
nodes = nodes + "," + k
} }
var reply types.ReplyConfig var reply types.ReplyConfig
reply.Key = string(key) reply.Key = string(key)
reply.Value = fmt.Sprint(nodes) reply.Value = nodes
return &reply, nil return &reply, nil
} }
......
...@@ -9,6 +9,8 @@ import ( ...@@ -9,6 +9,8 @@ import (
"strconv" "strconv"
"math/big"
"github.com/33cn/chain33/common" "github.com/33cn/chain33/common"
dbm "github.com/33cn/chain33/common/db" dbm "github.com/33cn/chain33/common/db"
"github.com/33cn/chain33/system/dapp" "github.com/33cn/chain33/system/dapp"
...@@ -208,6 +210,28 @@ func makeParaNodeGroupReceipt(title string, prev, current *types.ConfigItem) *ty ...@@ -208,6 +210,28 @@ func makeParaNodeGroupReceipt(title string, prev, current *types.ConfigItem) *ty
} }
} }
//获取nodes范围内的bitmap,如果bitmap超出了nodes范围,也不处理,防止越界
func getAddrsByBitMap(nodes []string, bitmap []byte) []string {
rst := big.NewInt(0).SetBytes(bitmap)
addrs := make([]string, 0)
for i, a := range nodes {
if rst.Bit(i) == uint(0x1) {
addrs = append(addrs, a)
}
}
return addrs
}
//get secp256 addr's bls pubkey
func getAddrBlsPubKey(db dbm.KV, title, addr string) (string, error) {
addrStat, err := getNodeAddr(db, title, addr)
if err != nil {
return "", errors.Wrapf(err, "nodeAddr:%s-%s get error", title, addr)
}
return addrStat.BlsPubKey, nil
}
func (a *action) checkValidNode(config *pt.ParaNodeAddrConfig) (bool, error) { func (a *action) checkValidNode(config *pt.ParaNodeAddrConfig) (bool, error) {
nodes, _, err := getParacrossNodes(a.db, config.Title) nodes, _, err := getParacrossNodes(a.db, config.Title)
if err != nil { if err != nil {
...@@ -262,6 +286,7 @@ func (a *action) nodeJoin(config *pt.ParaNodeAddrConfig) (*types.Receipt, error) ...@@ -262,6 +286,7 @@ func (a *action) nodeJoin(config *pt.ParaNodeAddrConfig) (*types.Receipt, error)
Status: pt.ParaApplyJoining, Status: pt.ParaApplyJoining,
Title: config.Title, Title: config.Title,
TargetAddr: config.Addr, TargetAddr: config.Addr,
BlsPubKey: config.BlsPubKey,
FromAddr: a.fromaddr, FromAddr: a.fromaddr,
Votes: &pt.ParaNodeVoteDetail{}, Votes: &pt.ParaNodeVoteDetail{},
CoinsFrozen: config.CoinsFrozen, CoinsFrozen: config.CoinsFrozen,
...@@ -350,6 +375,23 @@ func (a *action) nodeCancel(config *pt.ParaNodeAddrConfig) (*types.Receipt, erro ...@@ -350,6 +375,23 @@ func (a *action) nodeCancel(config *pt.ParaNodeAddrConfig) (*types.Receipt, erro
} }
func (a *action) nodeModify(config *pt.ParaNodeAddrConfig) (*types.Receipt, error) {
addrStat, err := getNodeAddr(a.db, config.Title, config.Addr)
if err != nil {
return nil, errors.Wrapf(err, "nodeAddr:%s get error", config.Addr)
}
//只能提案发起人撤销
if a.fromaddr != config.Addr {
return nil, errors.Wrapf(types.ErrNotAllow, "addr create by:%s,not by:%s", config.Addr, a.fromaddr)
}
preStat := *addrStat
addrStat.BlsPubKey = config.BlsPubKey
return makeParaNodeStatusReceipt(a.fromaddr, &preStat, addrStat), nil
}
// IsSuperManager is supper manager or not // IsSuperManager is supper manager or not
func isSuperManager(cfg *types.Chain33Config, addr string) bool { func isSuperManager(cfg *types.Chain33Config, addr string) bool {
confManager := types.ConfSub(cfg, manager.ManageX) confManager := types.ConfSub(cfg, manager.ManageX)
...@@ -439,6 +481,7 @@ func (a *action) updateNodeAddrStatus(stat *pt.ParaNodeIdStatus) (*types.Receipt ...@@ -439,6 +481,7 @@ func (a *action) updateNodeAddrStatus(stat *pt.ParaNodeIdStatus) (*types.Receipt
addrStat = &pt.ParaNodeAddrIdStatus{} addrStat = &pt.ParaNodeAddrIdStatus{}
addrStat.Title = stat.Title addrStat.Title = stat.Title
addrStat.Addr = stat.TargetAddr addrStat.Addr = stat.TargetAddr
addrStat.BlsPubKey = stat.BlsPubKey
addrStat.Status = pt.ParaApplyJoined addrStat.Status = pt.ParaApplyJoined
addrStat.ProposalId = stat.Id addrStat.ProposalId = stat.Id
addrStat.QuitId = "" addrStat.QuitId = ""
...@@ -769,6 +812,15 @@ func (a *action) nodeGroupApply(config *pt.ParaNodeGroupConfig) (*types.Receipt, ...@@ -769,6 +812,15 @@ func (a *action) nodeGroupApply(config *pt.ParaNodeGroupConfig) (*types.Receipt,
return nil, errors.Wrapf(types.ErrInvalidParam, "node group apply addrs null:%s", config.Addrs) return nil, errors.Wrapf(types.ErrInvalidParam, "node group apply addrs null:%s", config.Addrs)
} }
var blsPubKeys []string
if len(config.BlsPubKeys) > 0 {
blsPubKeys = getConfigAddrs(config.BlsPubKeys)
if len(blsPubKeys) != len(addrs) {
return nil, errors.Wrapf(types.ErrInvalidParam, "nodegroup apply blsPubkeys length=%d not match addrs=%d",
len(blsPubKeys), len(addrs))
}
}
receipt := &types.Receipt{Ty: types.ExecOk} receipt := &types.Receipt{Ty: types.ExecOk}
//main chain //main chain
cfg := a.api.GetConfig() cfg := a.api.GetConfig()
...@@ -787,9 +839,12 @@ func (a *action) nodeGroupApply(config *pt.ParaNodeGroupConfig) (*types.Receipt, ...@@ -787,9 +839,12 @@ func (a *action) nodeGroupApply(config *pt.ParaNodeGroupConfig) (*types.Receipt,
Status: pt.ParacrossNodeGroupApply, Status: pt.ParacrossNodeGroupApply,
Title: config.Title, Title: config.Title,
TargetAddrs: strings.Join(addrs, ","), TargetAddrs: strings.Join(addrs, ","),
BlsPubKeys: strings.Join(blsPubKeys, ","),
CoinsFrozen: config.CoinsFrozen, CoinsFrozen: config.CoinsFrozen,
FromAddr: a.fromaddr, FromAddr: a.fromaddr,
Height: a.height} Height: a.height,
}
r := makeNodeGroupIDReceipt(a.fromaddr, nil, stat) r := makeNodeGroupIDReceipt(a.fromaddr, nil, stat)
receipt.KV = append(receipt.KV, r.KV...) receipt.KV = append(receipt.KV, r.KV...)
receipt.Logs = append(receipt.Logs, r.Logs...) receipt.Logs = append(receipt.Logs, r.Logs...)
...@@ -977,6 +1032,11 @@ func (a *action) nodeGroupCreate(status *pt.ParaNodeGroupStatus) (*types.Receipt ...@@ -977,6 +1032,11 @@ func (a *action) nodeGroupCreate(status *pt.ParaNodeGroupStatus) (*types.Receipt
receipt := makeParaNodeGroupReceipt(status.Title, nil, &item) receipt := makeParaNodeGroupReceipt(status.Title, nil, &item)
var blsPubKeys []string
if len(status.BlsPubKeys) > 0 {
blsPubKeys = strings.Split(status.BlsPubKeys, ",")
}
//update addr status //update addr status
for i, addr := range nodes { for i, addr := range nodes {
stat := &pt.ParaNodeIdStatus{ stat := &pt.ParaNodeIdStatus{
...@@ -988,7 +1048,9 @@ func (a *action) nodeGroupCreate(status *pt.ParaNodeGroupStatus) (*types.Receipt ...@@ -988,7 +1048,9 @@ func (a *action) nodeGroupCreate(status *pt.ParaNodeGroupStatus) (*types.Receipt
CoinsFrozen: status.CoinsFrozen, CoinsFrozen: status.CoinsFrozen,
FromAddr: status.FromAddr, FromAddr: status.FromAddr,
Height: a.height} Height: a.height}
if len(blsPubKeys) > 0 {
stat.BlsPubKey = blsPubKeys[i]
}
r := makeNodeConfigReceipt(a.fromaddr, nil, nil, stat) r := makeNodeConfigReceipt(a.fromaddr, nil, nil, stat)
receipt = mergeReceipt(receipt, r) receipt = mergeReceipt(receipt, r)
...@@ -1052,25 +1114,28 @@ func (a *action) NodeConfig(config *pt.ParaNodeAddrConfig) (*types.Receipt, erro ...@@ -1052,25 +1114,28 @@ func (a *action) NodeConfig(config *pt.ParaNodeAddrConfig) (*types.Receipt, erro
return nil, errors.Wrapf(types.ErrInvalidParam, "exec=%s,should prefix with user.p.", string(a.tx.Execer)) return nil, errors.Wrapf(types.ErrInvalidParam, "exec=%s,should prefix with user.p.", string(a.tx.Execer))
} }
if config.Op == pt.ParaOpNewApply { switch config.Op {
case pt.ParaOpNewApply:
return a.nodeJoin(config) return a.nodeJoin(config)
case pt.ParaOpQuit:
} else if config.Op == pt.ParaOpQuit { //退出nodegroup
return a.nodeQuit(config) return a.nodeQuit(config)
case pt.ParaOpCancel:
} else if config.Op == pt.ParaOpCancel { //撤销未批准的申请
if config.Id == "" { if config.Id == "" {
return nil, types.ErrInvalidParam return nil, types.ErrInvalidParam
} }
return a.nodeCancel(config) return a.nodeCancel(config)
case pt.ParaOpVote:
} else if config.Op == pt.ParaOpVote {
if config.Id == "" || config.Value >= pt.ParaVoteEnd { if config.Id == "" || config.Value >= pt.ParaVoteEnd {
return nil, types.ErrInvalidParam return nil, types.ErrInvalidParam
} }
return a.nodeVote(config) return a.nodeVote(config)
case pt.ParaOpModify:
//修改addr相关联的参数,只能原创地址修改
return a.nodeModify(config)
default:
return nil, pt.ErrParaUnSupportNodeOper
} }
return nil, pt.ErrParaUnSupportNodeOper
} }
...@@ -61,6 +61,7 @@ message ParaNodeAddrConfig { ...@@ -61,6 +61,7 @@ message ParaNodeAddrConfig {
string addr = 4; string addr = 4;
uint32 value = 5; uint32 value = 5;
int64 coinsFrozen = 6; int64 coinsFrozen = 6;
string blsPubKey = 7; //本地址私钥对应的bls聚合签名的公钥
} }
message ParaNodeVoteDetail { message ParaNodeVoteDetail {
...@@ -74,6 +75,7 @@ message ParaNodeAddrIdStatus { ...@@ -74,6 +75,7 @@ message ParaNodeAddrIdStatus {
string quitId = 3; string quitId = 3;
int32 status = 4; int32 status = 4;
string title = 5; string title = 5;
string blsPubKey = 6;
} }
message ParaNodeIdStatus { message ParaNodeIdStatus {
...@@ -85,6 +87,7 @@ message ParaNodeIdStatus { ...@@ -85,6 +87,7 @@ message ParaNodeIdStatus {
ParaNodeVoteDetail votes = 6; ParaNodeVoteDetail votes = 6;
string fromAddr = 7; string fromAddr = 7;
int64 height = 8; int64 height = 8;
string blsPubKey = 9;
} }
message ReceiptParaNodeConfig { message ReceiptParaNodeConfig {
...@@ -117,6 +120,7 @@ message ParaNodeGroupConfig { ...@@ -117,6 +120,7 @@ message ParaNodeGroupConfig {
string id = 3; string id = 3;
string addrs = 4; string addrs = 4;
int64 coinsFrozen = 5; int64 coinsFrozen = 5;
string blsPubKeys = 6;
} }
message ParaNodeGroupStatus { message ParaNodeGroupStatus {
...@@ -127,6 +131,7 @@ message ParaNodeGroupStatus { ...@@ -127,6 +131,7 @@ message ParaNodeGroupStatus {
int64 coinsFrozen = 5; int64 coinsFrozen = 5;
string fromAddr = 6; string fromAddr = 6;
int64 height = 7; int64 height = 7;
string blsPubKeys = 8;
} }
message ReceiptParaNodeGroupConfig { message ReceiptParaNodeGroupConfig {
...@@ -142,6 +147,7 @@ message ReqParacrossNodeInfo { ...@@ -142,6 +147,7 @@ message ReqParacrossNodeInfo {
string id = 2; string id = 2;
string addr = 3; string addr = 3;
int32 status = 4; int32 status = 4;
string blsPubKey = 5;
} }
message RespParacrossNodeAddrs { message RespParacrossNodeAddrs {
...@@ -259,8 +265,14 @@ message ReplyQuerySelfStages { ...@@ -259,8 +265,14 @@ message ReplyQuerySelfStages {
repeated SelfConsensStageInfo stageInfo = 1; repeated SelfConsensStageInfo stageInfo = 1;
} }
message ParacrossCommitBlsInfo {
bytes sign = 1;
bytes addrs = 2; //addrs' bitmap
}
message ParacrossCommitAction { message ParacrossCommitAction {
ParacrossNodeStatus status = 1; ParacrossNodeStatus status = 1;
ParacrossCommitBlsInfo bls = 2;
} }
message ParacrossMinerAction { message ParacrossMinerAction {
......
...@@ -57,4 +57,6 @@ var ( ...@@ -57,4 +57,6 @@ var (
ErrKeyNotExist = errors.New("ErrKeyNotExist") ErrKeyNotExist = errors.New("ErrKeyNotExist")
// ErrConsensClosed consensus closed // ErrConsensClosed consensus closed
ErrConsensClosed = errors.New("ErrConsensClosed") ErrConsensClosed = errors.New("ErrConsensClosed")
//ErrConsBlsSignVerify bls12-381 aggregate sign verify
ErrBlsSignVerify = errors.New("ErrBlsSignVerify")
) )
...@@ -105,6 +105,7 @@ const ( ...@@ -105,6 +105,7 @@ const (
ParaOpVote ParaOpVote
ParaOpQuit ParaOpQuit
ParaOpCancel ParaOpCancel
ParaOpModify
) )
// node vote op // node vote op
...@@ -180,17 +181,14 @@ func CalcMinerHeightKey(title string, height int64) []byte { ...@@ -180,17 +181,14 @@ func CalcMinerHeightKey(title string, height int64) []byte {
} }
// CreateRawCommitTx4MainChain create commit tx to main chain // CreateRawCommitTx4MainChain create commit tx to main chain
func CreateRawCommitTx4MainChain(cfg *types.Chain33Config, status *ParacrossNodeStatus, name string, fee int64) (*types.Transaction, error) { func CreateRawCommitTx4MainChain(cfg *types.Chain33Config, status *ParacrossCommitAction, name string, fee int64) (*types.Transaction, error) {
return createRawCommitTx(cfg, status, name, fee) return createRawCommitTx(cfg, status, name, fee)
} }
func createRawCommitTx(cfg *types.Chain33Config, status *ParacrossNodeStatus, name string, feeRate int64) (*types.Transaction, error) { func createRawCommitTx(cfg *types.Chain33Config, commit *ParacrossCommitAction, name string, feeRate int64) (*types.Transaction, error) {
v := &ParacrossCommitAction{
Status: status,
}
action := &ParacrossAction{ action := &ParacrossAction{
Ty: ParacrossActionCommit, Ty: ParacrossActionCommit,
Value: &ParacrossAction_Commit{v}, Value: &ParacrossAction_Commit{commit},
} }
tx := &types.Transaction{ tx := &types.Transaction{
Execer: []byte(name), Execer: []byte(name),
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment