diff --git a/changelog.md b/changelog.md index d8c4487b73..8bf218e88b 100644 --- a/changelog.md +++ b/changelog.md @@ -10,6 +10,10 @@ * [4070](https://github.com/zeta-chain/node/pull/4070) - remove support for v1 revert address for BTC +### Fixes + +* [4090](https://github.com/zeta-chain/node/pull/4090) - print error message in detail if unable to decode Bitcoin memo + ## v33.0.0 ### Features diff --git a/e2e/e2etests/test_bitcoin_deposit_invalid_memo_revert.go b/e2e/e2etests/test_bitcoin_deposit_invalid_memo_revert.go index cb180f9658..1c364252bd 100644 --- a/e2e/e2etests/test_bitcoin_deposit_invalid_memo_revert.go +++ b/e2e/e2etests/test_bitcoin_deposit_invalid_memo_revert.go @@ -5,6 +5,7 @@ import ( "github.com/zeta-chain/node/e2e/runner" "github.com/zeta-chain/node/e2e/utils" + "github.com/zeta-chain/node/pkg/memo" crosschaintypes "github.com/zeta-chain/node/x/crosschain/types" ) @@ -20,7 +21,7 @@ func TestBitcoinDepositInvalidMemoRevert(r *runner.E2ERunner, args []string) { txHash, err := r.SendToTSSWithMemo(0.1, nil) require.NoError(r, err) - // wait for the cctx to be mined + // wait for the cctx to be reverted cctx := utils.WaitCctxMinedByInboundHash(r.Ctx, txHash.String(), r.CctxClient, r.Logger, r.CctxTimeout) r.Logger.CCTX(*cctx, "deposit without memo") utils.RequireCCTXStatus(r, cctx, crosschaintypes.CctxStatus_Reverted) @@ -31,20 +32,49 @@ func TestBitcoinDepositInvalidMemoRevert(r *runner.E2ERunner, args []string) { txHash, err = r.SendToTSSWithMemo(0.1, []byte{}) require.NoError(r, err) - // wait for the cctx to be mined + // wait for the cctx to be reverted cctx = utils.WaitCctxMinedByInboundHash(r.Ctx, txHash.String(), r.CctxClient, r.Logger, r.CctxTimeout) r.Logger.CCTX(*cctx, "deposit empty memo") utils.RequireCCTXStatus(r, cctx, crosschaintypes.CctxStatus_Reverted) require.EqualValues(r, crosschaintypes.InboundStatus_INVALID_MEMO, cctx.InboundParams.Status) // CASE 3 - // make a deposit with an invalid memo - txHash, err = r.SendToTSSWithMemo(0.1, []byte("invalid memo")) + // make a deposit with an invalid legacy memo + txHash, err = r.SendToTSSWithMemo(0.1, []byte("invalid legacy memo")) require.NoError(r, err) - // wait for the cctx to be mined + // wait for the cctx to be reverted cctx = utils.WaitCctxMinedByInboundHash(r.Ctx, txHash.String(), r.CctxClient, r.Logger, r.CctxTimeout) r.Logger.CCTX(*cctx, "deposit invalid memo") utils.RequireCCTXStatus(r, cctx, crosschaintypes.CctxStatus_Reverted) require.EqualValues(r, crosschaintypes.InboundStatus_INVALID_MEMO, cctx.InboundParams.Status) + + // CASE 4 + // make a deposit with an invalid standard memo + memo := &memo.InboundMemo{ + Header: memo.Header{ + Version: 0, + EncodingFmt: memo.EncodingFmtCompactShort, + OpCode: memo.OpCodeDepositAndCall, + }, + FieldsV0: memo.FieldsV0{ + Receiver: r.TestDAppV2ZEVMAddr, + Payload: []byte("payload is not allowed"), + }, + } + + // modify the op code to 0b0000 (deposit), so payload won't be allowed + memoBytes, err := memo.EncodeToBytes() + require.NoError(r, err) + memoBytes[2] = 0x00 + + // deposit to TSS + txHash, err = r.SendToTSSWithMemo(0.1, memoBytes) + require.NoError(r, err) + + // wait for the cctx to be reverted + cctx = utils.WaitCctxMinedByInboundHash(r.Ctx, txHash.String(), r.CctxClient, r.Logger, r.CctxTimeout) + r.Logger.CCTX(*cctx, "deposit invalid standard memo") + utils.RequireCCTXStatus(r, cctx, crosschaintypes.CctxStatus_Reverted) + require.EqualValues(r, crosschaintypes.InboundStatus_INVALID_MEMO, cctx.InboundParams.Status) } diff --git a/zetaclient/chains/bitcoin/observer/inbound.go b/zetaclient/chains/bitcoin/observer/inbound.go index 4d56664c7b..7afc6d670d 100644 --- a/zetaclient/chains/bitcoin/observer/inbound.go +++ b/zetaclient/chains/bitcoin/observer/inbound.go @@ -197,7 +197,7 @@ func (ob *Observer) GetInboundVoteFromBtcEvent(event *BTCInboundEvent) *crosscha // if the memo is invalid, we set the status in the event, the inbound will be observed as invalid err := event.DecodeMemoBytes(ob.Chain().ChainId) if err != nil { - ob.Logger().Inbound.Info().Fields(lf).Msgf("invalid memo bytes: %s", hex.EncodeToString(event.MemoBytes)) + ob.Logger().Inbound.Info().Err(err).Fields(lf).Msgf("invalid memo: %s", hex.EncodeToString(event.MemoBytes)) event.Status = crosschaintypes.InboundStatus_INVALID_MEMO }