diff --git a/api/grpc/receipt.go b/api/grpc/receipt.go index 1404572..80e22f9 100644 --- a/api/grpc/receipt.go +++ b/api/grpc/receipt.go @@ -15,7 +15,7 @@ import ( func (cbs *ChainBrokerService) GetReceipt(ctx context.Context, req *pb.TransactionHashMsg) (*pb.Receipt, error) { hash := types.NewHashByStr(req.TxHash) if hash == nil { - return nil, fmt.Errorf("invalid format of receipt hash for querying receipt") + return nil, status.Newf(codes.InvalidArgument, fmt.Sprintf("invalid format of receipt hash %s for querying receipt", hash)).Err() } r, err := cbs.api.Broker().GetReceipt(hash) if err != nil { diff --git a/internal/executor/contracts/contracts_test.go b/internal/executor/contracts/contracts_test.go index d5cc98f..059a73a 100644 --- a/internal/executor/contracts/contracts_test.go +++ b/internal/executor/contracts/contracts_test.go @@ -732,11 +732,11 @@ func TestInterchainManager_HandleIBTP(t *testing.T) { res := im.HandleIBTP(ibtp) assert.False(t, res.Ok) - assert.Equal(t, "this appchain does not exist", string(res.Result)) + assert.Equal(t, "appchain not available: this appchain does not exist", string(res.Result)) res = im.HandleIBTP(ibtp) assert.False(t, res.Ok) - assert.Equal(t, "empty destination chain id", string(res.Result)) + assert.Equal(t, "invalid ibtp: empty destination chain id", string(res.Result)) ibtp = &pb.IBTP{ From: appchainMethod, @@ -752,12 +752,12 @@ func TestInterchainManager_HandleIBTP(t *testing.T) { ibtp.From = appchainMethod2 res = im.HandleIBTP(ibtp) assert.False(t, res.Ok) - assert.Equal(t, true, strings.HasPrefix(string(res.Result), "caller is not bind to ibtp from")) + assert.Equal(t, true, strings.Contains(string(res.Result), "caller is not bind to ibtp from")) ibtp.From = appchainMethod res = im.HandleIBTP(ibtp) assert.False(t, res.Ok) - assert.Equal(t, "index already exists, required 2, but 0", string(res.Result)) + assert.Equal(t, "index already exists: required 2, but 0", string(res.Result)) ibtp.Index = 2 res = im.HandleIBTP(ibtp) @@ -778,7 +778,7 @@ func TestInterchainManager_HandleIBTP(t *testing.T) { ibtp.Type = pb.IBTP_RECEIPT_SUCCESS res = im.HandleIBTP(ibtp) assert.False(t, res.Ok) - assert.Equal(t, "caller is not bind to ibtp to", string(res.Result)) + assert.Equal(t, "invalid ibtp: caller is not bind to ibtp to", string(res.Result)) mockStub.EXPECT().Caller().Return(to.String()).AnyTimes() res = im.HandleIBTP(ibtp) diff --git a/internal/executor/contracts/interchain.go b/internal/executor/contracts/interchain.go index 79ba7d2..31eda2a 100755 --- a/internal/executor/contracts/interchain.go +++ b/internal/executor/contracts/interchain.go @@ -18,6 +18,14 @@ import ( "github.com/meshplus/bitxid" ) +const ( + AppchainNotAvailable = "appchain not available" + InvalidIBTP = "invalid ibtp" + internalError = "internal server error" + ibtpIndexExist = "index already exists" + ibtpIndexWrong = "wrong index" +) + type InterchainManager struct { boltvm.Stub } @@ -180,7 +188,7 @@ func (x *InterchainManager) HandleIBTPs(data []byte) *boltvm.Response { func (x *InterchainManager) checkIBTP(ibtp *pb.IBTP, interchain *pb.Interchain) error { if ibtp.To == "" { - return fmt.Errorf("empty destination chain id") + return fmt.Errorf("%s: empty destination chain id", InvalidIBTP) } if _, ok := x.getInterchain(ibtp.To); !ok { @@ -197,15 +205,15 @@ func (x *InterchainManager) checkIBTP(ibtp *pb.IBTP, interchain *pb.Interchain) pb.IBTP_ASSET_EXCHANGE_REFUND == ibtp.Type { if srcChainInfo.ChainType != appchainMgr.RelaychainType { if err := x.checkPubKeyAndCaller(srcChainInfo.PublicKey); err != nil { - return fmt.Errorf("caller is not bind to ibtp from: %w", err) + return fmt.Errorf("%s: caller is not bind to ibtp from: %w", InvalidIBTP, err) } } idx := interchain.InterchainCounter[ibtp.To] if ibtp.Index <= idx { - return fmt.Errorf(fmt.Sprintf("index already exists, required %d, but %d", idx+1, ibtp.Index)) + return fmt.Errorf(fmt.Sprintf("%s: required %d, but %d", ibtpIndexExist, idx+1, ibtp.Index)) } if ibtp.Index > idx+1 { - return fmt.Errorf(fmt.Sprintf("wrong index, required %d, but %d", idx+1, ibtp.Index)) + return fmt.Errorf(fmt.Sprintf("%s: required %d, but %d", ibtpIndexWrong, idx+1, ibtp.Index)) } } else { if srcChainInfo.ChainType != appchainMgr.RelaychainType { @@ -214,16 +222,16 @@ func (x *InterchainManager) checkIBTP(ibtp *pb.IBTP, interchain *pb.Interchain) return err } if err := x.checkPubKeyAndCaller(destChainInfo.PublicKey); err != nil { - return fmt.Errorf("caller is not bind to ibtp to") + return fmt.Errorf("%s: caller is not bind to ibtp to", InvalidIBTP) } } idx := interchain.ReceiptCounter[ibtp.To] if ibtp.Index <= idx { - return fmt.Errorf(fmt.Sprintf("receipt index already exists, required %d, but %d", idx+1, ibtp.Index)) + return fmt.Errorf(fmt.Sprintf("%s: required %d, but %d", ibtpIndexExist, 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)) + return fmt.Errorf(fmt.Sprintf("%s: required %d, but %d", ibtpIndexWrong, idx+1, ibtp.Index)) } } @@ -252,13 +260,13 @@ func (x *InterchainManager) checkPubKeyAndCaller(pub string) error { func (x *InterchainManager) checkAppchain(id string) (*pb.Interchain, *appchainMgr.Appchain, error) { interchain, ok := x.getInterchain(id) if !ok { - return nil, nil, fmt.Errorf("this appchain does not exist") + return nil, nil, fmt.Errorf("%s: this appchain does not exist", AppchainNotAvailable) } app := &appchainMgr.Appchain{} res := x.CrossInvoke(constant.AppchainMgrContractAddr.String(), "GetAppchain", pb.String(id)) if !res.Ok { - return nil, nil, fmt.Errorf("get appchain info error: " + string(res.Result)) + return nil, nil, fmt.Errorf("%s: get appchain info error: %s", AppchainNotAvailable, string(res.Result)) } if err := json.Unmarshal(res.Result, app); err != nil { @@ -266,7 +274,7 @@ func (x *InterchainManager) checkAppchain(id string) (*pb.Interchain, *appchainM } if app.Status != appchainMgr.AppchainAvailable { - return nil, nil, fmt.Errorf("the appchain status is " + string(app.Status) + ", can not handle IBTP") + return nil, nil, fmt.Errorf("%s: the appchain status is %s, can not handle IBTP", AppchainNotAvailable, string(app.Status)) } return interchain, app, nil @@ -277,7 +285,7 @@ func (x *InterchainManager) getAppchainInfo(chainMethod string) (*appchainMgr.Ap srcChain := &appchainMgr.Appchain{} res := x.CrossInvoke(constant.AppchainMgrContractAddr.String(), "GetAppchain", pb.String(chainMethod)) if err := json.Unmarshal(res.Result, srcChain); err != nil { - return nil, fmt.Errorf("unmarshal appchain info error: %w", err) + return nil, fmt.Errorf("%s: unmarshal appchain info error: %w", internalError, err) } return srcChain, nil } diff --git a/internal/executor/executor.go b/internal/executor/executor.go index d24d100..a7a72aa 100755 --- a/internal/executor/executor.go +++ b/internal/executor/executor.go @@ -180,15 +180,17 @@ func (exec *BlockExecutor) verifyProofs(blockWrapper *BlockWrapper) { txs := block.Transactions wg.Add(len(txs)) + errM := make(map[int]string) for i, tx := range txs { go func(i int, tx *pb.Transaction) { defer wg.Done() if _, ok := blockWrapper.invalidTx[i]; !ok { - ok, _ := exec.ibtpVerify.CheckProof(tx) + ok, err := exec.ibtpVerify.CheckProof(tx) if !ok { lock.Lock() defer lock.Unlock() invalidTxs = append(invalidTxs, i) + errM[i] = err.Error() } } }(i, tx) @@ -196,7 +198,7 @@ func (exec *BlockExecutor) verifyProofs(blockWrapper *BlockWrapper) { wg.Wait() for _, i := range invalidTxs { - blockWrapper.invalidTx[i] = "tx has invalid ibtp proof" + blockWrapper.invalidTx[i] = agency.InvalidReason(errM[i]) } } diff --git a/pkg/proof/proof_pool.go b/pkg/proof/proof_pool.go index f3b4ebf..d3629c0 100644 --- a/pkg/proof/proof_pool.go +++ b/pkg/proof/proof_pool.go @@ -22,6 +22,13 @@ import ( "github.com/sirupsen/logrus" ) +const ( + InvalidIBTP = "invalid ibtp" + AppchainNotAvailable = "appchain not available" + NoBindRule = "appchain didn't register rule" + internalError = "internal server error" +) + type VerifyPool struct { proofs sync.Map //ibtp proof cache ledger ledger.Ledger @@ -73,12 +80,12 @@ type bxhValidators struct { // verifyMultiSign . func verifyMultiSign(app *appchainMgr.Appchain, ibtp *pb.IBTP, proof []byte) (bool, error) { - if "" == app.Validators { - return false, fmt.Errorf("empty validators in relay chain:%s", app.ID) + if app.Validators == "" { + return false, fmt.Errorf("%s: empty validators in relay chain:%s", internalError, app.ID) } var validators bxhValidators if err := json.Unmarshal([]byte(app.Validators), &validators); err != nil { - return false, err + return false, fmt.Errorf("%s: %w", InvalidIBTP, err) } m := make(map[string]struct{}, 0) @@ -87,7 +94,7 @@ func verifyMultiSign(app *appchainMgr.Appchain, ibtp *pb.IBTP, proof []byte) (bo } var signs pb.SignResponse - if err := signs.Unmarshal(ibtp.Proof); err != nil { + if err := signs.Unmarshal(proof); err != nil { return false, err } @@ -98,7 +105,7 @@ func verifyMultiSign(app *appchainMgr.Appchain, ibtp *pb.IBTP, proof []byte) (bo hash := sha256.Sum256([]byte(ibtpHash.String())) for v, sign := range signs.Sign { if _, ok := m[v]; !ok { - return false, fmt.Errorf("wrong validator: %s", v) + return false, fmt.Errorf("%s: wrong validator: %s", InvalidIBTP, v) } delete(m, v) addr := types.NewAddressByStr(v) @@ -110,33 +117,32 @@ func verifyMultiSign(app *appchainMgr.Appchain, ibtp *pb.IBTP, proof []byte) (bo return true, nil } } - return false, fmt.Errorf("multi signs verify fail, counter: %d", counter) + return false, fmt.Errorf("%s: multi signs verify fail, counter: %d", InvalidIBTP, counter) } func (pl *VerifyPool) verifyProof(ibtp *pb.IBTP, proof []byte) (bool, error) { if proof == nil { - return false, fmt.Errorf("empty proof") + return false, fmt.Errorf("%s:, empty proof", InvalidIBTP) } proofHash := sha256.Sum256(proof) if !bytes.Equal(proofHash[:], ibtp.Proof) { - return false, fmt.Errorf("proof hash is not correct") + return false, fmt.Errorf("%s: proof hash is not correct", InvalidIBTP) } // get real appchain id for union ibtp from := ibtp.From if len(strings.Split(ibtp.From, "-")) == 2 { from = strings.Split(ibtp.From, "-")[1] - return true, nil } app := &appchainMgr.Appchain{} ok, data := pl.getAccountState(constant.AppchainMgrContractAddr, contracts.AppchainKey(from)) // ibtp.From if !ok { - return false, fmt.Errorf("cannot get registered appchain") + return false, fmt.Errorf("%s: cannot get registered appchain", AppchainNotAvailable) } err := json.Unmarshal(data, app) if err != nil { - return false, fmt.Errorf("unmarshal appchain data fail: %w", err) + return false, fmt.Errorf("%s: unmarshal appchain data fail: %w", internalError, err) } if len(strings.Split(ibtp.From, "-")) == 2 { @@ -148,18 +154,18 @@ func (pl *VerifyPool) verifyProof(ibtp *pb.IBTP, proof []byte) (bool, error) { ok, data = pl.getAccountState(constant.RuleManagerContractAddr, contracts.RuleKey(from)) if ok { if err := json.Unmarshal(data, rl); err != nil { - return false, fmt.Errorf("unmarshal rule data error: %w", err) + return false, fmt.Errorf("%s: unmarshal rule data error: %w", internalError, err) } validateAddr = rl.Address } else { if app.ChainType != appchainMgr.FabricType { - return false, fmt.Errorf("appchain didn't register rule") + return false, fmt.Errorf(NoBindRule) } } ok, err = pl.ve.Validate(validateAddr, from, proof, ibtp.Payload, app.Validators) // ibtp.From if err != nil { - return false, err + return false, fmt.Errorf("%s: %w", InvalidIBTP, err) } return ok, nil } diff --git a/pkg/proof/proof_test.go b/pkg/proof/proof_test.go index f497713..e754dea 100644 --- a/pkg/proof/proof_test.go +++ b/pkg/proof/proof_test.go @@ -171,14 +171,14 @@ func TestVerifyPool_CheckProof2(t *testing.T) { } signData, err := sign.Marshal() require.Nil(t, err) - ibtp.Proof = signData + proof := signData ok, err := verifyMultiSign(chain, ibtp, nil) require.NotNil(t, err) require.False(t, ok) chain.Validators = string(addrsData) - ok, err = verifyMultiSign(chain, ibtp, nil) + ok, err = verifyMultiSign(chain, ibtp, proof) require.Nil(t, err) require.True(t, ok) }