2020-03-29 21:32:01 +08:00
|
|
|
package contracts
|
|
|
|
|
|
|
|
import (
|
2020-08-24 14:20:19 +08:00
|
|
|
"crypto/sha256"
|
2020-03-29 21:32:01 +08:00
|
|
|
"encoding/json"
|
|
|
|
"fmt"
|
2020-04-08 18:34:20 +08:00
|
|
|
"strings"
|
2020-03-29 21:32:01 +08:00
|
|
|
|
2020-10-22 13:49:05 +08:00
|
|
|
appchainMgr "github.com/meshplus/bitxhub-core/appchain-mgr"
|
2020-10-21 18:41:53 +08:00
|
|
|
"github.com/meshplus/bitxhub-core/boltvm"
|
2020-08-24 14:20:19 +08:00
|
|
|
"github.com/meshplus/bitxhub-kit/crypto"
|
|
|
|
"github.com/meshplus/bitxhub-kit/crypto/asym"
|
2020-03-29 21:32:01 +08:00
|
|
|
"github.com/meshplus/bitxhub-kit/types"
|
2020-10-21 18:41:53 +08:00
|
|
|
"github.com/meshplus/bitxhub-model/constant"
|
2020-03-29 21:32:01 +08:00
|
|
|
"github.com/meshplus/bitxhub-model/pb"
|
|
|
|
)
|
|
|
|
|
2020-05-07 14:18:19 +08:00
|
|
|
type InterchainManager struct {
|
2020-03-29 21:32:01 +08:00
|
|
|
boltvm.Stub
|
|
|
|
}
|
|
|
|
|
2020-08-24 14:20:19 +08:00
|
|
|
type BxhValidators struct {
|
|
|
|
Addresses []string `json:"addresses"`
|
|
|
|
}
|
|
|
|
|
2021-03-19 09:41:19 +08:00
|
|
|
func (x *InterchainManager) Register(chainId string) *boltvm.Response {
|
|
|
|
interchain, ok := x.getInterchain(chainId)
|
2020-09-29 15:13:05 +08:00
|
|
|
if !ok {
|
|
|
|
interchain = &pb.Interchain{
|
2021-03-19 09:41:19 +08:00
|
|
|
ID: chainId,
|
2020-09-29 15:13:05 +08:00
|
|
|
InterchainCounter: make(map[string]uint64),
|
|
|
|
ReceiptCounter: make(map[string]uint64),
|
|
|
|
SourceReceiptCounter: make(map[string]uint64),
|
|
|
|
}
|
2021-03-19 09:41:19 +08:00
|
|
|
x.setInterchain(chainId, interchain)
|
2020-03-29 21:32:01 +08:00
|
|
|
}
|
2020-09-29 15:13:05 +08:00
|
|
|
body, err := interchain.Marshal()
|
|
|
|
if err != nil {
|
|
|
|
return boltvm.Error(err.Error())
|
2020-03-29 21:32:01 +08:00
|
|
|
}
|
|
|
|
|
2020-09-29 15:13:05 +08:00
|
|
|
return boltvm.Success(body)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (x *InterchainManager) DeleteInterchain(id string) *boltvm.Response {
|
|
|
|
x.Delete(AppchainKey(id))
|
|
|
|
return boltvm.Success(nil)
|
|
|
|
}
|
|
|
|
|
|
|
|
// GetInterchain returns information of the interchain count, Receipt count and SourceReceipt count by id
|
|
|
|
func (x *InterchainManager) getInterchain(id string) (*pb.Interchain, bool) {
|
|
|
|
interchain := &pb.Interchain{}
|
|
|
|
ok, data := x.Get(AppchainKey(id))
|
|
|
|
if !ok {
|
|
|
|
return nil, false
|
2020-03-29 21:32:01 +08:00
|
|
|
}
|
|
|
|
|
2020-09-29 15:13:05 +08:00
|
|
|
if err := interchain.Unmarshal(data); err != nil {
|
|
|
|
panic(err)
|
2020-03-29 21:32:01 +08:00
|
|
|
}
|
|
|
|
|
2020-09-29 15:13:05 +08:00
|
|
|
if interchain.InterchainCounter == nil {
|
|
|
|
interchain.InterchainCounter = make(map[string]uint64)
|
|
|
|
}
|
2020-03-29 21:32:01 +08:00
|
|
|
|
2020-09-29 15:13:05 +08:00
|
|
|
if interchain.ReceiptCounter == nil {
|
|
|
|
interchain.ReceiptCounter = make(map[string]uint64)
|
2020-03-29 21:32:01 +08:00
|
|
|
}
|
2020-09-29 15:13:05 +08:00
|
|
|
|
|
|
|
if interchain.SourceReceiptCounter == nil {
|
|
|
|
interchain.SourceReceiptCounter = make(map[string]uint64)
|
2020-03-29 21:32:01 +08:00
|
|
|
}
|
|
|
|
|
2020-09-29 15:13:05 +08:00
|
|
|
return interchain, true
|
2020-03-29 21:32:01 +08:00
|
|
|
}
|
|
|
|
|
2020-09-29 15:13:05 +08:00
|
|
|
// GetInterchain returns information of the interchain count, Receipt count and SourceReceipt count by id
|
|
|
|
func (x *InterchainManager) setInterchain(id string, interchain *pb.Interchain) {
|
|
|
|
data, err := interchain.Marshal()
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
x.Set(AppchainKey(id), data)
|
2020-03-29 21:32:01 +08:00
|
|
|
}
|
|
|
|
|
2020-05-09 15:07:55 +08:00
|
|
|
// Interchain returns information of the interchain count, Receipt count and SourceReceipt count
|
|
|
|
func (x *InterchainManager) Interchain() *boltvm.Response {
|
2020-09-14 11:29:14 +08:00
|
|
|
ok, data := x.Get(AppchainKey(x.Caller()))
|
2020-05-09 15:07:55 +08:00
|
|
|
if !ok {
|
|
|
|
return boltvm.Error(fmt.Errorf("this appchain does not exist").Error())
|
|
|
|
}
|
|
|
|
return boltvm.Success(data)
|
|
|
|
}
|
|
|
|
|
2020-08-25 20:01:58 +08:00
|
|
|
// GetInterchain returns information of the interchain count, Receipt count and SourceReceipt count by id
|
|
|
|
func (x *InterchainManager) GetInterchain(id string) *boltvm.Response {
|
2020-09-14 11:29:14 +08:00
|
|
|
ok, data := x.Get(AppchainKey(id))
|
2020-08-25 20:01:58 +08:00
|
|
|
if !ok {
|
|
|
|
return boltvm.Error(fmt.Errorf("this appchain does not exist").Error())
|
|
|
|
}
|
|
|
|
return boltvm.Success(data)
|
|
|
|
}
|
|
|
|
|
2020-10-23 18:48:53 +08:00
|
|
|
func (x *InterchainManager) HandleIBTP(ibtp *pb.IBTP) *boltvm.Response {
|
2021-01-21 15:38:13 +08:00
|
|
|
|
2020-08-24 14:20:19 +08:00
|
|
|
if len(strings.Split(ibtp.From, "-")) == 2 {
|
|
|
|
return x.handleUnionIBTP(ibtp)
|
|
|
|
}
|
|
|
|
|
2020-09-29 15:13:05 +08:00
|
|
|
interchain, ok := x.getInterchain(ibtp.From)
|
2020-08-24 14:20:19 +08:00
|
|
|
if !ok {
|
|
|
|
return boltvm.Error("this appchain does not exist")
|
|
|
|
}
|
|
|
|
|
2020-07-17 10:29:36 +08:00
|
|
|
if err := x.checkIBTP(ibtp, interchain); err != nil {
|
|
|
|
return boltvm.Error(err.Error())
|
|
|
|
}
|
|
|
|
|
|
|
|
res := boltvm.Success(nil)
|
|
|
|
|
|
|
|
if pb.IBTP_INTERCHAIN == ibtp.Type {
|
|
|
|
res = x.beginTransaction(ibtp)
|
2020-07-24 20:19:32 +08:00
|
|
|
} else if pb.IBTP_RECEIPT_SUCCESS == ibtp.Type || pb.IBTP_RECEIPT_FAILURE == ibtp.Type {
|
2020-07-17 10:29:36 +08:00
|
|
|
res = x.reportTransaction(ibtp)
|
2020-07-24 20:19:32 +08:00
|
|
|
} else if pb.IBTP_ASSET_EXCHANGE_INIT == ibtp.Type ||
|
|
|
|
pb.IBTP_ASSET_EXCHANGE_REDEEM == ibtp.Type ||
|
|
|
|
pb.IBTP_ASSET_EXCHANGE_REFUND == ibtp.Type {
|
|
|
|
res = x.handleAssetExchange(ibtp)
|
2020-03-29 21:32:01 +08:00
|
|
|
}
|
2020-07-17 10:29:36 +08:00
|
|
|
|
|
|
|
if !res.Ok {
|
|
|
|
return res
|
|
|
|
}
|
|
|
|
|
|
|
|
x.ProcessIBTP(ibtp, interchain)
|
|
|
|
|
|
|
|
return res
|
|
|
|
}
|
|
|
|
|
|
|
|
func (x *InterchainManager) HandleIBTPs(data []byte) *boltvm.Response {
|
2020-09-14 11:29:14 +08:00
|
|
|
ok := x.Has(AppchainKey(x.Caller()))
|
2020-03-29 21:32:01 +08:00
|
|
|
if !ok {
|
2020-07-17 10:29:36 +08:00
|
|
|
return boltvm.Error("this appchain does not exist")
|
|
|
|
}
|
|
|
|
|
|
|
|
ibtps := &pb.IBTPs{}
|
|
|
|
if err := ibtps.Unmarshal(data); err != nil {
|
|
|
|
return boltvm.Error(err.Error())
|
2020-03-29 21:32:01 +08:00
|
|
|
}
|
|
|
|
|
2020-09-29 15:13:05 +08:00
|
|
|
interchain := &pb.Interchain{}
|
2021-01-27 16:25:07 +08:00
|
|
|
x.GetObject(AppchainKey(x.Caller()), interchain)
|
2020-07-17 10:29:36 +08:00
|
|
|
|
2020-09-22 11:35:55 +08:00
|
|
|
for _, ibtp := range ibtps.Ibtps {
|
2020-07-17 10:29:36 +08:00
|
|
|
if err := x.checkIBTP(ibtp, interchain); err != nil {
|
|
|
|
return boltvm.Error(err.Error())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if res := x.beginMultiTargetsTransaction(ibtps); !res.Ok {
|
|
|
|
return res
|
|
|
|
}
|
|
|
|
|
2020-09-22 11:35:55 +08:00
|
|
|
for _, ibtp := range ibtps.Ibtps {
|
2020-07-17 10:29:36 +08:00
|
|
|
x.ProcessIBTP(ibtp, interchain)
|
|
|
|
}
|
|
|
|
|
|
|
|
return boltvm.Success(nil)
|
|
|
|
}
|
|
|
|
|
2020-09-29 15:13:05 +08:00
|
|
|
func (x *InterchainManager) checkIBTP(ibtp *pb.IBTP, interchain *pb.Interchain) error {
|
2021-02-01 11:08:26 +08:00
|
|
|
isRelayIBTP := x.isRelayIBTP(ibtp.From)
|
2021-01-21 15:38:13 +08:00
|
|
|
|
2020-07-17 10:29:36 +08:00
|
|
|
if ibtp.To == "" {
|
|
|
|
return fmt.Errorf("empty destination chain id")
|
|
|
|
}
|
2020-09-29 15:13:05 +08:00
|
|
|
|
|
|
|
if _, ok := x.getInterchain(ibtp.To); !ok {
|
2020-08-24 14:20:19 +08:00
|
|
|
x.Logger().WithField("chain_id", ibtp.To).Debug("target appchain does not exist")
|
2020-07-17 10:29:36 +08:00
|
|
|
}
|
2020-03-29 21:32:01 +08:00
|
|
|
|
2020-07-24 20:19:32 +08:00
|
|
|
if pb.IBTP_INTERCHAIN == ibtp.Type ||
|
|
|
|
pb.IBTP_ASSET_EXCHANGE_INIT == ibtp.Type ||
|
|
|
|
pb.IBTP_ASSET_EXCHANGE_REDEEM == ibtp.Type ||
|
|
|
|
pb.IBTP_ASSET_EXCHANGE_REFUND == ibtp.Type {
|
2021-02-01 11:08:26 +08:00
|
|
|
if !isRelayIBTP {
|
2021-01-21 15:38:13 +08:00
|
|
|
if ibtp.From != x.Caller() {
|
|
|
|
return fmt.Errorf("ibtp from != caller")
|
|
|
|
}
|
2020-03-29 21:32:01 +08:00
|
|
|
}
|
|
|
|
|
2020-09-14 15:26:44 +08:00
|
|
|
idx := interchain.InterchainCounter[ibtp.To]
|
2020-11-18 10:36:12 +08:00
|
|
|
if ibtp.Index <= idx {
|
|
|
|
return fmt.Errorf(fmt.Sprintf("index already exists, required %d, but %d", idx+1, ibtp.Index))
|
|
|
|
}
|
|
|
|
if ibtp.Index > idx+1 {
|
2020-09-14 15:26:44 +08:00
|
|
|
return fmt.Errorf(fmt.Sprintf("wrong index, required %d, but %d", idx+1, ibtp.Index))
|
|
|
|
}
|
2020-07-17 10:29:36 +08:00
|
|
|
} else {
|
2021-02-01 11:08:26 +08:00
|
|
|
if !isRelayIBTP {
|
2021-01-21 15:38:13 +08:00
|
|
|
if ibtp.To != x.Caller() {
|
|
|
|
return fmt.Errorf("ibtp to != caller")
|
|
|
|
}
|
2020-03-29 21:32:01 +08:00
|
|
|
}
|
|
|
|
|
2020-09-14 15:26:44 +08:00
|
|
|
idx := interchain.ReceiptCounter[ibtp.To]
|
2020-11-18 10:36:12 +08:00
|
|
|
if ibtp.Index <= idx {
|
|
|
|
return fmt.Errorf(fmt.Sprintf("receipt index already exists, required %d, but %d", idx+1, ibtp.Index))
|
|
|
|
}
|
|
|
|
|
|
|
|
if ibtp.Index > idx+1 {
|
|
|
|
return fmt.Errorf(fmt.Sprintf("wrong receipt index, required %d, but %d", idx+1, ibtp.Index))
|
2020-09-14 15:26:44 +08:00
|
|
|
}
|
2020-07-17 10:29:36 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
return nil
|
|
|
|
}
|
2020-03-29 21:32:01 +08:00
|
|
|
|
2021-02-01 11:08:26 +08:00
|
|
|
// isRelayIBTP returns whether ibtp.from is relaychain type
|
|
|
|
func (x *InterchainManager) isRelayIBTP(from string) bool {
|
|
|
|
srcChain := &appchainMgr.Appchain{}
|
|
|
|
res := x.CrossInvoke(constant.AppchainMgrContractAddr.String(), "GetAppchain", pb.String(from))
|
|
|
|
if err := json.Unmarshal(res.Result, srcChain); err != nil {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
return srcChain.ChainType == appchainMgr.RelaychainType
|
|
|
|
}
|
|
|
|
|
2020-09-29 15:13:05 +08:00
|
|
|
func (x *InterchainManager) ProcessIBTP(ibtp *pb.IBTP, interchain *pb.Interchain) {
|
2020-07-17 10:29:36 +08:00
|
|
|
m := make(map[string]uint64)
|
2020-07-24 20:19:32 +08:00
|
|
|
if pb.IBTP_INTERCHAIN == ibtp.Type ||
|
|
|
|
pb.IBTP_ASSET_EXCHANGE_INIT == ibtp.Type ||
|
|
|
|
pb.IBTP_ASSET_EXCHANGE_REDEEM == ibtp.Type ||
|
|
|
|
pb.IBTP_ASSET_EXCHANGE_REFUND == ibtp.Type {
|
2021-01-21 15:38:13 +08:00
|
|
|
if interchain.InterchainCounter == nil {
|
|
|
|
x.Logger().Info("interchain counter is nil, make one")
|
|
|
|
interchain.InterchainCounter = make(map[string]uint64)
|
|
|
|
}
|
2020-07-17 10:29:36 +08:00
|
|
|
interchain.InterchainCounter[ibtp.To]++
|
2020-09-29 15:13:05 +08:00
|
|
|
x.setInterchain(ibtp.From, interchain)
|
|
|
|
x.AddObject(x.indexMapKey(ibtp.ID()), x.GetTxHash())
|
2020-07-17 10:29:36 +08:00
|
|
|
m[ibtp.To] = x.GetTxIndex()
|
|
|
|
} else {
|
2020-05-07 14:18:19 +08:00
|
|
|
interchain.ReceiptCounter[ibtp.To] = ibtp.Index
|
2020-09-29 15:13:05 +08:00
|
|
|
x.setInterchain(ibtp.From, interchain)
|
2020-03-29 21:32:01 +08:00
|
|
|
m[ibtp.From] = x.GetTxIndex()
|
|
|
|
|
2020-09-29 15:13:05 +08:00
|
|
|
ic, _ := x.getInterchain(ibtp.To)
|
2020-05-07 14:18:19 +08:00
|
|
|
ic.SourceReceiptCounter[ibtp.From] = ibtp.Index
|
2020-09-29 15:13:05 +08:00
|
|
|
x.setInterchain(ibtp.To, ic)
|
2020-11-18 10:36:12 +08:00
|
|
|
x.SetObject(x.indexReceiptMapKey(ibtp.ID()), x.GetTxHash())
|
|
|
|
|
2020-07-17 10:29:36 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
x.PostInterchainEvent(m)
|
|
|
|
}
|
2020-03-29 21:32:01 +08:00
|
|
|
|
2020-07-17 10:29:36 +08:00
|
|
|
func (x *InterchainManager) beginMultiTargetsTransaction(ibtps *pb.IBTPs) *boltvm.Response {
|
|
|
|
args := make([]*pb.Arg, 0)
|
|
|
|
globalId := fmt.Sprintf("%s-%s", x.Caller(), x.GetTxHash())
|
|
|
|
args = append(args, pb.String(globalId))
|
|
|
|
|
2020-09-22 11:35:55 +08:00
|
|
|
for _, ibtp := range ibtps.Ibtps {
|
2020-07-17 10:29:36 +08:00
|
|
|
if ibtp.Type != pb.IBTP_INTERCHAIN {
|
|
|
|
return boltvm.Error("ibtp type != IBTP_INTERCHAIN")
|
|
|
|
}
|
|
|
|
|
|
|
|
childTxId := fmt.Sprintf("%s-%s-%d", ibtp.From, ibtp.To, ibtp.Index)
|
|
|
|
args = append(args, pb.String(childTxId))
|
2020-03-29 21:32:01 +08:00
|
|
|
}
|
|
|
|
|
2020-07-30 13:57:44 +08:00
|
|
|
return x.CrossInvoke(constant.TransactionMgrContractAddr.String(), "BeginMultiTXs", args...)
|
2020-07-17 10:29:36 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
func (x *InterchainManager) beginTransaction(ibtp *pb.IBTP) *boltvm.Response {
|
|
|
|
txId := fmt.Sprintf("%s-%s-%d", ibtp.From, ibtp.To, ibtp.Index)
|
|
|
|
return x.CrossInvoke(constant.TransactionMgrContractAddr.String(), "Begin", pb.String(txId))
|
|
|
|
}
|
|
|
|
|
|
|
|
func (x *InterchainManager) reportTransaction(ibtp *pb.IBTP) *boltvm.Response {
|
2020-07-30 13:57:44 +08:00
|
|
|
txId := fmt.Sprintf("%s-%s-%d", ibtp.From, ibtp.To, ibtp.Index)
|
2020-07-17 10:29:36 +08:00
|
|
|
result := int32(0)
|
|
|
|
if ibtp.Type == pb.IBTP_RECEIPT_FAILURE {
|
|
|
|
result = 1
|
|
|
|
}
|
|
|
|
return x.CrossInvoke(constant.TransactionMgrContractAddr.String(), "Report", pb.String(txId), pb.Int32(result))
|
2020-03-29 21:32:01 +08:00
|
|
|
}
|
|
|
|
|
2020-07-24 20:19:32 +08:00
|
|
|
func (x *InterchainManager) handleAssetExchange(ibtp *pb.IBTP) *boltvm.Response {
|
|
|
|
var method string
|
|
|
|
|
|
|
|
switch ibtp.Type {
|
|
|
|
case pb.IBTP_ASSET_EXCHANGE_INIT:
|
|
|
|
method = "Init"
|
|
|
|
case pb.IBTP_ASSET_EXCHANGE_REDEEM:
|
|
|
|
method = "Redeem"
|
|
|
|
case pb.IBTP_ASSET_EXCHANGE_REFUND:
|
|
|
|
method = "Refund"
|
|
|
|
default:
|
|
|
|
return boltvm.Error("unsupported asset exchange type")
|
|
|
|
}
|
|
|
|
|
|
|
|
return x.CrossInvoke(constant.AssetExchangeContractAddr.String(), method, pb.String(ibtp.From),
|
|
|
|
pb.String(ibtp.To), pb.Bytes(ibtp.Extra))
|
|
|
|
}
|
|
|
|
|
2020-05-07 14:18:19 +08:00
|
|
|
func (x *InterchainManager) GetIBTPByID(id string) *boltvm.Response {
|
2020-04-08 18:34:20 +08:00
|
|
|
arr := strings.Split(id, "-")
|
|
|
|
if len(arr) != 3 {
|
|
|
|
return boltvm.Error("wrong ibtp id")
|
|
|
|
}
|
|
|
|
|
|
|
|
caller := x.Caller()
|
|
|
|
|
2020-04-16 00:37:53 +08:00
|
|
|
if caller != arr[0] && caller != arr[1] {
|
2020-04-08 18:34:20 +08:00
|
|
|
return boltvm.Error("The caller does not have access to this ibtp")
|
|
|
|
}
|
|
|
|
|
2020-03-29 21:32:01 +08:00
|
|
|
var hash types.Hash
|
|
|
|
exist := x.GetObject(x.indexMapKey(id), &hash)
|
|
|
|
if !exist {
|
|
|
|
return boltvm.Error("this id is not existed")
|
|
|
|
}
|
|
|
|
|
|
|
|
return boltvm.Success(hash.Bytes())
|
|
|
|
}
|
|
|
|
|
2020-08-24 14:20:19 +08:00
|
|
|
func (x *InterchainManager) handleUnionIBTP(ibtp *pb.IBTP) *boltvm.Response {
|
|
|
|
srcRelayChainID := strings.Split(ibtp.From, "-")[0]
|
2020-09-14 11:29:14 +08:00
|
|
|
ok := x.Has(AppchainKey(srcRelayChainID))
|
2020-08-24 14:20:19 +08:00
|
|
|
if !ok {
|
|
|
|
return boltvm.Error("this relay chain does not exist")
|
|
|
|
}
|
|
|
|
|
|
|
|
if ibtp.To == "" {
|
|
|
|
return boltvm.Error("empty destination chain id")
|
|
|
|
}
|
2020-09-14 11:29:14 +08:00
|
|
|
if ok := x.Has(AppchainKey(ibtp.To)); !ok {
|
2020-08-24 14:20:19 +08:00
|
|
|
return boltvm.Error(fmt.Sprintf("target appchain does not exist: %s", ibtp.To))
|
|
|
|
}
|
|
|
|
|
|
|
|
app := &appchainMgr.Appchain{}
|
|
|
|
res := x.CrossInvoke(constant.AppchainMgrContractAddr.String(), "GetAppchain", pb.String(srcRelayChainID))
|
|
|
|
if err := json.Unmarshal(res.Result, app); err != nil {
|
|
|
|
return boltvm.Error(err.Error())
|
|
|
|
}
|
|
|
|
|
2021-01-21 15:38:13 +08:00
|
|
|
interchain, ok := x.getInterchain(ibtp.From)
|
2020-08-25 20:01:58 +08:00
|
|
|
if !ok {
|
2020-09-29 15:13:05 +08:00
|
|
|
interchain = &pb.Interchain{
|
|
|
|
ID: ibtp.From,
|
|
|
|
}
|
|
|
|
x.setInterchain(ibtp.From, interchain)
|
2020-08-25 20:01:58 +08:00
|
|
|
}
|
2020-08-24 14:20:19 +08:00
|
|
|
|
2020-08-25 20:01:58 +08:00
|
|
|
if err := x.checkUnionIBTP(app, ibtp, interchain); err != nil {
|
|
|
|
return boltvm.Error(err.Error())
|
2020-08-24 14:20:19 +08:00
|
|
|
}
|
2020-08-25 20:01:58 +08:00
|
|
|
|
2020-08-24 14:20:19 +08:00
|
|
|
x.ProcessIBTP(ibtp, interchain)
|
|
|
|
return boltvm.Success(nil)
|
|
|
|
}
|
|
|
|
|
2020-09-29 15:13:05 +08:00
|
|
|
func (x *InterchainManager) checkUnionIBTP(app *appchainMgr.Appchain, ibtp *pb.IBTP, interchain *pb.Interchain) error {
|
2020-08-25 20:01:58 +08:00
|
|
|
if pb.IBTP_INTERCHAIN == ibtp.Type ||
|
|
|
|
pb.IBTP_ASSET_EXCHANGE_INIT == ibtp.Type ||
|
|
|
|
pb.IBTP_ASSET_EXCHANGE_REDEEM == ibtp.Type ||
|
|
|
|
pb.IBTP_ASSET_EXCHANGE_REFUND == ibtp.Type {
|
|
|
|
|
|
|
|
idx := interchain.InterchainCounter[ibtp.To]
|
|
|
|
if idx+1 != ibtp.Index {
|
|
|
|
return fmt.Errorf(fmt.Sprintf("wrong index, required %d, but %d", idx+1, ibtp.Index))
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
idx := interchain.ReceiptCounter[ibtp.To]
|
|
|
|
if idx+1 != ibtp.Index {
|
|
|
|
if interchain.SourceReceiptCounter[ibtp.To]+1 != ibtp.Index {
|
|
|
|
return fmt.Errorf("wrong receipt index, required %d, but %d", idx+1, ibtp.Index)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-02-24 15:35:08 +08:00
|
|
|
_, err := verifyMultiSign(app, ibtp, ibtp.Proof)
|
|
|
|
return err
|
2021-01-21 15:38:13 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// verifyMultiSign .
|
|
|
|
func verifyMultiSign(app *appchainMgr.Appchain, ibtp *pb.IBTP, proof []byte) (bool, error) {
|
2020-08-24 14:20:19 +08:00
|
|
|
if "" == app.Validators {
|
2021-01-21 15:38:13 +08:00
|
|
|
return false, fmt.Errorf("empty validators in relay chain:%s", app.ID)
|
2020-08-24 14:20:19 +08:00
|
|
|
}
|
|
|
|
var validators BxhValidators
|
|
|
|
if err := json.Unmarshal([]byte(app.Validators), &validators); err != nil {
|
2021-01-21 15:38:13 +08:00
|
|
|
return false, err
|
2020-08-24 14:20:19 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
m := make(map[string]struct{}, 0)
|
|
|
|
for _, validator := range validators.Addresses {
|
|
|
|
m[validator] = struct{}{}
|
|
|
|
}
|
|
|
|
|
|
|
|
var signs pb.SignResponse
|
|
|
|
if err := signs.Unmarshal(ibtp.Proof); err != nil {
|
2021-01-21 15:38:13 +08:00
|
|
|
return false, err
|
2020-08-24 14:20:19 +08:00
|
|
|
}
|
|
|
|
|
2021-01-21 15:38:13 +08:00
|
|
|
threshold := (len(validators.Addresses) - 1) / 3 // TODO be dynamic
|
2020-08-24 14:20:19 +08:00
|
|
|
counter := 0
|
|
|
|
|
2020-10-21 13:50:17 +08:00
|
|
|
ibtpHash := ibtp.Hash()
|
|
|
|
hash := sha256.Sum256([]byte(ibtpHash.String()))
|
2020-08-24 14:20:19 +08:00
|
|
|
for v, sign := range signs.Sign {
|
|
|
|
if _, ok := m[v]; !ok {
|
2021-01-21 15:38:13 +08:00
|
|
|
return false, fmt.Errorf("wrong validator: %s", v)
|
2020-08-24 14:20:19 +08:00
|
|
|
}
|
|
|
|
delete(m, v)
|
2020-10-21 19:38:51 +08:00
|
|
|
addr := types.NewAddressByStr(v)
|
2020-10-21 13:50:17 +08:00
|
|
|
ok, _ := asym.Verify(crypto.Secp256k1, sign, hash[:], *addr)
|
2020-08-24 14:20:19 +08:00
|
|
|
if ok {
|
|
|
|
counter++
|
|
|
|
}
|
|
|
|
if counter > threshold {
|
2021-01-21 15:38:13 +08:00
|
|
|
return true, nil
|
2020-08-24 14:20:19 +08:00
|
|
|
}
|
|
|
|
}
|
2021-01-21 15:38:13 +08:00
|
|
|
return false, fmt.Errorf("multi signs verify fail, counter: %d", counter)
|
2020-08-24 14:20:19 +08:00
|
|
|
}
|
|
|
|
|
2020-09-14 11:29:14 +08:00
|
|
|
func AppchainKey(id string) string {
|
2020-05-07 14:18:19 +08:00
|
|
|
return appchainMgr.PREFIX + id
|
2020-03-29 21:32:01 +08:00
|
|
|
}
|
|
|
|
|
2020-05-07 14:18:19 +08:00
|
|
|
func (x *InterchainManager) indexMapKey(id string) string {
|
2020-03-29 21:32:01 +08:00
|
|
|
return fmt.Sprintf("index-tx-%s", id)
|
|
|
|
}
|
2020-11-18 10:36:12 +08:00
|
|
|
|
|
|
|
func (x *InterchainManager) indexReceiptMapKey(id string) string {
|
|
|
|
return fmt.Sprintf("index-receipt-tx-%s", id)
|
|
|
|
}
|