Skip to content

Commit b7b2df1

Browse files
eee-bytegguoss
authored andcommitted
Abnormal cash withdrawals (paritytech#316)
* Fix give change Optimize log * Fix irr_block * Modify decoding mode * Modify 'chainx_getWithdrawTx' * Make format btc Change sign status * Delete unused params
1 parent 8bfc71c commit b7b2df1

File tree

13 files changed

+106
-80
lines changed

13 files changed

+106
-80
lines changed
19.6 KB
Binary file not shown.

cli/src/genesis_config.rs

Lines changed: 13 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -272,29 +272,19 @@ pub fn testnet_genesis(genesis_spec: GenesisSpec) -> GenesisConfig {
272272
}),
273273
bitcoin: Some(XBridgeOfBTCConfig {
274274
// start genesis block: (genesis, blocknumber)
275-
genesis: (
276-
BlockHeader {
277-
version: 980090880,
278-
previous_header_hash: H256::from_reversed_str(
279-
"00000000000000ab706b663326210d03780fea6ecfe0cc59c78f0c7dddba9cc2",
280-
),
281-
merkle_root_hash: H256::from_reversed_str(
282-
"91ee572484dabc6edf5a8da44a4fb55b5040facf66624b2a37c4f633070c60c8",
283-
),
284-
time: 1550454022,
285-
bits: Compact::new(436283074),
286-
nonce: 47463732,
287-
},
288-
1457525,
289-
),
290-
params_info: Params::new(
291-
520159231, // max_bits
292-
2 * 60 * 60, // block_max_future
293-
3, // max_fork_route_preset
294-
2 * 7 * 24 * 60 * 60, // target_timespan_seconds
295-
10 * 60, // target_spacing_seconds
296-
4,
297-
), // retargeting_factor
275+
genesis: (BlockHeader {
276+
version: 536870912,
277+
previous_header_hash: H256::from_reversed_str("0000000000005a693961608af8c00d25fa71bde2d9e3eae4494c10baaeed4070"),
278+
merkle_root_hash: H256::from_reversed_str("9e7add48fd35513b37309fed6c0b9e116621de9385548aee5c4bb313476ff30a"),
279+
time: 1550490136,
280+
bits: Compact::new(453049348),
281+
nonce: 3012999283,
282+
}, 1474333),
283+
params_info: Params::new(520159231, // max_bits
284+
2 * 60 * 60, // block_max_future
285+
2 * 7 * 24 * 60 * 60, // target_timespan_seconds
286+
10 * 60, // target_spacing_seconds
287+
4), // retargeting_factor
298288
network_id: 1,
299289
irr_block: 6,
300290
reserved: 2100,

rpc/src/chainx/impl_rpc.rs

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ extern crate hex;
44

55
use self::types::Revocation;
66
use super::*;
7+
use codec::Encode;
78
use keys::DisplayLayout;
89
use runtime_primitives::traits::{Header, ProvideRuntimeApi};
910
use srml_support::storage::generator::{StorageMap, StorageValue};
@@ -810,8 +811,6 @@ where
810811
}
811812

812813
fn fee(&self, call_params: String, tx_length: u64) -> Result<Option<u64>> {
813-
use codec::Encode;
814-
815814
if !call_params.starts_with("0x") {
816815
return Err(BinanryStartErr.into());
817816
}
@@ -835,6 +834,42 @@ where
835834
let transaction_fee = transaction_fee?;
836835
Ok(transaction_fee)
837836
}
837+
838+
fn withdraw_tx(&self, chain: Chain) -> Result<Option<WithdrawTxInfo>> {
839+
let state = self.best_state()?;
840+
match chain {
841+
Chain::Bitcoin => {
842+
let key = <xbitcoin::TrusteeRedeemScript<Runtime>>::key();
843+
match Self::pickout::<xbitcoin::TrusteeScriptInfo>(&state, &key)? {
844+
Some(script) => {
845+
let key = <TxProposal<Runtime>>::key();
846+
if let Some(candidate) =
847+
Self::pickout::<CandidateTx<AccountId>>(&state, &key)?
848+
{
849+
let mut sign_status = false;
850+
if candidate.sig_status == VoteResult::Finish {
851+
sign_status = true;
852+
}
853+
let raw_tx = candidate.tx.encode();
854+
if raw_tx.len() < 2 {
855+
return Ok(None);
856+
}
857+
let tx_info = WithdrawTxInfo {
858+
tx: hex::encode(raw_tx[2..].to_vec()),
859+
redeem_script: hex::encode(script.hot_redeem_script),
860+
sign_status: sign_status,
861+
};
862+
Ok(Some(tx_info))
863+
} else {
864+
return Ok(None);
865+
}
866+
}
867+
None => return Ok(None),
868+
}
869+
}
870+
_ => return Ok(None),
871+
}
872+
}
838873
}
839874

