Skip to content

Commit

Permalink
Improve bitcoin tx deposit (chainx-org#357)
Browse files Browse the repository at this point in the history
* Improve bitcoin tx deposit

Signed-off-by: koushiro <[email protected]>

* update chainx-js types

Signed-off-by: koushiro <[email protected]>
  • Loading branch information
koushiro authored Nov 18, 2020
1 parent 8b3dce1 commit e8210e2
Show file tree
Hide file tree
Showing 5 changed files with 75 additions and 84 deletions.
6 changes: 3 additions & 3 deletions scripts/chainx-js/chainx_types_manual.json
Original file line number Diff line number Diff line change
Expand Up @@ -140,12 +140,12 @@
"BtcTxResult": {
"_enum": [
"Success",
"Failed"
"Failure"
]
},
"BtcTxState": {
"result": "BtcTxResult",
"tx_type": "BtcTxType"
"tx_type": "BtcTxType",
"result": "BtcTxResult"
},
"BtcTxType": {
"_enum": [
Expand Down
8 changes: 4 additions & 4 deletions scripts/chainx-js/res/chainx_types.json
Original file line number Diff line number Diff line change
Expand Up @@ -161,8 +161,8 @@
"finalFee": "Balance"
},
"UnbondedIndex": "u32",
"Desc": "Text",
"Token": "Text",
"Desc": "Text",
"AddrStr": "Text",
"HandicapInfo": "Handicap",
"Price": "u128",
Expand Down Expand Up @@ -304,12 +304,12 @@
"BtcTxResult": {
"_enum": [
"Success",
"Failed"
"Failure"
]
},
"BtcTxState": {
"result": "BtcTxResult",
"txType": "BtcTxType"
"txType": "BtcTxType",
"result": "BtcTxResult"
},
"BtcTxType": {
"_enum": [
Expand Down
1 change: 0 additions & 1 deletion xpallets/gateway/bitcoin/src/benchmarking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,6 @@ benchmarks! {

let (signed_tx, _, _) = withdraw_tx();
let tx_raw: Vec<u8> = serialization::serialize(&signed_tx).into();

}: _(RawOrigin::Signed(bob), Some(tx_raw))
verify {
assert_eq!(WithdrawalProposal::<T>::get().unwrap().sig_state, VoteResult::Finish);
Expand Down
32 changes: 16 additions & 16 deletions xpallets/gateway/bitcoin/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,16 +30,6 @@ use frame_support::{
use frame_system::{ensure_root, ensure_signed};
use orml_utilities::with_transaction_result;

use chainx_primitives::{AssetId, ReferralId};
use xp_gateway_common::AccountExtractor;
use xp_logging::{debug, error, info};
use xpallet_assets::{BalanceOf, Chain, ChainT, WithdrawalLimit};
use xpallet_gateway_common::{
traits::{AddrBinding, ChannelBinding, TrusteeSession},
trustees::bitcoin::BtcTrusteeAddrInfo,
};
use xpallet_support::{str, try_addr};

#[cfg(feature = "std")]
pub use light_bitcoin::primitives::h256_rev;
pub use light_bitcoin::{
Expand All @@ -53,15 +43,25 @@ use light_bitcoin::{
serialization::{deserialize, Reader},
};

pub use self::types::{BtcAddress, BtcParams, BtcTxVerifier, BtcWithdrawalProposal};
use self::types::{
BtcDepositCache, BtcHeaderIndex, BtcHeaderInfo, BtcRelayedTx, BtcRelayedTxInfo, BtcTxResult,
BtcTxState,
use chainx_primitives::{AssetId, ReferralId};
use xp_gateway_common::AccountExtractor;
use xp_logging::{debug, error, info};
use xpallet_assets::{BalanceOf, Chain, ChainT, WithdrawalLimit};
use xpallet_gateway_common::{
traits::{AddrBinding, ChannelBinding, TrusteeSession},
trustees::bitcoin::BtcTrusteeAddrInfo,
};
use crate::weight_info::WeightInfo;
use crate::{
use xpallet_support::{str, try_addr};

pub use self::types::{BtcAddress, BtcParams, BtcTxVerifier, BtcWithdrawalProposal};
use self::{
trustee::{get_last_trustee_address_pair, get_trustee_address_pair},
tx::remove_pending_deposit,
types::{
BtcDepositCache, BtcHeaderIndex, BtcHeaderInfo, BtcRelayedTx, BtcRelayedTxInfo,
BtcTxResult, BtcTxState,
},
weight_info::WeightInfo,
};

// syntactic sugar for native log.
Expand Down
112 changes: 52 additions & 60 deletions xpallets/gateway/bitcoin/src/tx/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,94 +52,86 @@ pub fn process_tx<T: Trait>(
let result = match meta_type {
BtcTxMetaType::<_>::Deposit(deposit_info) => deposit::<T>(tx.hash(), deposit_info),
BtcTxMetaType::<_>::Withdrawal => withdraw::<T>(tx),
BtcTxMetaType::HotAndCold | BtcTxMetaType::TrusteeTransition => BtcTxResult::Success,
// mark `Irrelevance` be `Failure` so that it could be replayed in the future
BtcTxMetaType::<_>::Irrelevance => BtcTxResult::Failure,
BtcTxMetaType::HotAndCold | BtcTxMetaType::TrusteeTransition => BtcTxResult::Success,
};

BtcTxState { tx_type, result }
}

fn deposit<T: Trait>(hash: H256, deposit_info: BtcDepositInfo<T::AccountId>) -> BtcTxResult {
if deposit_info.op_return.is_none() && deposit_info.input_addr.is_none() {
warn!("[deposit] Process a deposit tx ({:?}) but do not have valid opreturn & not have input addr", hash_rev(hash));
return BtcTxResult::Failure;
}

let account_info = match deposit_info.op_return {
Some((account, referral)) => {
if let Some(addr) = deposit_info.input_addr {
let addr = addr2vecu8(&addr);
// remove old unbinding deposit info
remove_pending_deposit::<T>(&addr, &account);
// update or override binding info
T::AddrBinding::update_binding(Module::<T>::chain(), addr, account.clone());
} else {
// no input addr
debug!(
"[deposit] Deposit tx ({:?}) has no input addr, but has opreturn, who:{:?}",
hash, account
);
}
fn deposit<T: Trait>(txid: H256, deposit_info: BtcDepositInfo<T::AccountId>) -> BtcTxResult {
let account_info = match (deposit_info.op_return, deposit_info.input_addr) {
(Some((account, referral)), Some(input_addr)) => {
let input_addr = addr2vecu8(&input_addr);
// remove old unbinding deposit info
remove_pending_deposit::<T>(&input_addr, &account);
// update or override binding info
T::AddrBinding::update_binding(Module::<T>::chain(), input_addr, account.clone());
AccountInfo::<T::AccountId>::Account((account, referral))
}
None => {
if let Some(addr) = deposit_info.input_addr {
// no opreturn, use addr to get accountid
let addr_bytes = addr2vecu8(&addr);
match T::AddrBinding::get_binding(Module::<T>::chain(), addr_bytes) {
Some(account) => AccountInfo::Account((account, None)),
None => AccountInfo::Address(addr),
}
} else {
// should not meet this branch, due it's handled before, it's unreachable
error!(
"[deposit] The deposit tx ({:?}) has no input addr and opreturn",
hash_rev(hash)
);
return BtcTxResult::Failure;
(Some((account, referral)), None) => {
// has opreturn but no input addr
debug!(
"[deposit] Deposit tx ({:?}) has no input addr, but has opreturn, who:{:?}",
hash_rev(txid),
account
);
AccountInfo::<T::AccountId>::Account((account, referral))
}
(None, Some(input_addr)) => {
// no opreturn but have input addr, use input addr to get accountid
let addr_bytes = addr2vecu8(&input_addr);
match T::AddrBinding::get_binding(Module::<T>::chain(), addr_bytes) {
Some(account) => AccountInfo::Account((account, None)),
None => AccountInfo::Address(input_addr),
}
}
(None, None) => {
warn!(
"[deposit] Process deposit tx ({:?}) but missing valid opreturn and input addr",
hash_rev(txid)
);
return BtcTxResult::Failure;
}
};

match account_info {
AccountInfo::<_>::Account((accountid, channel_name)) => {
T::Channel::update_binding(
&<Module<T> as ChainT<_>>::ASSET_ID,
&accountid,
channel_name,
);

if deposit_token::<T>(hash, &accountid, deposit_info.deposit_value).is_err() {
return BtcTxResult::Failure;
AccountInfo::<_>::Account((account, referral)) => {
T::Channel::update_binding(&<Module<T> as ChainT<_>>::ASSET_ID, &account, referral);
match deposit_token::<T>(txid, &account, deposit_info.deposit_value) {
Ok(_) => {
info!(
"[deposit] Deposit tx ({:?}) success, who:{:?}, balance:{}",
hash_rev(txid),
account,
deposit_info.deposit_value
);
BtcTxResult::Success
}
Err(_) => BtcTxResult::Failure,
}
info!(
"[deposit] Deposit tx ({:?}) success, who:{:?}, balance:{}",
hash_rev(hash),
accountid,
deposit_info.deposit_value
);
}
AccountInfo::<_>::Address(addr) => {
insert_pending_deposit::<T>(&addr, hash, deposit_info.deposit_value);
AccountInfo::<_>::Address(input_addr) => {
insert_pending_deposit::<T>(&input_addr, txid, deposit_info.deposit_value);
info!(
"[deposit] Deposit tx ({:?}) into pending, addr:{:?}, balance:{}",
hash_rev(hash),
str!(addr2vecu8(&addr)),
hash_rev(txid),
str!(addr2vecu8(&input_addr)),
deposit_info.deposit_value
);
BtcTxResult::Success
}
};
BtcTxResult::Success
}
}

fn deposit_token<T: Trait>(tx_hash: H256, who: &T::AccountId, balance: u64) -> DispatchResult {
fn deposit_token<T: Trait>(txid: H256, who: &T::AccountId, balance: u64) -> DispatchResult {
let id: AssetId = <Module<T> as ChainT<_>>::ASSET_ID;

let value: BalanceOf<T> = balance.saturated_into();
match <xpallet_gateway_records::Module<T>>::deposit(&who, id, value) {
Ok(()) => {
Module::<T>::deposit_event(Event::<T>::Deposited(tx_hash, who.clone(), value));
Module::<T>::deposit_event(Event::<T>::Deposited(txid, who.clone(), value));
Ok(())
}
Err(err) => {
Expand Down

0 comments on commit e8210e2

Please sign in to comment.