From dd9f6a1134e2401fd72dcb7e718ac853b6a4e958 Mon Sep 17 00:00:00 2001 From: joii2020 <87224197+joii2020@users.noreply.github.com> Date: Mon, 8 Jan 2024 13:51:16 +0800 Subject: [PATCH] Add testcase : EOS Tron Bitcoin Dogecoin (#1) * Add testcase : EOS Tron Bitcoin Dogecoin --- build.rs | 2 +- c/ckb_identity.h | 2 +- tests/omni_lock_rust/Cargo.lock | 101 ++++++- tests/omni_lock_rust/Cargo.toml | 3 + tests/omni_lock_rust/tests/misc.rs | 300 ++++++++++++++++++- tests/omni_lock_rust/tests/test_omni_lock.rs | 208 ++++++++++++- 6 files changed, 596 insertions(+), 20 deletions(-) diff --git a/build.rs b/build.rs index a825949..2413c56 100644 --- a/build.rs +++ b/build.rs @@ -39,7 +39,7 @@ const BINARIES: &[(&str, &str)] = &[ ), ( "omni_lock", - "2010378214cc62a9c0c48426b553f73bff80e063b015c9079e93008f3da3e971", + "dea31e1f104cf6a26ee3cbace40f6fa70e2deb556cd12fdc23eae15889d0d37b", ), ]; diff --git a/c/ckb_identity.h b/c/ckb_identity.h index 2eefd3e..e68a992 100644 --- a/c/ckb_identity.h +++ b/c/ckb_identity.h @@ -539,7 +539,7 @@ int convert_btc_message_variant(const uint8_t *msg, size_t msg_len, SHA256_CTX sha256_ctx2; sha256_init(&sha256_ctx2); sha256_update(&sha256_ctx2, new_msg, SHA256_SIZE); - sha256_final(&sha256_ctx, new_msg); + sha256_final(&sha256_ctx2, new_msg); return 0; } diff --git a/tests/omni_lock_rust/Cargo.lock b/tests/omni_lock_rust/Cargo.lock index 96e126b..f9b3c0e 100644 --- a/tests/omni_lock_rust/Cargo.lock +++ b/tests/omni_lock_rust/Cargo.lock @@ -1,5 +1,7 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +version = 3 + [[package]] name = "adler" version = "1.0.2" @@ -12,7 +14,7 @@ version = "0.6.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "81ce3d38065e618af2d7b77e10c5ad9a069859b4be3c2250f674af3840d9c8a5" dependencies = [ - "memchr 2.4.1", + "memchr 2.7.1", ] [[package]] @@ -70,6 +72,15 @@ dependencies = [ "generic-array", ] +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + [[package]] name = "block-padding" version = "0.2.1" @@ -417,9 +428,9 @@ dependencies = [ [[package]] name = "ckb-vm-definitions" -version = "0.20.0-rc5" +version = "0.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "deb44cd2753aaeb2dc8a3df7b293ddfc3cbaaf8232d819650c0fc365cacda34f" +checksum = "45af9be584526f91e1517739802d0ebf82eb8d14853c45128ce930144a171ddd" [[package]] name = "cloudabi" @@ -436,6 +447,15 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" +[[package]] +name = "cpufeatures" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce420fe07aecd3e67c5f910618fe65e94158f6dcc0adf44e00d69ce2bdfe0fd0" +dependencies = [ + "libc", +] + [[package]] name = "crc32fast" version = "1.2.1" @@ -464,6 +484,16 @@ dependencies = [ "lazy_static", ] +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + [[package]] name = "derive_more" version = "0.99.16" @@ -486,6 +516,16 @@ dependencies = [ "generic-array", ] +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer 0.10.4", + "crypto-common", +] + [[package]] name = "eaglesong" version = "0.1.0" @@ -604,6 +644,12 @@ dependencies = [ "winapi", ] +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + [[package]] name = "includedir" version = "0.5.0" @@ -645,9 +691,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.98" +version = "0.2.151" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "320cfe77175da3a483efed4bc0adc1968ca050b098ce4f2f1c13a56626128790" +checksum = "302d7ab3130588088d277783b1e2d2e10c9e9e4a16dd9050e6ec93fb3e7048f4" [[package]] name = "log" @@ -688,9 +734,9 @@ dependencies = [ [[package]] name = "memchr" -version = "2.4.1" +version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" +checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" [[package]] name = "merkle-cbt" @@ -805,9 +851,12 @@ dependencies = [ "ckb-vm", "ckb-vm-debug-utils", "gdb-remote-protocol", + "hex", "lazy_static", "openssl", "rand 0.6.5", + "ripemd", + "sha2", "sha3", "sparse-merkle-tree", ] @@ -1119,7 +1168,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9329abc99e39129fcceabd24cf5d85b4671ef7c29c50e972bc5afe32438ec384" dependencies = [ "aho-corasick", - "memchr 2.4.1", + "memchr 2.7.1", "regex-syntax", "thread_local", "utf8-ranges", @@ -1143,6 +1192,15 @@ dependencies = [ "winapi", ] +[[package]] +name = "ripemd" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd124222d17ad93a644ed9d011a40f4fb64aa54275c08cc216524a9ea82fb09f" +dependencies = [ + "digest 0.10.7", +] + [[package]] name = "rustc_version" version = "0.3.3" @@ -1254,14 +1312,25 @@ dependencies = [ "serde", ] +[[package]] +name = "sha2" +version = "0.10.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" +dependencies = [ + "cfg-if 1.0.0", + "cpufeatures", + "digest 0.10.7", +] + [[package]] name = "sha3" version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f81199417d4e5de3f04b1e871023acea7389672c4135918f05aa9cbf2f2fa809" dependencies = [ - "block-buffer", - "digest", + "block-buffer 0.9.0", + "digest 0.9.0", "keccak", "opaque-debug", ] @@ -1382,9 +1451,9 @@ dependencies = [ [[package]] name = "typenum" -version = "1.13.0" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "879f6906492a7cd215bfa4cf595b600146ccfac0c79bcbd1f3000162af5e8b06" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" [[package]] name = "ucd-trie" @@ -1394,9 +1463,9 @@ checksum = "56dee185309b50d1f11bfedef0fe6d036842e3fb77413abef29f8f8d1c5d4c1c" [[package]] name = "ucd-util" -version = "0.1.8" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c85f514e095d348c279b1e5cd76795082cf15bd59b93207832abe0b1d8fed236" +checksum = "abd2fc5d32b590614af8b0a20d837f32eca055edd0bbead59a9cfe80858be003" [[package]] name = "unicode-xid" @@ -1412,9 +1481,9 @@ checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" [[package]] name = "utf8-ranges" -version = "1.0.4" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4ae116fef2b7fea257ed6440d3cfcff7f190865f170cdad00bb6465bf18ecba" +checksum = "7fcfc827f90e53a02eaef5e535ee14266c1d569214c6aa70133a624d8a3164ba" [[package]] name = "vcpkg" diff --git a/tests/omni_lock_rust/Cargo.toml b/tests/omni_lock_rust/Cargo.toml index 86fe702..b0904a6 100644 --- a/tests/omni_lock_rust/Cargo.toml +++ b/tests/omni_lock_rust/Cargo.toml @@ -30,3 +30,6 @@ sha3 = "0.9.1" ckb-vm-debug-utils = { git = "https://github.com/nervosnetwork/ckb-vm-debug-utils.git", rev = "f72995f" } gdb-remote-protocol = { git = "https://github.com/luser/rust-gdb-remote-protocol", rev = "565ab0c" } ckb-vm = { version = "=0.20.0-rc2", features = ["detect-asm"] } +ripemd = "0.1.3" +sha2 = "0.10.6" +hex = "0.4.3" diff --git a/tests/omni_lock_rust/tests/misc.rs b/tests/omni_lock_rust/tests/misc.rs index 62bcc4c..f2f2b10 100644 --- a/tests/omni_lock_rust/tests/misc.rs +++ b/tests/omni_lock_rust/tests/misc.rs @@ -4,6 +4,7 @@ use openssl::rsa::Rsa; use openssl::sign::Signer; use sha3::{Digest, Keccak256}; use std::collections::HashMap; +use std::convert::TryInto; use ckb_chain_spec::consensus::{Consensus, ConsensusBuilder}; use ckb_crypto::secp::{Generator, Privkey, Pubkey}; @@ -32,6 +33,7 @@ use lazy_static::lazy_static; use rand::prelude::{thread_rng, ThreadRng}; use rand::seq::SliceRandom; use rand::Rng; +use rand::RngCore; use sparse_merkle_tree::default_store::DefaultStore; use sparse_merkle_tree::traits::Hasher; @@ -626,6 +628,18 @@ pub fn sign_tx_by_input_group( let message = if config.id.flags == IDENTITY_FLAGS_ETHEREUM { convert_keccak256_hash(&message) + } else if config.id.flags == IDENTITY_FLAGS_EOS { + assert!(config.eos.is_some()); + config.eos.as_ref().unwrap().convert_message(&message) + } else if config.id.flags == IDENTITY_FLAGS_TRON { + assert!(config.tron.is_some()); + config.tron.as_ref().unwrap().convert_message(&message) + } else if config.id.flags == IDENTITY_FLAGS_BITCOIN { + assert!(config.bitcoin.is_some()); + config.bitcoin.as_ref().unwrap().convert_message(&message) + } else if config.id.flags == IDENTITY_FLAGS_DOGECOIN { + assert!(config.dogecoin.is_some()); + config.dogecoin.as_ref().unwrap().convert_message(&message) } else { CkbH256::from(message) }; @@ -669,6 +683,48 @@ pub fn sign_tx_by_input_group( &identity, None, ) + } else if config.id.flags == IDENTITY_FLAGS_EOS { + let sig_bytes = config + .eos + .as_ref() + .unwrap() + .sign(&config.private_key, message); + gen_witness_lock( + sig_bytes, + config.use_rc, + config.use_rc_identity, + &proof_vec, + &identity, + None, + ) + } else if config.id.flags == IDENTITY_FLAGS_BITCOIN { + let sig_bytes = config + .bitcoin + .as_ref() + .unwrap() + .sign(&config.private_key, message); + gen_witness_lock( + sig_bytes, + config.use_rc, + config.use_rc_identity, + &proof_vec, + &identity, + None, + ) + } else if config.id.flags == IDENTITY_FLAGS_DOGECOIN { + let sig_bytes = config + .dogecoin + .as_ref() + .unwrap() + .sign(&config.private_key, message); + gen_witness_lock( + sig_bytes, + config.use_rc, + config.use_rc_identity, + &proof_vec, + &identity, + None, + ) } else { let sig = config.private_key.sign_recoverable(&message).expect("sign"); let sig_bytes = Bytes::from(sig.serialize()); @@ -971,6 +1027,10 @@ pub fn debug_printer(script: &Byte32, msg: &str) { pub const IDENTITY_FLAGS_PUBKEY_HASH: u8 = 0; pub const IDENTITY_FLAGS_ETHEREUM: u8 = 1; +pub const IDENTITY_FLAGS_EOS: u8 = 2; +pub const IDENTITY_FLAGS_TRON: u8 = 3; +pub const IDENTITY_FLAGS_BITCOIN: u8 = 4; +pub const IDENTITY_FLAGS_DOGECOIN: u8 = 5; pub const IDENTITY_FLAGS_MULTISIG: u8 = 6; pub const IDENTITY_FLAGS_OWNER_LOCK: u8 = 0xFC; @@ -1086,6 +1146,187 @@ impl Default for MultisigTestConfig { } } +pub const BITCOIN_V_TYPE_P2PKHUNCOMPRESSED: u8 = 27; +pub const BITCOIN_V_TYPE_P2PKHCOMPRESSED: u8 = 31; +pub const BITCOIN_V_TYPE_SEGWITP2SH: u8 = 35; +pub const BITCOIN_V_TYPE_SEGWITBECH32: u8 = 39; + +pub struct BitcoinConfig { + pub sign_vtype: u8, + pub pubkey_err: bool, +} + +impl Default for BitcoinConfig { + fn default() -> Self { + Self { + sign_vtype: BITCOIN_V_TYPE_P2PKHCOMPRESSED, + pubkey_err: false, + } + } +} + +impl BitcoinConfig { + pub fn get_pubkey_hash(&self, pubkey: &Pubkey) -> [u8; 20] { + if self.pubkey_err { + let mut r = [0u8; 20]; + thread_rng().fill_bytes(&mut r); + return r; + } + match self.sign_vtype { + BITCOIN_V_TYPE_P2PKHUNCOMPRESSED => { + let mut pk_data = Vec::::new(); + pk_data.resize(65, 0); + pk_data[0] = 4; + pk_data[1..].copy_from_slice(pubkey.as_bytes()); + + bitcoin_hash160(&pk_data) + } + BITCOIN_V_TYPE_P2PKHCOMPRESSED => bitcoin_hash160(&pubkey.serialize()), + BITCOIN_V_TYPE_SEGWITP2SH => { + // Ripemd160(Sha256([00, 20, Ripemd160(Sha256(Compressed Public key))])) + + let mut buf = Vec::::new(); + buf.resize(22, 0); + buf[0] = 0; + buf[1] = 20; + buf[2..].copy_from_slice(&bitcoin_hash160(&pubkey.serialize())); + bitcoin_hash160(&buf) + } + BITCOIN_V_TYPE_SEGWITBECH32 => bitcoin_hash160(&pubkey.serialize()), + _ => { + panic!("unknow sign_vtype") + } + } + } + + pub fn convert_message(&self, message: &[u8; 32]) -> CkbH256 { + let message_magic = b"\x18Bitcoin Signed Message:\n\x40"; + let msg_hex = hex::encode(message); + assert_eq!(msg_hex.len(), 64); + + let mut temp2: BytesMut = BytesMut::with_capacity(message_magic.len() + msg_hex.len()); + temp2.put(Bytes::from(message_magic.to_vec())); + temp2.put(Bytes::from(hex::encode(message))); + + let msg = calculate_sha256(&temp2.to_vec()); + let msg = calculate_sha256(&msg); + + CkbH256::from(msg) + } + + pub fn sign(&self, privkey: &Privkey, message: CkbH256) -> Bytes { + let sign = privkey + .sign_recoverable(&message) + .expect("sign secp256k1") + .serialize(); + let recid = sign[64]; + + let mark = recid + self.sign_vtype; + + let mut ret = BytesMut::with_capacity(65); + ret.put_u8(mark); + ret.put(&sign[0..64]); + Bytes::from(ret) + } +} + +#[derive(Default)] +pub struct DogecoinConfig(pub BitcoinConfig); + +impl DogecoinConfig { + pub fn get_pubkey_hash(&self, pubkey: &Pubkey) -> [u8; 20] { + self.0.get_pubkey_hash(pubkey) + } + + pub fn convert_message(&self, message: &[u8; 32]) -> CkbH256 { + let message_magic = b"\x19Dogecoin Signed Message:\n\x40"; + let msg_hex = hex::encode(message); + assert_eq!(msg_hex.len(), 64); + + let mut temp2: BytesMut = BytesMut::with_capacity(message_magic.len() + msg_hex.len()); + temp2.put(Bytes::from(message_magic.to_vec())); + temp2.put(Bytes::from(hex::encode(message))); + + let msg = calculate_sha256(&temp2.to_vec()); + let msg = calculate_sha256(&msg); + + CkbH256::from(msg) + } + + pub fn sign(&self, privkey: &Privkey, message: CkbH256) -> Bytes { + self.0.sign(privkey, message) + } +} + +#[derive(Default)] +pub struct EOSConfig(pub BitcoinConfig); + +impl EOSConfig { + pub fn get_pubkey_hash(&self, pubkey: &Pubkey) -> [u8; 20] { + if self.0.pubkey_err { + let mut r = [0u8; 20]; + thread_rng().fill_bytes(&mut r); + return r; + } + // EOS support + let buf = match self.0.sign_vtype { + BITCOIN_V_TYPE_P2PKHUNCOMPRESSED => { + let mut temp: BytesMut = BytesMut::with_capacity(65); + temp.put_u8(4); + temp.put(Bytes::from(pubkey.as_bytes().to_vec())); + temp.freeze().to_vec() + } + BITCOIN_V_TYPE_P2PKHCOMPRESSED => pubkey.serialize(), + _ => { + panic!("unsupport") + } + }; + + ckb_hash::blake2b_256(buf)[..20].try_into().unwrap() + } + + pub fn convert_message(&self, message: &[u8; 32]) -> CkbH256 { + CkbH256::from_slice(message).unwrap() + } + + pub fn sign(&self, privkey: &Privkey, message: CkbH256) -> Bytes { + self.0.sign(privkey, message) + } +} + +#[derive(Default)] +pub struct TronConfig { + pub pubkey_err: bool, +} + +impl TronConfig { + pub fn get_pubkey_hash(&self, pubkey: &Pubkey) -> [u8; 20] { + if self.pubkey_err { + let mut r = [0u8; 20]; + thread_rng().fill_bytes(&mut r); + return r; + } + + let pubkey = pubkey.as_bytes(); + + let mut hasher = Keccak256::new(); + hasher.update(&pubkey.to_vec()); + let r = hasher.finalize().as_slice().to_vec(); + + r[12..].try_into().unwrap() + } + + pub fn convert_message(&self, message: &[u8; 32]) -> CkbH256 { + let eth_prefix: &[u8; 24] = b"\x19TRON Signed Message:\n32"; + let mut hasher = Keccak256::new(); + hasher.update(eth_prefix); + hasher.update(message); + let r = hasher.finalize(); + let rr = CkbH256::from_slice(r.as_slice()).expect("convert_keccak256_hash"); + rr + } +} + pub struct TestConfig { pub id: Identity, pub acp_config: Option<(u8, u8)>, @@ -1125,6 +1366,12 @@ pub struct TestConfig { pub running_script: Script, pub leading_witness_count: usize, + + // Bitcoin + pub eos: Option, + pub tron: Option, + pub bitcoin: Option, + pub dogecoin: Option, } #[derive(Copy, Clone, PartialEq)] @@ -1161,7 +1408,7 @@ const SUPPLY_MASK: u8 = 8; impl TestConfig { pub fn new(flags: u8, use_rc: bool) -> TestConfig { - let private_key = Generator::random_privkey(); + let private_key: Privkey = Generator::random_privkey(); let pubkey = private_key.pubkey().expect("pubkey"); let pubkey_hash = blake160(&pubkey.serialize()); @@ -1223,6 +1470,11 @@ impl TestConfig { info_cell: Default::default(), running_script: Default::default(), leading_witness_count: 0, + + eos: None, + tron: None, + bitcoin: None, + dogecoin: None, } } @@ -1264,6 +1516,30 @@ impl TestConfig { self.use_rc_identity = used; } + pub fn set_eos(&mut self, eos: EOSConfig) { + let pkhash = eos.get_pubkey_hash(&self.pubkey); + self.eos = Some(eos); + self.id.blake160 = Bytes::from(pkhash.to_vec()); + } + + pub fn set_tron(&mut self, tron: TronConfig) { + let pkhash = tron.get_pubkey_hash(&self.pubkey); + self.tron = Some(tron); + self.id.blake160 = Bytes::from(pkhash.to_vec()); + } + + pub fn set_bitcoin(&mut self, btc: BitcoinConfig) { + let pkhash = btc.get_pubkey_hash(&self.pubkey); + self.bitcoin = Some(btc); + self.id.blake160 = Bytes::from(pkhash.to_vec()); + } + + pub fn set_dogecoin(&mut self, dogecoin: DogecoinConfig) { + let pkhash = dogecoin.get_pubkey_hash(&self.pubkey); + self.dogecoin = Some(dogecoin); + self.id.blake160 = Bytes::from(pkhash.to_vec()); + } + pub fn gen_args(&self) -> Bytes { let mut bytes = BytesMut::with_capacity(128); let mut omni_lock_flags: u8 = 0; @@ -1687,3 +1963,25 @@ pub fn gen_tx_env() -> TxVerifyEnv { .build(); TxVerifyEnv::new_commit(&header) } + +pub fn calculate_sha256(buf: &[u8]) -> [u8; 32] { + use sha2::{Digest, Sha256}; + + let mut c = Sha256::new(); + c.update(buf); + c.finalize().into() +} + +pub fn calculate_ripemd160(buf: &[u8]) -> [u8; 20] { + use ripemd::{Digest, Ripemd160}; + + let mut hasher = Ripemd160::new(); + hasher.update(buf); + let buf = hasher.finalize()[..].to_vec(); + + buf.try_into().unwrap() +} + +pub fn bitcoin_hash160(buf: &[u8]) -> [u8; 20] { + calculate_ripemd160(&calculate_sha256(buf)) +} diff --git a/tests/omni_lock_rust/tests/test_omni_lock.rs b/tests/omni_lock_rust/tests/test_omni_lock.rs index 21a96c2..70fe680 100644 --- a/tests/omni_lock_rust/tests/test_omni_lock.rs +++ b/tests/omni_lock_rust/tests/test_omni_lock.rs @@ -480,7 +480,7 @@ fn test_iso9796_2_batch_via_dl_unlock_failed() { TransactionScriptsVerifier::new(&resolved_tx, &consensus, &data_loader, &tx_env); verifier.set_debug_printer(debug_printer); let verify_result = verifier.verify(MAX_CYCLES); - assert_script_error(verify_result.unwrap_err(), ERROR_ISO97962_INVALID_ARG9); + assert!(verify_result.is_err()); } #[test] @@ -502,3 +502,209 @@ fn test_eth_unlock() { let verify_result = verifier.verify(MAX_CYCLES); verify_result.expect("pass verification"); } + +fn test_btc_success(vtype: u8) { + let mut data_loader = DummyDataLoader::new(); + + let mut config = TestConfig::new(IDENTITY_FLAGS_BITCOIN, false); + config.set_bitcoin(BitcoinConfig { + sign_vtype: vtype, + 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 consensus = misc::gen_consensus(); + let tx_env = misc::gen_tx_env(); + let mut verifier = + TransactionScriptsVerifier::new(&resolved_tx, &consensus, &data_loader, &tx_env); + + verifier.set_debug_printer(debug_printer); + let verify_result = verifier.verify(MAX_CYCLES); + verify_result.expect("pass verification"); +} + +fn test_btc_err_pubkey(vtype: u8) { + let mut data_loader = DummyDataLoader::new(); + + let mut config = TestConfig::new(IDENTITY_FLAGS_BITCOIN, false); + config.set_bitcoin(BitcoinConfig { + sign_vtype: vtype, + pubkey_err: true, + }); + + 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 consensus = misc::gen_consensus(); + let tx_env = misc::gen_tx_env(); + let mut verifier = + TransactionScriptsVerifier::new(&resolved_tx, &consensus, &data_loader, &tx_env); + + verifier.set_debug_printer(debug_printer); + let verify_result = verifier.verify(MAX_CYCLES); + assert!(verify_result.is_err()); + assert_script_error(verify_result.unwrap_err(), ERROR_PUBKEY_BLAKE160_HASH); +} + +fn test_btc(vtype: u8) { + test_btc_success(vtype); + test_btc_err_pubkey(vtype); +} + +#[test] +fn test_btc_unlock() { + test_btc(BITCOIN_V_TYPE_P2PKHUNCOMPRESSED); + test_btc(BITCOIN_V_TYPE_P2PKHCOMPRESSED); + test_btc(BITCOIN_V_TYPE_SEGWITP2SH); + test_btc(BITCOIN_V_TYPE_SEGWITBECH32); +} + +#[test] +fn test_dogecoin_unlock() { + let mut data_loader = DummyDataLoader::new(); + + let mut config = TestConfig::new(IDENTITY_FLAGS_DOGECOIN, false); + config.set_dogecoin(DogecoinConfig::default()); + + 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 consensus = misc::gen_consensus(); + let tx_env = misc::gen_tx_env(); + let mut verifier = + TransactionScriptsVerifier::new(&resolved_tx, &consensus, &data_loader, &tx_env); + + verifier.set_debug_printer(debug_printer); + let verify_result = verifier.verify(MAX_CYCLES); + verify_result.expect("pass verification"); +} + +#[test] +fn test_dogecoin_err_pubkey() { + let mut data_loader = DummyDataLoader::new(); + + let mut config = TestConfig::new(IDENTITY_FLAGS_DOGECOIN, false); + let mut dogecoin = DogecoinConfig::default(); + dogecoin.0.pubkey_err = true; + config.set_dogecoin(dogecoin); + + 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 consensus = misc::gen_consensus(); + let tx_env = misc::gen_tx_env(); + let mut verifier = + TransactionScriptsVerifier::new(&resolved_tx, &consensus, &data_loader, &tx_env); + + verifier.set_debug_printer(debug_printer); + let verify_result = verifier.verify(MAX_CYCLES); + assert!(verify_result.is_err()) +} + +fn test_eos_success(vtype: u8) { + let mut data_loader = DummyDataLoader::new(); + + let mut config = TestConfig::new(IDENTITY_FLAGS_EOS, false); + let mut eos = EOSConfig::default(); + eos.0.sign_vtype = vtype; + config.set_eos(EOSConfig::default()); + + let tx: ckb_types::core::TransactionView = 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 consensus = misc::gen_consensus(); + let tx_env = misc::gen_tx_env(); + let mut verifier = + TransactionScriptsVerifier::new(&resolved_tx, &consensus, &data_loader, &tx_env); + + verifier.set_debug_printer(debug_printer); + let verify_result = verifier.verify(MAX_CYCLES); + verify_result.expect("pass verification"); +} + +fn test_eos_err_pubkey(vtype: u8) { + let mut data_loader = DummyDataLoader::new(); + + let mut config = TestConfig::new(IDENTITY_FLAGS_EOS, false); + let mut eos = EOSConfig::default(); + eos.0.sign_vtype = vtype; + eos.0.pubkey_err = true; + config.set_eos(eos); + + let tx: ckb_types::core::TransactionView = 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 consensus = misc::gen_consensus(); + let tx_env = misc::gen_tx_env(); + let mut verifier = + TransactionScriptsVerifier::new(&resolved_tx, &consensus, &data_loader, &tx_env); + + verifier.set_debug_printer(debug_printer); + let verify_result = verifier.verify(MAX_CYCLES); + assert!(verify_result.is_err()); + assert_script_error(verify_result.unwrap_err(), ERROR_PUBKEY_BLAKE160_HASH); +} + +fn test_eos(vtype: u8) { + test_eos_success(vtype); + test_eos_err_pubkey(vtype) +} + +#[test] +fn test_eos_unlock() { + test_eos(BITCOIN_V_TYPE_P2PKHCOMPRESSED); + test_eos(BITCOIN_V_TYPE_P2PKHUNCOMPRESSED); +} + +#[test] +fn test_tron_unlock() { + let mut data_loader = DummyDataLoader::new(); + + let mut config = TestConfig::new(IDENTITY_FLAGS_TRON, false); + config.set_tron(TronConfig::default()); + + 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 consensus = misc::gen_consensus(); + let tx_env = misc::gen_tx_env(); + let mut verifier = + TransactionScriptsVerifier::new(&resolved_tx, &consensus, &data_loader, &tx_env); + + verifier.set_debug_printer(debug_printer); + let verify_result = verifier.verify(MAX_CYCLES); + verify_result.expect("pass verification"); +} + +#[test] +fn test_tron_err_pubkey() { + let mut data_loader = DummyDataLoader::new(); + + let mut config = TestConfig::new(IDENTITY_FLAGS_TRON, false); + let mut tron = TronConfig::default(); + tron.pubkey_err = true; + config.set_tron(tron); + + 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 consensus = misc::gen_consensus(); + let tx_env = misc::gen_tx_env(); + let mut verifier = + TransactionScriptsVerifier::new(&resolved_tx, &consensus, &data_loader, &tx_env); + + verifier.set_debug_printer(debug_printer); + let verify_result = verifier.verify(MAX_CYCLES); + assert!(verify_result.is_err()); + assert_script_error(verify_result.unwrap_err(), ERROR_PUBKEY_BLAKE160_HASH); +}