Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

feat: enable inscription parsing on Bitcoin mainnet #3425

Merged
merged 3 commits into from
Jan 29, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
* [3357](https://github.com/zeta-chain/node/pull/3357) - cosmos-sdk v.50.x upgrade
* [3358](https://github.com/zeta-chain/node/pull/3358) - register aborted CCTX for Bitcoin inbound that carries insufficient depositor fee
* [3368](https://github.com/zeta-chain/node/pull/3368) - cli command to fetch inbound ballot from inbound hash added to zetatools.
* [3425](https://github.com/zeta-chain/node/pull/3425) - enable inscription parsing on Bitcoin mainnet

### Refactor

Expand Down
107 changes: 1 addition & 106 deletions zetaclient/chains/bitcoin/observer/inbound.go
Original file line number Diff line number Diff line change
Expand Up @@ -285,7 +285,7 @@ func (ob *Observer) GetInboundVoteFromBtcEvent(event *BTCInboundEvent) *types.Ms
}

// GetBtcEvent returns a valid BTCInboundEvent or nil
// it uses witness data to extract the sender address, except for mainnet
// it uses witness data to extract the sender address
func GetBtcEvent(
ctx context.Context,
rpc RPC,
Expand All @@ -296,114 +296,9 @@ func GetBtcEvent(
netParams *chaincfg.Params,
feeCalculator common.DepositorFeeCalculator,
) (*BTCInboundEvent, error) {
if netParams.Name == chaincfg.MainNetParams.Name {
return GetBtcEventWithoutWitness(ctx, rpc, tx, tssAddress, blockNumber, logger, netParams, feeCalculator)
}

return GetBtcEventWithWitness(ctx, rpc, tx, tssAddress, blockNumber, logger, netParams, feeCalculator)
}

// GetBtcEventWithoutWitness either returns a valid BTCInboundEvent or nil
// Note: the caller should retry the tx on error (e.g., GetSenderAddressByVin failed)
// TODO(revamp): simplify this function
func GetBtcEventWithoutWitness(
ctx context.Context,
rpc RPC,
tx btcjson.TxRawResult,
tssAddress string,
blockNumber uint64,
logger zerolog.Logger,
netParams *chaincfg.Params,
feeCalculator common.DepositorFeeCalculator,
) (*BTCInboundEvent, error) {
var (
found bool
value float64
depositorFee float64
memo []byte
status = types.InboundStatus_SUCCESS
)

// prepare logger fields
lf := map[string]any{
logs.FieldMethod: "GetBtcEventWithoutWitness",
logs.FieldTx: tx.Txid,
}

if len(tx.Vout) >= 2 {
// 1st vout must have tss address as receiver with p2wpkh scriptPubKey
vout0 := tx.Vout[0]
script := vout0.ScriptPubKey.Hex
if len(script) == 44 && script[:4] == "0014" {
// P2WPKH output: 0x00 + 20 bytes of pubkey hash
receiver, err := common.DecodeScriptP2WPKH(vout0.ScriptPubKey.Hex, netParams)
if err != nil { // should never happen
return nil, err
}

// skip irrelevant tx to us
if receiver != tssAddress {
return nil, nil
}

// calculate depositor fee
depositorFee, err = feeCalculator(ctx, rpc, &tx, netParams)
if err != nil {
return nil, errors.Wrapf(err, "error calculating depositor fee for inbound %s", tx.Txid)
}

// deduct depositor fee
// to allow developers to track failed deposit caused by insufficient depositor fee,
// the error message will be forwarded to zetacore to register a failed CCTX
value, err = DeductDepositorFee(vout0.Value, depositorFee)
if err != nil {
value = 0
status = types.InboundStatus_INSUFFICIENT_DEPOSITOR_FEE
logger.Error().Err(err).Fields(lf).Msgf("unable to deduct depositor fee")
}

// 2nd vout must be a valid OP_RETURN memo
vout1 := tx.Vout[1]
memo, found, err = common.DecodeOpReturnMemo(vout1.ScriptPubKey.Hex)
if err != nil {
lf["memo"] = vout1.ScriptPubKey.Hex
logger.Error().Err(err).Fields(lf).Msgf("unable to decode OP_RETURN memo")
return nil, nil
}
}
}
// event found, get sender address
if found {
if len(tx.Vin) == 0 { // should never happen
return nil, fmt.Errorf("GetBtcEvent: no input found for inbound: %s", tx.Txid)
}

// get sender address by input (vin)
fromAddress, err := GetSenderAddressByVin(ctx, rpc, tx.Vin[0], netParams)
if err != nil {
return nil, errors.Wrapf(err, "error getting sender address for inbound: %s", tx.Txid)
}

// skip this tx and move on (e.g., due to unknown script type)
// we don't know whom to refund if this tx gets reverted in zetacore
if fromAddress == "" {
return nil, nil
}

return &BTCInboundEvent{
FromAddress: fromAddress,
ToAddress: tssAddress,
Value: value,
DepositorFee: depositorFee,
MemoBytes: memo,
BlockNumber: blockNumber,
TxHash: tx.Txid,
Status: status,
}, nil
}
return nil, nil
}

// GetSenderAddressByVin get the sender address from the transaction input (vin)
func GetSenderAddressByVin(
ctx context.Context,
Expand Down
Loading