diff --git a/tests/omni_lock_rust/Cargo.lock b/tests/omni_lock_rust/Cargo.lock index feb3908..3cae86c 100644 --- a/tests/omni_lock_rust/Cargo.lock +++ b/tests/omni_lock_rust/Cargo.lock @@ -133,6 +133,15 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8d696c370c750c948ada61c69a0ee2cbbb9c50b1019ddb86d9317157a99c2cae" +[[package]] +name = "bs58" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf88ba1141d185c399bee5288d850d63b8369520c1eafc32a0430b5b6c287bf4" +dependencies = [ + "tinyvec", +] + [[package]] name = "byteorder" version = "1.5.0" @@ -1126,6 +1135,7 @@ version = "0.1.0" dependencies = [ "blake2b-ref", "blake2b-rs 0.1.5", + "bs58", "ckb-chain-spec", "ckb-crypto", "ckb-error", @@ -1796,6 +1806,21 @@ dependencies = [ "syn 2.0.48", ] +[[package]] +name = "tinyvec" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + [[package]] name = "tokio" version = "1.35.1" diff --git a/tests/omni_lock_rust/Cargo.toml b/tests/omni_lock_rust/Cargo.toml index 91a1981..6d20c47 100644 --- a/tests/omni_lock_rust/Cargo.toml +++ b/tests/omni_lock_rust/Cargo.toml @@ -31,4 +31,5 @@ molecule = "0.7.5" blake2b-ref = "0.3.1" serde = "1.0" serde_json = "1.0" -ed25519-dalek = "2.1.1" \ No newline at end of file +ed25519-dalek = "2.1.1" +bs58 = "0.5.1" diff --git a/tests/omni_lock_rust/tests/misc.rs b/tests/omni_lock_rust/tests/misc.rs index c95653a..dd1be60 100644 --- a/tests/omni_lock_rust/tests/misc.rs +++ b/tests/omni_lock_rust/tests/misc.rs @@ -592,26 +592,38 @@ pub fn sign_tx_by_input_group( let sig = config.multisig.sign(&message.into()); gen_witness_lock(sig, config.use_rc, config.use_rc_identity, &proof_vec, &identity, None) } else if config.id.flags == IDENTITY_FLAGS_SOLANA { - // name conflicted - use ed25519_dalek::Signer; - // solana has different signing process and algorithm - let signing_key = SigningKey::from_bytes(&config.solana_secret_key); - let msg = String::from("CKB transaction: 0x") + &hex::encode(message); - println!("message to be signed by ed25519: {}", msg); - let sig = signing_key.sign(msg.as_bytes()); - let verifying_key = signing_key.verifying_key(); - - let mut sig_plus_pubkey = sig.to_vec(); - sig_plus_pubkey.extend(verifying_key.to_bytes()); - let sig_plus_pubkey: Bytes = sig_plus_pubkey.into(); - gen_witness_lock( - sig_plus_pubkey, - config.use_rc, - config.use_rc_identity, - &proof_vec, - &identity, - None, - ) + if let Some(sig) = config.solana_phantom_sig.clone() { + let sig_plus_pubkey: Bytes = sig.into(); + gen_witness_lock( + sig_plus_pubkey, + config.use_rc, + config.use_rc_identity, + &proof_vec, + &identity, + None, + ) + } else { + // name conflicted + use ed25519_dalek::Signer; + // solana has different signing process and algorithm + let signing_key = SigningKey::from_bytes(&config.solana_secret_key); + let msg = String::from("CKB transaction: 0x") + &hex::encode(message); + println!("message to be signed by ed25519: {}", msg); + let sig = signing_key.sign(msg.as_bytes()); + let verifying_key = signing_key.verifying_key(); + + let mut sig_plus_pubkey = sig.to_vec(); + sig_plus_pubkey.extend(verifying_key.to_bytes()); + let sig_plus_pubkey: Bytes = sig_plus_pubkey.into(); + gen_witness_lock( + sig_plus_pubkey, + config.use_rc, + config.use_rc_identity, + &proof_vec, + &identity, + None, + ) + } } else if use_chain_config(config.id.flags) { let sig_bytes = config.chain_config.as_ref().unwrap().sign(&config.private_key, message); println!("bitcoin sign(size: {}): {:02x?}", sig_bytes.len(), sig_bytes.to_vec()); @@ -1284,6 +1296,7 @@ pub struct TestConfig { pub custom_extension_witnesses_beginning: Option>, pub random_tx: bool, pub solana_secret_key: [u8; 32], + pub solana_phantom_sig: Option>, } #[derive(Copy, Clone, PartialEq)] @@ -1384,6 +1397,7 @@ impl TestConfig { custom_extension_witnesses_beginning: None, random_tx: true, solana_secret_key: [0u8; 32], + solana_phantom_sig: None, } } diff --git a/tests/omni_lock_rust/tests/test_omni_lock.rs b/tests/omni_lock_rust/tests/test_omni_lock.rs index fb5fc25..a71e59d 100644 --- a/tests/omni_lock_rust/tests/test_omni_lock.rs +++ b/tests/omni_lock_rust/tests/test_omni_lock.rs @@ -575,6 +575,58 @@ fn test_solana_unlock() { verify_result.expect("pass verification"); } +/// Steps to update this test case: +/// +/// 1. Install Phantom wallet from: [Phantom Wallet](https://phantom.app/) +/// 2. Create an account on the wallet and obtain the Solana address. Update it +/// to the variable `address`. +/// 3. Run `cargo test test_solana_phantom_wallet -- --nocapture`. Find the +/// message to sign, for example: +/// ``` +/// Message to be signed by ed25519: CKB transaction: +/// 0x761f6986168340c33dfe016c7274fc30b3339d6d29dacc594f93addc700704fe +/// ``` +/// 4. Sign the message using [Phantom's message signing functionality](https://docs.phantom.app/solana/signing-a-message), e.g.: +/// ``` +/// provider.signMessage(new TextEncoder().encode("CKB transaction: +/// 0x761f6986168340c33dfe016c7274fc30b3339d6d29dacc594f93addc700704fe"), +/// "utf8") +/// ``` +/// 5. Update the variable `sig` with the obtained signature. +/// +#[test] +fn test_solana_phantom_wallet() { + let mut data_loader = DummyDataLoader::new(); + let address = "FK577f9qN4jiUJkQoiXvjuCcwmwLmB3sWwzBzX3ij8wG"; + let mut sig = vec![ + 139, 30, 199, 50, 16, 72, 145, 222, 75, 218, 182, 90, 47, 14, 110, 181, 226, 204, 15, 118, 122, 239, 221, 181, + 120, 164, 215, 252, 0, 72, 232, 235, 80, 74, 74, 107, 48, 10, 90, 145, 212, 44, 198, 233, 76, 253, 51, 91, 235, + 252, 117, 77, 242, 40, 68, 155, 143, 28, 252, 98, 94, 179, 6, 0, + ]; + + let verifying_key = bs58::decode(address).into_vec().unwrap(); + sig.extend(verifying_key.clone()); + + let mut config = TestConfig::new(IDENTITY_FLAGS_SOLANA, false); + config.random_tx = false; + config.sig_len = 96; + + let blake160 = blake160(&verifying_key); + let auth = Identity { flags: IDENTITY_FLAGS_SOLANA, blake160 }; + config.id = auth; + assert_eq!(sig.len(), 96); + config.solana_phantom_sig = Some(sig); + + 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"); +} + // this test can fail during development // TODO: enable it when ready #[test]