840875
fn get_btc_deposit_info(

rpc/src/chainx/mod.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ use self::error::Result;
4747
use self::types::{
4848
AssetInfo, DepositInfo, IntentionInfo, NominationRecord, PageData, PairInfo,
4949
PseduIntentionInfo, PseduNominationRecord, QuotationsList, TotalAssetInfo, TrusteeInfo,
50-
WithdrawInfo, WithdrawStatus,
50+
WithdrawInfo, WithdrawStatus, WithdrawTxInfo,
5151
};
5252
use chainx::error::ErrorKind::*;
5353
const MAX_PAGE_SIZE: u32 = 100;
@@ -109,6 +109,9 @@ pub trait ChainXApi<Number, AccountId, Balance, BlockNumber, SignedBlock> {
109109

110110
#[rpc(name = "chainx_getFeeByCallAndLength")]
111111
fn fee(&self, String, u64) -> Result<Option<u64>>;
112+
113+
#[rpc(name = "chainx_getWithdrawTx")]
114+
fn withdraw_tx(&self, chain: Chain) -> Result<Option<WithdrawTxInfo>>;
112115
}
113116

114117
/// ChainX API

rpc/src/chainx/types.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -294,3 +294,14 @@ impl WithdrawInfo {
294294
}
295295
}
296296
}
297+
298+
#[derive(Debug, PartialEq, Serialize, Deserialize)]
299+
#[serde(rename_all = "camelCase")]
300+
pub struct WithdrawTxInfo {
301+
/// tx
302+
pub tx: String,
303+
/// redeem_script
304+
pub redeem_script: String,
305+
/// sign_status
306+
pub sign_status: bool,
307+
}

xrml/xbridge/bitcoin/src/blockchain.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ impl<T: Trait> Chain<T> {
4343
None => return Err(ChainErr::OtherErr("Not found block header for this hash")),
4444
};
4545

46-
runtime_io::print("[bridge-btc] Confirmed header height:");
46+
runtime_io::print("[bridge-btc] Confirmed header:");
4747
runtime_io::print(confirmed_header.height as u64);
4848

