Skip to content

Commit 5eda454

Browse files
author
Liu Chuankai
committed
fix: 🐛 Handle opentx scriptgroup for merge
1 parent 1b3e96f commit 5eda454

File tree

2 files changed

+44
-5
lines changed

2 files changed

+44
-5
lines changed

src/unlock/opentx/assembler.rs

+38-5
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
use anyhow::anyhow;
2-
32
use std::{cmp::Ordering, collections::HashSet, convert::TryFrom};
43

54
use ckb_types::{
@@ -9,11 +8,27 @@ use ckb_types::{
98
prelude::*,
109
};
1110

12-
use crate::types::omni_lock::OmniLockWitnessLock;
1311
use crate::{traits::TransactionDependencyProvider, unlock::omni_lock::OmniLockFlags};
12+
use crate::{
13+
tx_builder::{gen_script_groups, ScriptGroups},
14+
types::omni_lock::OmniLockWitnessLock,
15+
};
1416

1517
use super::OpenTxError;
1618

19+
/// Check if different
20+
fn check_script_groups(group_vec: &[ScriptGroups]) -> Result<(), OpenTxError> {
21+
let mut keys = HashSet::new();
22+
for group in group_vec.iter() {
23+
let len = keys.len();
24+
keys.extend(group.lock_groups.keys().clone());
25+
if len + group.lock_groups.len() > keys.len() {
26+
return Err(OpenTxError::SameLockInDifferentOpenTx);
27+
}
28+
}
29+
Ok(())
30+
}
31+
1732
/// Assemble a transaction from multiple opentransaction, remove duplicate cell deps and header deps.
1833
/// Alter base input/output index.
1934
pub fn assemble_new_tx(
@@ -29,21 +44,33 @@ pub fn assemble_new_tx(
2944
let mut header_deps = HashSet::new();
3045
let mut base_input_idx = 0usize;
3146
let mut base_output_idx = 0usize;
47+
let mut base_input_cap = 0usize;
48+
let mut base_output_cap = 0usize;
49+
let group_vec: Result<Vec<_>, _> = transactions
50+
.iter()
51+
.map(|tx| gen_script_groups(tx, provider))
52+
.collect();
53+
let group_vec = group_vec?;
54+
check_script_groups(&group_vec)?;
3255
for tx in transactions.iter() {
3356
cell_deps.extend(tx.cell_deps());
3457
header_deps.extend(tx.header_deps());
3558
builder = builder.inputs(tx.inputs());
59+
base_input_cap += tx.inputs().len();
60+
base_output_cap += tx.outputs().len();
3661
// Handle opentx witness
3762
for (input, witness) in tx.inputs().into_iter().zip(tx.witnesses().into_iter()) {
3863
let lock = provider.get_cell(&input.previous_output())?.lock();
3964
let code_hash = lock.code_hash();
40-
if code_hash.cmp(&opentx_code_hash) == Ordering::Equal {
65+
// empty witness should be in a script group
66+
if !witness.is_empty() && code_hash.cmp(&opentx_code_hash) == Ordering::Equal {
4167
let args = &lock.args().raw_data();
42-
if args.len() >= 22
68+
let witness_data = witness.raw_data();
69+
if witness_data.len() > 8 // sizeof base_input + sizeof base_output
70+
&& args.len() >= 22
4371
&& OmniLockFlags::from_bits_truncate(args[21]).contains(OmniLockFlags::OPENTX)
4472
{
4573
// Parse lock data
46-
let witness_data = witness.raw_data();
4774
let current_witness: WitnessArgs =
4875
WitnessArgs::from_slice(witness_data.as_ref())?;
4976
let lock_field = current_witness
@@ -64,11 +91,17 @@ pub fn assemble_new_tx(
6491
tmp.copy_from_slice(&data[0..4]);
6592
let this_base_input_idx = u32::from_le_bytes(tmp)
6693
+ u32::try_from(base_input_idx).map_err(|e| anyhow!(e))?;
94+
if this_base_input_idx as usize > base_input_cap {
95+
return Err(OpenTxError::BaseInputIndexOverFlow);
96+
}
6797
data[0..4].copy_from_slice(&this_base_input_idx.to_le_bytes());
6898

6999
tmp.copy_from_slice(&data[4..8]);
70100
let this_base_output_idx = u32::from_le_bytes(tmp)
71101
+ u32::try_from(base_output_idx).map_err(|e| anyhow!(e))?;
102+
if this_base_output_idx as usize > base_output_cap {
103+
return Err(OpenTxError::BaseOutputIndexOverFlow);
104+
}
72105
data[4..8].copy_from_slice(&this_base_output_idx.to_le_bytes());
73106

74107
let omnilock_witnesslock = omnilock_witnesslock

src/unlock/opentx/mod.rs

+6
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,12 @@ pub enum OpenTxError {
3636
WitnessLockMissing,
3737
#[error("signature not exist")]
3838
SignatureMissing,
39+
#[error("Cells in different partital open transaction can not be merged")]
40+
SameLockInDifferentOpenTx,
41+
#[error("Base input index is overflow")]
42+
BaseInputIndexOverFlow,
43+
#[error("Base output index is overflow")]
44+
BaseOutputIndexOverFlow,
3945
#[error(transparent)]
4046
Other(#[from] anyhow::Error),
4147
}

0 commit comments

Comments
 (0)