diff --git a/Cargo.lock b/Cargo.lock index 1deeed1..7662efa 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -394,7 +394,7 @@ dependencies = [ [[package]] name = "ckb-system-scripts" -version = "0.4.0-alpha.14+2-phase-dao" +version = "0.4.0-alpha.17+multisig-since" dependencies = [ "blake2b-rs 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/Cargo.toml b/Cargo.toml index 3cb228b..88d83a6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "ckb-system-scripts" -version = "0.4.0-alpha.14+2-phase-dao" +version = "0.4.0-alpha.17+multisig-since" authors = ["Nervos Core Dev "] edition = "2018" build = "build.rs" diff --git a/build.rs b/build.rs index 14482da..8aac304 100644 --- a/build.rs +++ b/build.rs @@ -27,7 +27,7 @@ const BINARIES: &[(&str, &str)] = &[ ), ( "secp256k1_blake160_multisig_all", - "2a450c65ed903e7064a53f95a660bce48a9c94ca64f395c82d5e86884ee25195", + "109805c7dc63086bdbbd81efb1c95a5ba2c81baf91a5f3e2564c7c23c5e77264", ), ]; diff --git a/c/secp256k1_blake160_multisig_all.c b/c/secp256k1_blake160_multisig_all.c index 24317d0..8f58159 100644 --- a/c/secp256k1_blake160_multisig_all.c +++ b/c/secp256k1_blake160_multisig_all.c @@ -5,6 +5,7 @@ #include "secp256k1_helper.h" /* script args errors */ +#define ERROR_INVALID_RESERVE_FIELD -41 #define ERROR_INVALID_PUBKEYS_CNT -42 #define ERROR_INVALID_THRESHOLD -43 #define ERROR_INVALID_REQUIRE_FIRST_N -44 @@ -22,24 +23,24 @@ #define MAX_WITNESS_SIZE 32768 #define MAX_SCRIPT_SIZE 32768 #define SIGNATURE_SIZE 65 -#define FLAGS_SIZE 12 +#define FLAGS_SIZE 4 /* * Arguments: - * multisig script blake160 hash, 20 bytes. + * 1. multisig script blake160 hash, 20 bytes. + * 2. an optional since constraint, 4 bytes. * * Witness: * multisig_script | Signature1 | signature2 | ... - * multisig_script: S | R | M | N | since | Pubkey1 | Pubkey2 | ... + * multisig_script: S | R | M | N | Pubkey1 | Pubkey2 | ... * * +------------+----------------------------------+-------+ * | | Description | Bytes | * +------------+----------------------------------+-------+ - * | S | reserved for future use | 1 | + * | S | reserved field, must be zero | 1 | * | R | first nth public keys must match | 1 | * | M | threshold | 1 | * | N | total public keys | 1 | - * | since | tx since verify | 8 | * | PubkeyN | compressed pubkey | 33 | * | SignatureN | recoverable signature | 65 | * +------------+----------------------------------+-------+ @@ -68,9 +69,14 @@ int main() { mol_seg_t args_seg = MolReader_Script_get_args(&script_seg); mol_seg_t args_bytes_seg = MolReader_Bytes_raw_bytes(&args_seg); - if (args_bytes_seg.size != BLAKE160_SIZE) { + if (args_bytes_seg.size != BLAKE160_SIZE && + args_bytes_seg.size != BLAKE160_SIZE + sizeof(uint64_t)) { return ERROR_ARGUMENTS_LEN; } + uint64_t since = 0; + if (args_bytes_seg.size == BLAKE160_SIZE + sizeof(uint64_t)) { + since = *(uint64_t *)&args_bytes_seg.ptr[BLAKE160_SIZE]; + } /* Load witness of first input */ unsigned char witness[MAX_WITNESS_SIZE]; @@ -97,7 +103,10 @@ int main() { uint8_t pubkeys_cnt = lock_bytes[3]; uint8_t threshold = lock_bytes[2]; uint8_t require_first_n = lock_bytes[1]; - uint64_t since = *(uint64_t *)&lock_bytes[4]; + uint8_t reserved_field = lock_bytes[0]; + if (reserved_field != 0) { + return ERROR_INVALID_RESERVE_FIELD; + } if (pubkeys_cnt == 0) { return ERROR_INVALID_PUBKEYS_CNT; } diff --git a/src/tests/secp256k1_blake160_multisig_all.rs b/src/tests/secp256k1_blake160_multisig_all.rs index 16d5676..f7bed67 100644 --- a/src/tests/secp256k1_blake160_multisig_all.rs +++ b/src/tests/secp256k1_blake160_multisig_all.rs @@ -28,11 +28,11 @@ const ERROR_INCORRECT_SINCE: i8 = -53; fn test_multisig_script_hash() { let mut data_loader = DummyDataLoader::new(); let keys = generate_keys(3); - let multi_sign_script = gen_multi_sign_script(&keys, 2, 0, 0); + let multi_sign_script = gen_multi_sign_script(&keys, 2, 0); let args = blake160(&multi_sign_script); let raw_tx = gen_tx(&mut data_loader, args); { - let wrong_multi_sign_script = gen_multi_sign_script(&keys, 2, 1, 0); + let wrong_multi_sign_script = gen_multi_sign_script(&keys, 2, 1); let tx = multi_sign_tx( raw_tx.clone(), &wrong_multi_sign_script, @@ -50,11 +50,11 @@ fn test_multisig_script_hash() { fn test_invalid_flags() { let mut data_loader = DummyDataLoader::new(); let keys = generate_keys(3); - let multi_sign_script = gen_multi_sign_script(&keys, 2, 0, 0); + let multi_sign_script = gen_multi_sign_script(&keys, 2, 0); let args = blake160(&multi_sign_script); let raw_tx = gen_tx(&mut data_loader, args); { - let wrong_multi_sign_script = gen_multi_sign_script(&vec![], 2, 0, 0); + let wrong_multi_sign_script = gen_multi_sign_script(&vec![], 2, 0); let tx = multi_sign_tx( raw_tx.clone(), &wrong_multi_sign_script, @@ -67,7 +67,7 @@ fn test_invalid_flags() { ); } { - let wrong_multi_sign_script = gen_multi_sign_script(&keys, 4, 0, 0); + let wrong_multi_sign_script = gen_multi_sign_script(&keys, 4, 0); let tx = multi_sign_tx( raw_tx.clone(), &wrong_multi_sign_script, @@ -80,7 +80,7 @@ fn test_invalid_flags() { ); } { - let wrong_multi_sign_script = gen_multi_sign_script(&keys, 2, 3, 0); + let wrong_multi_sign_script = gen_multi_sign_script(&keys, 2, 3); let tx = multi_sign_tx( raw_tx.clone(), &wrong_multi_sign_script, @@ -98,7 +98,7 @@ fn test_invalid_flags() { fn test_multisig_0_2_3_unlock() { let mut data_loader = DummyDataLoader::new(); let keys = generate_keys(3); - let multi_sign_script = gen_multi_sign_script(&keys, 2, 0, 0); + let multi_sign_script = gen_multi_sign_script(&keys, 2, 0); let args = blake160(&multi_sign_script); let raw_tx = gen_tx(&mut data_loader, args); { @@ -170,7 +170,7 @@ fn test_multisig_0_2_3_unlock() { fn test_multisig_1_2_3_unlock() { let mut data_loader = DummyDataLoader::new(); let keys = generate_keys(3); - let multi_sign_script = gen_multi_sign_script(&keys, 2, 1, 0); + let multi_sign_script = gen_multi_sign_script(&keys, 2, 1); let args = blake160(&multi_sign_script); let tx = gen_tx(&mut data_loader, args); { @@ -199,7 +199,7 @@ fn test_multisig_1_2_3_unlock() { fn test_multisig_1_2_3_with_extra_witness_unlock() { let mut data_loader = DummyDataLoader::new(); let keys = generate_keys(3); - let multi_sign_script = gen_multi_sign_script(&keys, 2, 1, 0); + let multi_sign_script = gen_multi_sign_script(&keys, 2, 1); let args = blake160(&multi_sign_script); let tx = gen_tx(&mut data_loader, args); let extract_witness = vec![1, 2, 3, 4]; @@ -237,10 +237,9 @@ fn test_multisig_1_2_3_with_extra_witness_unlock() { fn test_multisig_1_2_3_with_multiple_inputs_unlock() { let mut data_loader = DummyDataLoader::new(); let keys = generate_keys(3); - let multi_sign_script = gen_multi_sign_script(&keys, 2, 1, 0); + let multi_sign_script = gen_multi_sign_script(&keys, 2, 1); let args = blake160(&multi_sign_script); let tx = gen_tx_with_extra_inputs(&mut data_loader, args, 1); - dbg!(format!("{}", &tx)); { let tx = multi_sign_tx(tx.clone(), &multi_sign_script, &[&keys[0], &keys[1]]); verify(&data_loader, &tx).expect("pass verification"); @@ -267,7 +266,7 @@ fn test_multisig_1_2_3_with_multiple_inputs_unlock() { fn test_multisig_0_1_1_unlock() { let mut data_loader = DummyDataLoader::new(); let keys = generate_keys(1); - let multi_sign_script = gen_multi_sign_script(&keys, 1, 0, 0); + let multi_sign_script = gen_multi_sign_script(&keys, 1, 0); let args = blake160(&multi_sign_script); let raw_tx = gen_tx(&mut data_loader, args); { @@ -289,7 +288,7 @@ fn test_multisig_0_1_1_unlock() { fn test_multisig_0_2_2_unlock() { let mut data_loader = DummyDataLoader::new(); let keys = generate_keys(2); - let multi_sign_script = gen_multi_sign_script(&keys, 2, 0, 0); + let multi_sign_script = gen_multi_sign_script(&keys, 2, 0); let args = blake160(&multi_sign_script); let raw_tx = gen_tx(&mut data_loader, args); { @@ -378,22 +377,16 @@ fn test_multisig_0_2_3_unlock_with_since() { let mut data_loader = DummyDataLoader::new(); let keys = generate_keys(3); let since = 0x0000_0000_8888_8888u64; - let multi_sign_script = gen_multi_sign_script(&keys, 2, 0, since); - let args = blake160(&multi_sign_script); + let multi_sign_script = gen_multi_sign_script(&keys, 2, 0); + let args = { + let mut buf = blake160(&multi_sign_script).to_vec(); + buf.extend(since.to_le_bytes().into_iter()); + Bytes::from(buf) + }; let raw_tx = gen_tx(&mut data_loader, args); { - let since2 = 0; - let multi_sign_script = gen_multi_sign_script(&keys, 2, 0, since2); let tx = multi_sign_tx(raw_tx.clone(), &multi_sign_script, &[&keys[0], &keys[1]]); let verify_result = verify(&data_loader, &tx); - assert_error_eq!( - verify_result.unwrap_err(), - ScriptError::ValidationFailure(ERROR_MULTSIG_SCRIPT_HASH), - ); - } - { - let tx = multi_sign_tx(raw_tx.clone(), &multi_sign_script, &[&keys[1], &keys[2]]); - let verify_result = verify(&data_loader, &tx); assert_error_eq!( verify_result.unwrap_err(), ScriptError::ValidationFailure(ERROR_INCORRECT_SINCE), @@ -453,18 +446,12 @@ fn test_multisig_0_2_3_unlock_with_since() { } } -fn gen_multi_sign_script( - keys: &[Privkey], - threshold: u8, - require_first_n: u8, - since: u64, -) -> Bytes { +fn gen_multi_sign_script(keys: &[Privkey], threshold: u8, require_first_n: u8) -> Bytes { let pubkeys = keys .iter() .map(|key| key.pubkey().unwrap()) .collect::>(); let mut script = vec![0u8, require_first_n, threshold, pubkeys.len() as u8]; - script.extend(since.to_le_bytes().into_iter()); pubkeys.iter().for_each(|pubkey| { script.extend_from_slice(&pubkey.serialize()); });