diff --git a/c/cobuild.c b/c/cobuild.c index 0c0653a..6fc5055 100644 --- a/c/cobuild.c +++ b/c/cobuild.c @@ -181,7 +181,7 @@ int ckb_check_others_in_group() { break; } CHECK(err); - // mohanson + // tested by test_non_empty_witness CHECK2(witness_len == 0, ERROR_NONEMPTY_WITNESS); } @@ -257,7 +257,11 @@ int ckb_new_witness_cursor(mol2_cursor_t *cursor, uint8_t *data_source, int ckb_hash_cursor(blake2b_state *ctx, mol2_cursor_t cursor) { // one batch to drain whole cache perfectly - // mohanson: cell data, 0, 1, 2048, 2049, 500k + // tested by test_input_cell_data_size_0 + // test_input_cell_data_size_1 + // test_input_cell_data_size_2048 + // test_input_cell_data_size_2049 + // test_input_cell_data_size_500k uint8_t batch[MAX_CACHE_SIZE]; while (true) { uint32_t read_len = mol2_read_at(&cursor, batch, sizeof(batch)); @@ -350,14 +354,15 @@ int ckb_fetch_seal(mol2_cursor_t *seal_cursor) { table SighashAllOnly { seal: Bytes, } + tested by test_sighash_all_only */ mol2_union_t uni = mol2_union_unpack(&cursor); *seal_cursor = mol2_table_slice_by_index(&uni.cursor, 0); } else { // the union id should be SighashAll or SighashAllOnly. otherwise, it fails // and mark it as non cobuild. - // mohanson - printf("error in fetch_seal, id = %d", id); + // tested by test_wrong_union_id + printf("error in fetch_seal, id = %u", id); CHECK2(false, ERROR_SIGHASHALL_NOSEAL); } @@ -377,7 +382,7 @@ int ckb_generate_signing_message_hash(bool has_message, size_t count = 0; // use different hash based on message if (has_message) { - // mohanson + // tested by test_input_cell_data_size_0 new_sighash_all_blake2b(&ctx); ckb_hash_cursor(&ctx, message_cursor); count += message_cursor.size; @@ -453,7 +458,7 @@ int ckb_parse_message(uint8_t *signing_message_hash, mol2_cursor_t *seal) { int err = ERROR_GENERAL; err = ckb_check_others_in_group(); - // mohanson + // tested by test_non_empty_witness CHECK(err); bool has_message = false; mol2_cursor_t message; diff --git a/tests/omni_lock_rust/tests/misc.rs b/tests/omni_lock_rust/tests/misc.rs index 546a757..19f1299 100644 --- a/tests/omni_lock_rust/tests/misc.rs +++ b/tests/omni_lock_rust/tests/misc.rs @@ -43,7 +43,7 @@ use ckb_script::TransactionScriptsVerifier; use ckb_types::core::hardfork::HardForks; use omni_lock_test::omni_lock; use omni_lock_test::omni_lock::OmniLockWitnessLock; -use omni_lock_test::schemas::basic::{Message, SighashAll}; +use omni_lock_test::schemas::basic::{Message, SighashAll, SighashAllOnly}; use omni_lock_test::xudt_rce_mol::{ RCCellVecBuilder, RCDataBuilder, RCDataUnion, RCRuleBuilder, SmtProofBuilder, SmtProofEntryBuilder, SmtProofEntryVec, SmtProofEntryVecBuilder, @@ -81,6 +81,7 @@ pub const ERROR_RCE_EMERGENCY_HALT: i8 = 54; pub const ERROR_RSA_VERIFY_FAILED: i8 = 42; pub const ERROR_INCORRECT_SINCE_VALUE: i8 = -24; pub const ERROR_ISO97962_INVALID_ARG9: i8 = 61; +pub const ERROR_MOL2_ERR_OVERFLOW: i8 = 8; // sudt supply errors pub const ERROR_EXCEED_SUPPLY: i8 = 90; pub const ERROR_SUPPLY_AMOUNT: i8 = 91; @@ -622,7 +623,7 @@ pub fn sign_tx_by_input_group( let mut preimage_hash: Bytes = Default::default(); let message = if config.cobuild_enabled { - cobuild_generate_signing_message_hash(&Some(config.cobuild_message.clone()), dummy, &tx) + cobuild_generate_signing_message_hash(&config.cobuild_message, dummy, &tx) } else { let mut blake2b = ckb_hash::new_blake2b(); let mut message = [0u8; 32]; @@ -751,21 +752,40 @@ pub fn sign_tx_by_input_group( ); if config.cobuild_enabled { - let msg = config.cobuild_message.clone(); - let sighash_all = SighashAll::new_builder() - .message(msg) - .seal(witness_lock.pack()) - .build(); - let sighash_all = WitnessLayout::new_builder().set(sighash_all).build(); - let sighash_all = sighash_all.as_bytes(); - println!( - "sighash_all with enum id(size: {}): {:02x?}", - sighash_all.len(), - sighash_all.as_ref() - ); - let res = sighash_all.pack(); - println!("res(size: {}): {:02x?}", res.len(), res.as_bytes().as_ref()); - res + match &config.cobuild_message { + Some(msg) => { + let sighash_all = SighashAll::new_builder() + .message(msg.clone()) + .seal(witness_lock.pack()) + .build(); + let sighash_all = WitnessLayout::new_builder().set(sighash_all).build(); + let sighash_all = sighash_all.as_bytes(); + println!( + "sighash_all with enum id(size: {}): {:02x?}", + sighash_all.len(), + sighash_all.as_ref() + ); + let res = sighash_all.pack(); + println!("res(size: {}): {:02x?}", res.len(), res.as_bytes().as_ref()); + res + } + None => { + let sighash_all_only = SighashAllOnly::new_builder() + .seal(witness_lock.pack()) + .build(); + let sighash_all_only = + WitnessLayout::new_builder().set(sighash_all_only).build(); + let sighash_all_only = sighash_all_only.as_bytes(); + println!( + "sighash_all_only with enum id(size: {}): {:02x?}", + sighash_all_only.len(), + sighash_all_only.as_ref() + ); + let res = sighash_all_only.pack(); + println!("res(size: {}): {:02x?}", res.len(), res.as_bytes().as_ref()); + res + } + } } else { let witness = WitnessArgs::new_unchecked( tx.witnesses().get(begin_index).unwrap().unpack(), @@ -1493,7 +1513,7 @@ pub struct TestConfig { pub chain_config: Option>, pub cobuild_enabled: bool, - pub cobuild_message: Message, + pub cobuild_message: Option, pub custom_extension_witnesses: Option>, } @@ -1594,7 +1614,7 @@ impl TestConfig { chain_config: None, cobuild_enabled: false, - cobuild_message: Message::default(), + cobuild_message: Some(Message::default()), custom_extension_witnesses: None, } } diff --git a/tests/omni_lock_rust/tests/test_omni_lock.rs b/tests/omni_lock_rust/tests/test_omni_lock.rs index 5fd04ee..915de86 100644 --- a/tests/omni_lock_rust/tests/test_omni_lock.rs +++ b/tests/omni_lock_rust/tests/test_omni_lock.rs @@ -677,7 +677,7 @@ fn test_binary_unchanged() { let actual_hash = faster_hex::hex_string(&hash); assert_eq!( - "eb9483b29855bdafcad85595f02644f548e9094c24d544eeb51cd26ee2ecf14a", + "ec16573ca45e4a12c16a440f18435ce47b1ff5f30e7f0c0e8fa5261239b4406c", &actual_hash ); } @@ -726,3 +726,227 @@ fn test_try_union_unpack_id_by_cobuild() { let verify_result = verifier.verify(MAX_CYCLES); verify_result.expect("pass verification"); } + +#[test] +fn test_non_empty_witness() { + let mut data_loader = DummyDataLoader::new(); + + let mut config = TestConfig::new(IDENTITY_FLAGS_BITCOIN, false); + config.cobuild_enabled = true; + config.set_chain_config(Box::new(BitcoinConfig { + sign_vtype: BITCOIN_V_TYPE_P2PKHCOMPRESSED, + pubkey_err: false, + })); + + let lock_args = config.gen_args(); + let tx = gen_tx_with_grouped_args(&mut data_loader, vec![(lock_args, 2)], &mut config); + + let tx = sign_tx(&mut data_loader, tx, &mut config); + let resolved_tx = build_resolved_tx(&data_loader, &tx); + + let mut verifier = verify_tx(resolved_tx, data_loader); + verifier.set_debug_printer(debug_printer); + let verify_result = verifier.verify(MAX_CYCLES); + assert_script_error(verify_result.unwrap_err(), ERROR_MOL2_ERR_OVERFLOW); +} + +#[test] +fn test_input_cell_data_size_0() { + let mut data_loader = DummyDataLoader::new(); + + let mut config = TestConfig::new(IDENTITY_FLAGS_BITCOIN, false); + config.cobuild_enabled = true; + config.set_chain_config(Box::new(BitcoinConfig { + sign_vtype: BITCOIN_V_TYPE_P2PKHCOMPRESSED, + pubkey_err: false, + })); + + let tx = gen_tx(&mut data_loader, &mut config); + let tx = sign_tx(&mut data_loader, tx, &mut config); + let resolved_tx = build_resolved_tx(&data_loader, &tx); + + let mut verifier = verify_tx(resolved_tx, data_loader); + verifier.set_debug_printer(debug_printer); + let verify_result = verifier.verify(MAX_CYCLES); + verify_result.expect("pass verification"); +} + +#[test] +fn test_input_cell_data_size_1() { + let mut data_loader = DummyDataLoader::new(); + + let mut config = TestConfig::new(IDENTITY_FLAGS_BITCOIN, false); + config.cobuild_enabled = true; + config.set_chain_config(Box::new(BitcoinConfig { + sign_vtype: BITCOIN_V_TYPE_P2PKHCOMPRESSED, + pubkey_err: false, + })); + + let tx = gen_tx(&mut data_loader, &mut config); + let inputs_len = tx.inputs().len(); + for i in 0..inputs_len { + let input_cell = tx.inputs().get(i).unwrap(); + let input_cell_out_point = input_cell.previous_output(); + let (input_cell_output, _) = data_loader.cells.get(&input_cell_out_point).unwrap(); + data_loader.cells.insert( + input_cell_out_point, + (input_cell_output.clone(), Bytes::from(vec![0x42; 1])), + ); + } + let tx = sign_tx(&mut data_loader, tx, &mut config); + let resolved_tx = build_resolved_tx(&data_loader, &tx); + + let mut verifier = verify_tx(resolved_tx, data_loader); + verifier.set_debug_printer(debug_printer); + let verify_result = verifier.verify(MAX_CYCLES); + verify_result.expect("pass verification"); +} + +#[test] +fn test_input_cell_data_size_2048() { + let mut data_loader = DummyDataLoader::new(); + + let mut config = TestConfig::new(IDENTITY_FLAGS_BITCOIN, false); + config.cobuild_enabled = true; + config.set_chain_config(Box::new(BitcoinConfig { + sign_vtype: BITCOIN_V_TYPE_P2PKHCOMPRESSED, + pubkey_err: false, + })); + + let tx = gen_tx(&mut data_loader, &mut config); + let inputs_len = tx.inputs().len(); + for i in 0..inputs_len { + let input_cell = tx.inputs().get(i).unwrap(); + let input_cell_out_point = input_cell.previous_output(); + let (input_cell_output, _) = data_loader.cells.get(&input_cell_out_point).unwrap(); + data_loader.cells.insert( + input_cell_out_point, + (input_cell_output.clone(), Bytes::from(vec![0x42; 2048])), + ); + } + let tx = sign_tx(&mut data_loader, tx, &mut config); + let resolved_tx = build_resolved_tx(&data_loader, &tx); + + let mut verifier = verify_tx(resolved_tx, data_loader); + verifier.set_debug_printer(debug_printer); + let verify_result = verifier.verify(MAX_CYCLES); + verify_result.expect("pass verification"); +} + +#[test] +fn test_input_cell_data_size_2049() { + let mut data_loader = DummyDataLoader::new(); + + let mut config = TestConfig::new(IDENTITY_FLAGS_BITCOIN, false); + config.cobuild_enabled = true; + config.set_chain_config(Box::new(BitcoinConfig { + sign_vtype: BITCOIN_V_TYPE_P2PKHCOMPRESSED, + pubkey_err: false, + })); + + let tx = gen_tx(&mut data_loader, &mut config); + let inputs_len = tx.inputs().len(); + for i in 0..inputs_len { + let input_cell = tx.inputs().get(i).unwrap(); + let input_cell_out_point = input_cell.previous_output(); + let (input_cell_output, _) = data_loader.cells.get(&input_cell_out_point).unwrap(); + data_loader.cells.insert( + input_cell_out_point, + (input_cell_output.clone(), Bytes::from(vec![0x42; 2049])), + ); + } + let tx = sign_tx(&mut data_loader, tx, &mut config); + let resolved_tx = build_resolved_tx(&data_loader, &tx); + + let mut verifier = verify_tx(resolved_tx, data_loader); + verifier.set_debug_printer(debug_printer); + let verify_result = verifier.verify(MAX_CYCLES); + verify_result.expect("pass verification"); +} + +#[test] +fn test_input_cell_data_size_500k() { + let mut data_loader = DummyDataLoader::new(); + + let mut config = TestConfig::new(IDENTITY_FLAGS_BITCOIN, false); + config.cobuild_enabled = true; + config.set_chain_config(Box::new(BitcoinConfig { + sign_vtype: BITCOIN_V_TYPE_P2PKHCOMPRESSED, + pubkey_err: false, + })); + + let tx = gen_tx(&mut data_loader, &mut config); + let inputs_len = tx.inputs().len(); + for i in 0..inputs_len { + let input_cell = tx.inputs().get(i).unwrap(); + let input_cell_out_point = input_cell.previous_output(); + let (input_cell_output, _) = data_loader.cells.get(&input_cell_out_point).unwrap(); + data_loader.cells.insert( + input_cell_out_point, + ( + input_cell_output.clone(), + Bytes::from(vec![0x42; 500 * 1024]), + ), + ); + } + let tx = sign_tx(&mut data_loader, tx, &mut config); + let resolved_tx = build_resolved_tx(&data_loader, &tx); + + let mut verifier = verify_tx(resolved_tx, data_loader); + verifier.set_debug_printer(debug_printer); + let verify_result = verifier.verify(MAX_CYCLES); + verify_result.expect("pass verification"); +} + +#[test] +fn test_wrong_union_id() { + let mut data_loader = DummyDataLoader::new(); + + let mut config = TestConfig::new(IDENTITY_FLAGS_BITCOIN, false); + config.cobuild_enabled = true; + config.set_chain_config(Box::new(BitcoinConfig { + sign_vtype: BITCOIN_V_TYPE_P2PKHCOMPRESSED, + pubkey_err: false, + })); + + let tx = gen_tx(&mut data_loader, &mut config); + let tx = sign_tx(&mut data_loader, tx, &mut config); + + let witness = tx.witnesses().get(0).unwrap(); + let mut witness_builder = witness.as_builder(); + witness_builder.replace(0, 0x03.into()); + let witness = witness_builder.build(); + let tx = tx + .as_advanced_builder() + .set_witnesses(vec![witness]) + .build(); + + let resolved_tx = build_resolved_tx(&data_loader, &tx); + + let mut verifier = verify_tx(resolved_tx, data_loader); + verifier.set_debug_printer(debug_printer); + let verify_result = verifier.verify(MAX_CYCLES); + assert_script_error(verify_result.unwrap_err(), ERROR_MOL2_ERR_OVERFLOW); +} + +#[test] +fn test_sighash_all_only() { + let mut data_loader = DummyDataLoader::new(); + + let mut config = TestConfig::new(IDENTITY_FLAGS_BITCOIN, false); + config.cobuild_enabled = true; + config.cobuild_message = None; + config.set_chain_config(Box::new(BitcoinConfig { + sign_vtype: BITCOIN_V_TYPE_P2PKHCOMPRESSED, + pubkey_err: false, + })); + + let tx = gen_tx(&mut data_loader, &mut config); + let tx = sign_tx(&mut data_loader, tx, &mut config); + let resolved_tx = build_resolved_tx(&data_loader, &tx); + + let mut verifier = verify_tx(resolved_tx, data_loader); + verifier.set_debug_printer(debug_printer); + let verify_result = verifier.verify(MAX_CYCLES); + verify_result.expect("pass verification"); +}