Getting Issue when sign_with_schnorr

I am getting error when calling sign_with_schnorr
(variant {Err="schnorr_public_key failed failed to decode canister response as (sign_backend::steller_lock::ManagementCanisterSchnorrPublicKeyReply,): Fail to decode argument 0 from table0 to record { public_key : blob; chain_code : blob }"})

Can you provide code to this sign_backend and definition of ManagementCanisterSchnorrPublicKeyReply?

1 Like
struct ManagementCanisterSchnorrPublicKeyReply {
    pub public_key: Vec<u8>,
    pub chain_code: Vec<u8>,
}```
using this 
```    let request: ManagementCanisterSignatureRequest = ManagementCanisterSignatureRequest {
        message:message_hash.as_bytes().to_vec(),
        derivation_path: vec![ic_cdk::api::caller().as_slice().to_vec()],
        key_id: SchnorrKeyId {
            algorithm: SchnorrAlgorithm::Ed25519,
            name: String::from("dfx_test_key"),
        },
    };

    ic_cdk::println!("request {:?}",request);
    let (res,): (ManagementCanisterSchnorrPublicKeyReply,) =  ic_cdk::api::call::call_with_payment(
        Principal::management_canister(),
        "sign_with_schnorr",
        (request,),
        25_000_000_000,
    )
    .await // Add the await keyword
    .map_err(|e| format!("schnorr_public_key failed {}", e.1))?;

SInce you call sign_with_schnorr, why are you expecting public key as a reply?

sign_with_schnorr has the following signature in candid:

type sign_with_schnorr_result = record {
    signature : blob;
};
sign_with_schnorr : (sign_with_schnorr_args) -> (sign_with_schnorr_result);

Can you please share the all the candid related to this ? like sign_with_schnorr_result and schnorr_public_key ?
can you share candid for schnorr_public_key and all management canister ?

2 Likes

Can you share the candid for all the management canister function ?

The above document links to this file (but it could change in future updates)
https://internetcomputer.org/assets/files/ic-ffcd514302057d6a64c13d6683d82757.did

1 Like

For this when , I am trying to call sign_with_schnorr .
ICP takes the different node for each time as I call it , so there are always some time it uses different node for signing the transaction .
below is how I am getting public key

        canister_id: None,
        derivation_path: vec![ic_cdk::api::caller().as_slice().to_vec()],
        key_id: SchnorrKeyId {
            algorithm: SchnorrAlgorithm::Ed25519,
            name: String::from("dfx_test_key"),
        },
    };
    ic_cdk::println!("Request for generate_keypair_stellar: {:?}", request);

    // Send the request and get the raw response
    let raw_response: Vec<u8> = ic_cdk::api::call::call_raw(
        Principal::management_canister(),
        "schnorr_public_key",
        Encode!(&request).unwrap(), // Encode the request
        25_000_000_000,
    )
    .await
    .map_err(|e| format!("schnorr_public_key failed {}", e.1))?;

if you are looking for latest api with BIP341 support, use this


/// Represents the BIP341 aux argument of the sign_with_schnorr API.
/// ```text
/// (record {
///   merkle_root_hash: blob;
/// })
/// ```
#[derive(Eq, PartialEq, Debug, CandidType, Deserialize)]
pub struct SignWithBip341Aux {
    pub merkle_root_hash: ByteBuf,
}

/// Represents the aux argument of the sign_with_schnorr API.
/// ```text
/// (variant {
///    bip341: record {
///      merkle_root_hash: blob;
///   }
/// })
/// ```
#[derive(Eq, PartialEq, Debug, CandidType, Deserialize)]
pub enum SignWithSchnorrAux {
    #[serde(rename = "bip341")]
    Bip341(SignWithBip341Aux),
}

/// Represents the argument of the sign_with_schnorr API.
/// ```text
/// (record {
///   message : blob;
///   derivation_path : vec blob;
///   key_id : schnorr_key_id;
///   aux: opt schnorr_aux;
/// })
/// ```
#[derive(Eq, PartialEq, Debug, CandidType, Deserialize)]
pub struct SignWithSchnorrArgs {
    #[serde(with = "serde_bytes")]
    pub message: Vec<u8>,
    pub derivation_path: Vec<Vec<u8>>,
    pub key_id: SchnorrKeyId,
    pub aux: Option<SignWithSchnorrAux>,
}

I don’t quite understand what you meant by “it uses different node”.

Do you mean the signature you get each time is different? This is by design. Signing the same message may give different signatures, but they are all valid signatures.

Or do you mean you get different public key each time when using the same derivation path? This cannot happen unless you have restarted dfx using dfx start --clean.

yes , getting different keys…
I have also cleaned it but same issue it also came when sign_with_ecdsa I used.

      key_id: EcdsaKeyId {
          curve: EcdsaCurve::Secp256k1,
          name: ecdsa_key.to_string(),
      },
      ..Default::default()
  };```
this is how I am using for ecdsa key pair , getting same public key ...but when I use without    ..Default::default() getting different public key in raw txn

Could you provide the argument that uses in schnorr_public_key and sign_with_schnorr like we use EcdsaPublicKeyArgument for ecdsa public key genration.

let request = EcdsaPublicKeyArgument {
        key_id: EcdsaKeyId {
            curve: EcdsaCurve::Secp256k1,
            name: ecdsa_key.to_string(),
        },
        ..Default::default()
    };

and SignWithEcdsaArgument for

let (signature,) = sign_with_ecdsa(SignWithEcdsaArgument {
        message_hash: txhash,
        key_id: key_id(),
        ..Default::default()
    })
    .await
    .expect("Failed to generate signature");

When you use without Default::default(), what canister_id and derivation_path did you use?
The default for them is just None and Vec::new().

You will get different public key when you use a different canister_id or derivation_path.