4949
let tx_list = confirmed_header.txid;
@@ -52,7 +52,7 @@ impl<T: Trait> Chain<T> {
5252
// deposit & withdraw
5353
match handle_tx::<T>(&txid) {
5454
Err(_) => {
55-
runtime_io::print("[bridge-btc] Handle_tx error, tx hash:");
55+
runtime_io::print("[bridge-btc] Handle tx error, tx hash:");
5656
runtime_io::print(&txid[..]);
5757
}
5858
Ok(()) => (),

xrml/xbridge/bitcoin/src/header_proof.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ use primitives::hash::H256;
99
use primitives::U256;
1010

1111
use super::{
12-
BestIndex, BlockHeaderFor, BlockHeightFor, GenesisInfo, NetworkId, Params, ParamsInfo, Trait,
12+
BestIndex, BlockHeaderFor, BlockHeightFor, GenesisInfo, IrrBlock, NetworkId, Params,
13+
ParamsInfo, Trait,
1314
};
1415
use blockchain::ChainErr;
1516
use runtime_primitives::traits::As;
@@ -44,8 +45,9 @@ impl<'a> HeaderVerifier<'a> {
4445
return Err(ChainErr::NotFound);
4546
}
4647

48+
let irr_block = <IrrBlock<T>>::get();
4749
let this_height = prev_height + 1;
48-
if this_height < best_height - params.max_fork_route_preset {
50+
if this_height < best_height - irr_block {
4951
return Err(ChainErr::AncientFork);
5052
}
5153

xrml/xbridge/bitcoin/src/lib.rs

Lines changed: 17 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ use rstd::result::Result as StdResult;
7676
use runtime_support::dispatch::Result;
7777
use runtime_support::{StorageMap, StorageValue};
7878
use script::script::Script;
79-
use ser::deserialize;
79+
use ser::{deserialize, Reader};
8080
use system::ensure_signed;
8181
pub use tx::RelayTx;
8282
use tx::{
@@ -175,7 +175,6 @@ pub struct Params {
175175
max_bits: u32,
176176
//Compact
177177
block_max_future: u32,
178-
max_fork_route_preset: u32,
179178

180179
target_timespan_seconds: u32,
181180
target_spacing_seconds: u32,
@@ -192,15 +191,13 @@ impl Params {
192191
pub fn new(
193192
max_bits: u32,
194193
block_max_future: u32,
195-
max_fork_route_preset: u32,
196194
target_timespan_seconds: u32,
197195
target_spacing_seconds: u32,
198196
retargeting_factor: u32,
199197
) -> Params {
200198
Params {
201199
max_bits,
202200
block_max_future,
203-
max_fork_route_preset,
204201

205202
target_timespan_seconds,
206203
target_spacing_seconds,
@@ -315,7 +312,6 @@ decl_module! {
315312
fn deposit_event<T>() = default;
316313

317314
pub fn push_header(origin, header: Vec<u8>) -> Result {
318-
runtime_io::print("[bridge_btc] Push btc header");
319315
let from = ensure_signed(origin)?;
320316
let header: BlockHeader = deserialize(header.as_slice()).map_err(|_| "Cannot deserialize the header vec")?;
321317
ensure!(
@@ -326,14 +322,12 @@ decl_module! {
326322
<BlockHeaderFor<T>>::exists(&header.previous_header_hash),
327323
"Cannot push if can't find its previous header in ChainX, which may be header of some orphan block."
328324
);
329-
330325
Self::apply_push_header(header, &from)?;
331326

332327
Ok(())
333328
}
334329

335330
pub fn push_transaction(origin, tx: Vec<u8>) -> Result {
336-
runtime_io::print("[bridge_btc] Push btc tx");
337331
ensure_signed(origin)?;
338332
let tx: RelayTx = Decode::decode(&mut tx.as_slice()).ok_or("Parse RelayTx err")?;
339333
let trustee_address = <xaccounts::TrusteeAddress<T>>::get(xassets::Chain::Bitcoin).ok_or("Should set trustee address first.")?;
@@ -348,7 +342,7 @@ decl_module! {
348342
let from = ensure_signed(origin)?;
349343
// commiter must in trustee node list
350344
Self::ensure_trustee_node(&from)?;
351-
let tx: BTCTransaction = Decode::decode(&mut tx.as_slice()).ok_or("Parse transaction err")?;
345+
let tx: BTCTransaction = deserialize(Reader::new(tx.as_slice())).map_err(|_|"Parse transaction err")?;
352346
Self::apply_create_withdraw(tx, withdraw_id)?;
353347

354348
Ok(())
@@ -475,9 +469,9 @@ impl<T: Trait> Module<T> {
475469
<BlockHeightFor<T>>::remove(&del);
476470

477471
// update confirmd status
478-
let params: Params = <ParamsInfo<T>>::get();
472+
let irr_block = <IrrBlock<T>>::get();
479473
let mut confirm_header = header_info.clone();
480-
for _index in 0..params.max_fork_route_preset {
474+
for _index in 0..irr_block {
481475
if let Some(info) =
482476
<BlockHeaderFor<T>>::get(&confirm_header.header.previous_header_hash)
483477
{
@@ -526,7 +520,7 @@ impl<T: Trait> Module<T> {
526520
let outpoint = tx.raw.inputs[0].previous_output.clone();
527521
match inspect_address::<T>(&tx.previous_raw, outpoint) {
528522
Some(a) => a,
529-
None => return Err("inspect address failed"),
523+
None => return Err("Inspect address failed"),
530524
}
531525
}
532526
};
@@ -549,7 +543,7 @@ impl<T: Trait> Module<T> {
549543

550544
if confirmed {
551545
handle_tx::<T>(&tx.raw.hash()).map_err(|e| {
552-
runtime_io::print("handle_tx error :");
546+
runtime_io::print("[bridge_btc] Handle tx error:");
553547
runtime_io::print(tx.raw.hash().to_vec().as_slice());
554548
e
555549
})?;
@@ -567,7 +561,10 @@ impl<T: Trait> Module<T> {
567561
.ok_or("Should set trustee address first.")?;
568562
let hot_address = Address::from_layout(&trustee_address.hot_address.as_slice())
569563
.map_err(|_| "Invalid Address")?;
570-
check_withdraw_tx::<T>(tx, withdraw_id, hot_address)?;
564+
check_withdraw_tx::<T>(tx.clone(), withdraw_id.clone(), hot_address.clone())?;
565+
let candidate = CandidateTx::new(withdraw_id, tx, VoteResult::Unfinish, Vec::new());
566+
<TxProposal<T>>::put(candidate);
567+
runtime_io::print("[bridge-btc] Through the legality check of withdrawal transaction ");
571568
Ok(())
572569
}
573570

@@ -586,28 +583,30 @@ impl<T: Trait> Module<T> {
586583
let reject_count: Vec<&(T::AccountId, bool)> =
587584
sig_node.iter().filter(|(_, vote)| *vote == false).collect();
588585
data.sig_node.push((who, vote_state));
589-
runtime_io::print("Veto signature");
586+
runtime_io::print("[bridge_btc] Veto signature");
590587
if reject_count.len() + 1 >= sign_num {
591-
runtime_io::print("Clear TxProposal");
588+
runtime_io::print("[bridge_btc] Clear TxProposal");
592589
<TxProposal<T>>::kill();
593590
return Ok(());
594591
}
595592
let candidate =
596593
CandidateTx::new(data.withdraw_id, data.tx, data.sig_status, data.sig_node);
597594
<TxProposal<T>>::put(candidate);
598595
} else {
599-
let tx: BTCTransaction = Decode::decode(&mut tx.as_slice()).ok_or("Parse transaction err")?;
596+
let tx: BTCTransaction = deserialize(Reader::new(tx.as_slice())).map_err(|_|"Parse transaction err")?;
600597
let script: Script = tx.inputs[0].script_sig.clone().into();
601598
let (sigs, _dem) = if let Ok((sigs, dem)) = script.extract_multi_scriptsig() {
602599
(sigs, dem)
603600
} else {
604601
return Err("No signature");
605602
};
606-
runtime_io::print("Signature pass");
603+
runtime_io::print("[bridge_btc] Signature pass");
607604
data.sig_node.push((who, vote_state));
608605
if sigs.len() >= sign_num {
609-
runtime_io::print("Signature finsh 2n/3");
606+
runtime_io::print("[bridge_btc] Signature finish");
610607
data.sig_status = VoteResult::Finish;
608+
} else {
609+
data.sig_status = VoteResult::Unfinish;
611610
}
612611

613612
let candidate =

xrml/xbridge/bitcoin/src/tests.rs

Lines changed: 5 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,7 @@ extern crate rustc_hex;
66
extern crate serialization;
77
extern crate sr_primitives;
88
extern crate srml_consensus as consensus;
9-
use self::base58::FromBase58;
10-
use self::hex::FromHex;
11-
//use self::rustc_hex::FromHex;
129
use self::keys::DisplayLayout;
13-
use self::rustc_hex::ToHex;
1410
use self::serialization::Reader;
1511
use super::*;
1612
use chain::Transaction;
@@ -22,10 +18,7 @@ use runtime_primitives::traits::{BlakeTwo256, IdentityLookup};
2218
use runtime_primitives::BuildStorage;
2319
use runtime_support::StorageValue;
2420
use script::builder::Builder;
25-
use script::{
26-
builder, script::Script, Opcode, SignatureChecker, SignatureVersion, TransactionInputSigner,
27-
TransactionSignatureChecker,
28-
};
21+
use script::{script::Script, Opcode};
2922
use substrate_primitives::{Blake2Hasher, H256 as S_H256};
3023

3124
impl_outer_origin! {
@@ -694,15 +687,14 @@ pub fn test_multi_address() {
694687

695688
fn create_multi_address(pubkeys: Vec<Vec<u8>>) -> Address {
696689
let mut build = Builder::default().push_opcode(Opcode::OP_3);
697-
for (i, pubkey) in pubkeys.iter().enumerate() {
690+
for (_, pubkey) in pubkeys.iter().enumerate() {
698691
build = build.push_bytes(pubkey);
699692
}
700693
let script = build
701694
.push_opcode(Opcode::OP_4)
702695
.push_opcode(Opcode::OP_CHECKMULTISIG)
703696
.into_script();
704-
println!("script:{:?}", script.to_bytes().to_vec());
705-
println!("script:{:?}", Script::from(script.to_bytes().to_vec()));
697+
//println!("script:{:?}", script.to_bytes().to_vec());
706698
let multisig_address = Address {
707699
kind: keys::Type::P2SH,
708700
network: keys::Network::Testnet,
@@ -746,10 +738,8 @@ fn test_create_multi_address() {
746738
cold_keys.push(pubkey7_bytes);
747739
cold_keys.push(pubkey8_bytes);
748740

749-
let hot_addr = create_multi_address(hot_keys);
741+
let _hot_addr = create_multi_address(hot_keys);
750742
let cold_addr = create_multi_address(cold_keys);
751-
println!("hot_addr:{:?}", hot_addr.to_string());
752-
println!("cold_addr:{:?}", cold_addr.to_string());
753743

754744
let layout_addr = cold_addr.layout().to_vec();
755745
let layout = [
@@ -804,7 +794,7 @@ fn test_accountid() {
804794
#[test]
805795
fn test_sign_withdraw() {
806796
with_externalities(&mut new_test_ext3(), || {
807-
let tx1 = hex::decode("01000000019d15247f7f75ffd6e9377ea928f476bcaf9ab542563429b97ee2ef89f2c9d4a101000000b5004830450221008c9147795b2ddf923d5dad3c9fcfde6394aa2629b9a10ca8f93a5c6d4293a7490220687aeb3318b35450fda4d45cc54177f3d6f898d15ea1f8705a77c7116cb44fe8014c695221023e505c48a955e759ce61145dc4a9a7447425290b8483f4e36f05169e7967c86d2102e34d10113f2dd162e8d8614a4afbb8e2eb14eddf4036042b35d12cf5529056a2210311252930af8ba766b9c7a6580d8dc4bbf9b0befd17a8ef7fabac275bba77ae4053aeffffffff01e8030000000000001976a914023dbd259dd15fc43da1a758ea7b2bfaec97893488ac00000000").unwrap();
797+
let _tx1 = hex::decode("01000000019d15247f7f75ffd6e9377ea928f476bcaf9ab542563429b97ee2ef89f2c9d4a101000000b5004830450221008c9147795b2ddf923d5dad3c9fcfde6394aa2629b9a10ca8f93a5c6d4293a7490220687aeb3318b35450fda4d45cc54177f3d6f898d15ea1f8705a77c7116cb44fe8014c695221023e505c48a955e759ce61145dc4a9a7447425290b8483f4e36f05169e7967c86d2102e34d10113f2dd162e8d8614a4afbb8e2eb14eddf4036042b35d12cf5529056a2210311252930af8ba766b9c7a6580d8dc4bbf9b0befd17a8ef7fabac275bba77ae4053aeffffffff01e8030000000000001976a914023dbd259dd15fc43da1a758ea7b2bfaec97893488ac00000000").unwrap();
808798
let tx2 = hex::decode("01000000019d15247f7f75ffd6e9377ea928f476bcaf9ab542563429b97ee2ef89f2c9d4a101000000fdfd00004830450221008c9147795b2ddf923d5dad3c9fcfde6394aa2629b9a10ca8f93a5c6d4293a7490220687aeb3318b35450fda4d45cc54177f3d6f898d15ea1f8705a77c7116cb44fe80147304402204b999fbf18b944a3f6446ca56d094d70699a1e44c8636b06fc2267434e9200ae022073327aca6cdad35075c9c8bb2759a24753906ef030ccb513d8a515648ab46d0e014c695221023e505c48a955e759ce61145dc4a9a7447425290b8483f4e36f05169e7967c86d2102e34d10113f2dd162e8d8614a4afbb8e2eb14eddf4036042b35d12cf5529056a2210311252930af8ba766b9c7a6580d8dc4bbf9b0befd17a8ef7fabac275bba77ae4053aeffffffff01e8030000000000001976a914023dbd259dd15fc43da1a758ea7b2bfaec97893488ac00000000").unwrap();
809799
let tx: Transaction = deserialize(Reader::new(&tx2)).unwrap();
810800
XBridgeOfBTC::apply_sign_withdraw(0, tx, true).unwrap();

0 commit comments

Comments
 (0)