Skip to content

Commit 962eab8

Browse files
committed
feat: add logging for channel auto-accept failures
This helps operators understand why channels aren't being auto-accepted, making debugging easier when channel opening fails. The logging covers both sender and receiver perspectives, including warnings when funding amounts are insufficient or UDT types don't match auto-accept requirements.
1 parent 9bff40e commit 962eab8

File tree

5 files changed

+481
-19
lines changed

5 files changed

+481
-19
lines changed

crates/fiber-lib/src/ckb/config.rs

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use crate::Result;
55
use ckb_jsonrpc_types::{OutPoint as OutPointWrapper, Script as ScriptWrapper};
66
use ckb_sdk::{traits::DefaultCellCollector, CkbRpcAsyncClient};
77
use ckb_types::core::ScriptHashType;
8-
use ckb_types::prelude::Builder;
8+
use ckb_types::prelude::{Builder, Pack};
99
use ckb_types::H256;
1010
use ckb_types::{
1111
core::DepType,
@@ -270,6 +270,27 @@ pub struct UdtArgInfo {
270270
#[derive(Serialize, Deserialize, Clone, Debug, Default, Eq, PartialEq, Hash)]
271271
pub struct UdtCfgInfos(pub Vec<UdtArgInfo>);
272272

273+
impl UdtCfgInfos {
274+
/// Find a matching UDT info by script (code_hash, hash_type, and args pattern)
275+
pub fn find_matching_udt(&self, udt_script: &Script) -> Option<&UdtArgInfo> {
276+
use regex::Regex;
277+
for udt in &self.0 {
278+
if let Ok(hash_type) = udt_script.hash_type().try_into() {
279+
if udt.script.code_hash.pack() == udt_script.code_hash()
280+
&& udt.script.hash_type == hash_type
281+
{
282+
let args = format!("0x{:x}", udt_script.args().raw_data());
283+
let pattern = Regex::new(&udt.script.args).expect("invalid expression");
284+
if pattern.is_match(&args) {
285+
return Some(udt);
286+
}
287+
}
288+
}
289+
}
290+
None
291+
}
292+
}
293+
273294
impl FromStr for UdtCfgInfos {
274295
type Err = serde_json::Error;
275296

crates/fiber-lib/src/ckb/contracts.rs

Lines changed: 2 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ use ckb_types::{
55
prelude::{Builder, Entity, Pack, PackVec},
66
};
77
use once_cell::sync::OnceCell;
8-
use regex::Regex;
98
use serde::{Deserialize, Serialize};
109
use std::{collections::HashMap, vec};
1110
use thiserror::Error;
@@ -377,20 +376,7 @@ impl ContractsContext {
377376
}
378377

379378
pub(crate) fn get_udt_info(&self, udt_script: &Script) -> Option<&UdtArgInfo> {
380-
for udt in &self.get_udt_whitelist().0 {
381-
if let Ok(_type) = udt_script.hash_type().try_into() {
382-
if udt.script.code_hash.pack() == udt_script.code_hash()
383-
&& udt.script.hash_type == _type
384-
{
385-
let args = format!("0x{:x}", udt_script.args().raw_data());
386-
let pattern = Regex::new(&udt.script.args).expect("invalid expression");
387-
if pattern.is_match(&args) {
388-
return Some(udt);
389-
}
390-
}
391-
}
392-
}
393-
None
379+
self.get_udt_whitelist().find_matching_udt(udt_script)
394380
}
395381
}
396382

@@ -445,7 +431,7 @@ pub fn get_cell_deps_count_by_contracts(contracts: Vec<Contract>) -> usize {
445431
get_contracts_context().get_cell_deps_count(contracts)
446432
}
447433

448-
fn get_udt_info(script: &Script) -> Option<UdtArgInfo> {
434+
pub fn get_udt_info(script: &Script) -> Option<UdtArgInfo> {
449435
get_contracts_context().get_udt_info(script).cloned()
450436
}
451437

crates/fiber-lib/src/ckb/tests/config.rs

Lines changed: 193 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@ use crate::ckb::config::{UdtArgInfo, UdtCellDep, UdtCfgInfos, UdtDep, UdtScript}
22
use crate::fiber::gen::fiber::UdtCfgInfos as MoleculeUdtCfgInfos;
33
use ckb_jsonrpc_types::OutPoint;
44
use ckb_types::core::{DepType, ScriptHashType};
5+
use ckb_types::packed::Script;
6+
use ckb_types::prelude::{Builder, Pack};
57
use ckb_types::H256;
8+
use hex;
69
use molecule::prelude::Entity;
710

811
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
@@ -30,3 +33,193 @@ fn test_udt_whitelist() {
3033
UdtCfgInfos::from(MoleculeUdtCfgInfos::from_slice(&serialized).expect("invalid mol"));
3134
assert_eq!(udt_whitelist, deserialized);
3235
}
36+
37+
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
38+
#[cfg_attr(not(target_arch = "wasm32"), test)]
39+
fn test_find_matching_udt_exact_match() {
40+
let code_hash = H256::from([1u8; 32]);
41+
let args = "0x1234".to_string();
42+
let udt_whitelist = UdtCfgInfos(vec![UdtArgInfo {
43+
name: "TestUDT".to_string(),
44+
script: UdtScript {
45+
code_hash: code_hash.clone(),
46+
hash_type: ScriptHashType::Data,
47+
args: args.clone(),
48+
},
49+
auto_accept_amount: Some(100),
50+
cell_deps: vec![],
51+
}]);
52+
53+
let args_bytes = hex::decode(&args[2..]).unwrap();
54+
let script = Script::new_builder()
55+
.code_hash(code_hash.pack())
56+
.hash_type(ScriptHashType::Data.into())
57+
.args(args_bytes.pack())
58+
.build();
59+
60+
let found = udt_whitelist.find_matching_udt(&script);
61+
assert!(found.is_some());
62+
assert_eq!(found.unwrap().name, "TestUDT");
63+
}
64+
65+
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
66+
#[cfg_attr(not(target_arch = "wasm32"), test)]
67+
fn test_find_matching_udt_regex_pattern() {
68+
let code_hash = H256::from([2u8; 32]);
69+
let udt_whitelist = UdtCfgInfos(vec![UdtArgInfo {
70+
name: "RegexUDT".to_string(),
71+
script: UdtScript {
72+
code_hash: code_hash.clone(),
73+
hash_type: ScriptHashType::Data,
74+
args: "0x[0-9a-f]{4}".to_string(), // Regex pattern matching 4 hex digits
75+
},
76+
auto_accept_amount: Some(200),
77+
cell_deps: vec![],
78+
}]);
79+
80+
// Test with matching args
81+
let args_bytes = hex::decode("abcd").unwrap();
82+
let script = Script::new_builder()
83+
.code_hash(code_hash.pack())
84+
.hash_type(ScriptHashType::Data.into())
85+
.args(args_bytes.pack())
86+
.build();
87+
88+
let found = udt_whitelist.find_matching_udt(&script);
89+
assert!(found.is_some());
90+
assert_eq!(found.unwrap().name, "RegexUDT");
91+
92+
// Test with non-matching args
93+
let args_bytes_no_match = hex::decode("ab").unwrap(); // Only 2 hex digits (1 byte), doesn't match pattern
94+
let script_no_match = Script::new_builder()
95+
.code_hash(code_hash.pack())
96+
.hash_type(ScriptHashType::Data.into())
97+
.args(args_bytes_no_match.pack())
98+
.build();
99+
100+
let found = udt_whitelist.find_matching_udt(&script_no_match);
101+
assert!(found.is_none());
102+
}
103+
104+
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
105+
#[cfg_attr(not(target_arch = "wasm32"), test)]
106+
fn test_find_matching_udt_wrong_code_hash() {
107+
let code_hash1 = H256::from([3u8; 32]);
108+
let code_hash2 = H256::from([4u8; 32]);
109+
let udt_whitelist = UdtCfgInfos(vec![UdtArgInfo {
110+
name: "TestUDT".to_string(),
111+
script: UdtScript {
112+
code_hash: code_hash1.clone(),
113+
hash_type: ScriptHashType::Data,
114+
args: "0x00".to_string(),
115+
},
116+
auto_accept_amount: Some(100),
117+
cell_deps: vec![],
118+
}]);
119+
120+
let args_bytes = hex::decode("00").unwrap();
121+
let script = Script::new_builder()
122+
.code_hash(code_hash2.pack()) // Different code_hash
123+
.hash_type(ScriptHashType::Data.into())
124+
.args(args_bytes.pack())
125+
.build();
126+
127+
let found = udt_whitelist.find_matching_udt(&script);
128+
assert!(found.is_none());
129+
}
130+
131+
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
132+
#[cfg_attr(not(target_arch = "wasm32"), test)]
133+
fn test_find_matching_udt_wrong_hash_type() {
134+
let code_hash = H256::from([5u8; 32]);
135+
let udt_whitelist = UdtCfgInfos(vec![UdtArgInfo {
136+
name: "TestUDT".to_string(),
137+
script: UdtScript {
138+
code_hash: code_hash.clone(),
139+
hash_type: ScriptHashType::Data,
140+
args: "0x00".to_string(),
141+
},
142+
auto_accept_amount: Some(100),
143+
cell_deps: vec![],
144+
}]);
145+
146+
let args_bytes = hex::decode("00").unwrap();
147+
let script = Script::new_builder()
148+
.code_hash(code_hash.pack())
149+
.hash_type(ScriptHashType::Type.into()) // Different hash_type
150+
.args(args_bytes.pack())
151+
.build();
152+
153+
let found = udt_whitelist.find_matching_udt(&script);
154+
assert!(found.is_none());
155+
}
156+
157+
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
158+
#[cfg_attr(not(target_arch = "wasm32"), test)]
159+
fn test_find_matching_udt_multiple_udts() {
160+
let code_hash1 = H256::from([6u8; 32]);
161+
let code_hash2 = H256::from([7u8; 32]);
162+
let udt_whitelist = UdtCfgInfos(vec![
163+
UdtArgInfo {
164+
name: "FirstUDT".to_string(),
165+
script: UdtScript {
166+
code_hash: code_hash1.clone(),
167+
hash_type: ScriptHashType::Data,
168+
args: "0x00".to_string(),
169+
},
170+
auto_accept_amount: Some(100),
171+
cell_deps: vec![],
172+
},
173+
UdtArgInfo {
174+
name: "SecondUDT".to_string(),
175+
script: UdtScript {
176+
code_hash: code_hash2.clone(),
177+
hash_type: ScriptHashType::Data,
178+
args: "0x01".to_string(),
179+
},
180+
auto_accept_amount: Some(200),
181+
cell_deps: vec![],
182+
},
183+
]);
184+
185+
// Test finding first UDT
186+
let args_bytes1 = hex::decode("00").unwrap();
187+
let script1 = Script::new_builder()
188+
.code_hash(code_hash1.pack())
189+
.hash_type(ScriptHashType::Data.into())
190+
.args(args_bytes1.pack())
191+
.build();
192+
193+
let found = udt_whitelist.find_matching_udt(&script1);
194+
assert!(found.is_some());
195+
assert_eq!(found.unwrap().name, "FirstUDT");
196+
197+
// Test finding second UDT
198+
let args_bytes2 = hex::decode("01").unwrap();
199+
let script2 = Script::new_builder()
200+
.code_hash(code_hash2.pack())
201+
.hash_type(ScriptHashType::Data.into())
202+
.args(args_bytes2.pack())
203+
.build();
204+
205+
let found = udt_whitelist.find_matching_udt(&script2);
206+
assert!(found.is_some());
207+
assert_eq!(found.unwrap().name, "SecondUDT");
208+
}
209+
210+
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test::wasm_bindgen_test)]
211+
#[cfg_attr(not(target_arch = "wasm32"), test)]
212+
fn test_find_matching_udt_empty_whitelist() {
213+
let udt_whitelist = UdtCfgInfos(vec![]);
214+
let code_hash = H256::from([8u8; 32]);
215+
216+
let args_bytes = hex::decode("00").unwrap();
217+
let script = Script::new_builder()
218+
.code_hash(code_hash.pack())
219+
.hash_type(ScriptHashType::Data.into())
220+
.args(args_bytes.pack())
221+
.build();
222+
223+
let found = udt_whitelist.find_matching_udt(&script);
224+
assert!(found.is_none());
225+
}

0 commit comments

Comments
 (0)