feat(*): add bvm transaction receipt error type

This commit is contained in:
Alexader 2021-04-23 10:04:10 +08:00
parent 80d8057fcf
commit b04f2c2a52
6 changed files with 51 additions and 35 deletions

View File

@ -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 {

View File

@ -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)

View File

@ -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
}

View File

@ -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])
}
}

View File

@ -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
}

View File

@ -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)
}